blob: a437d9582af5c68c34e41d27d1d876c5239200d5 [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;
125
126public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
127 static final String TAG = "ActivityManager";
128 static final boolean DEBUG = false;
129 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
130 static final boolean DEBUG_SWITCH = localLOGV || false;
131 static final boolean DEBUG_TASKS = localLOGV || false;
132 static final boolean DEBUG_PAUSE = localLOGV || false;
133 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
134 static final boolean DEBUG_TRANSITION = localLOGV || false;
135 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700136 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 static final boolean DEBUG_SERVICE = localLOGV || false;
138 static final boolean DEBUG_VISBILITY = localLOGV || false;
139 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700140 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800141 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700143 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700144 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700145 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 static final boolean VALIDATE_TOKENS = false;
147 static final boolean SHOW_ACTIVITY_START_TIME = true;
148
149 // Control over CPU and battery monitoring.
150 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
151 static final boolean MONITOR_CPU_USAGE = true;
152 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
153 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
154 static final boolean MONITOR_THREAD_CPU_USAGE = false;
155
Dianne Hackborn1655be42009-05-08 14:29:01 -0700156 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700157 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 private static final String SYSTEM_SECURE = "ro.secure";
160
161 // This is the maximum number of application processes we would like
162 // to have running. Due to the asynchronous nature of things, we can
163 // temporarily go beyond this limit.
164 static final int MAX_PROCESSES = 2;
165
166 // Set to false to leave processes running indefinitely, relying on
167 // the kernel killing them as resources are required.
168 static final boolean ENFORCE_PROCESS_LIMIT = false;
169
170 // This is the maximum number of activities that we would like to have
171 // running at a given time.
172 static final int MAX_ACTIVITIES = 20;
173
174 // Maximum number of recent tasks that we can remember.
175 static final int MAX_RECENT_TASKS = 20;
176
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700177 // Amount of time after a call to stopAppSwitches() during which we will
178 // prevent further untrusted switches from happening.
179 static final long APP_SWITCH_DELAY_TIME = 5*1000;
180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 // How long until we reset a task when the user returns to it. Currently
182 // 30 minutes.
183 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
184
185 // Set to true to disable the icon that is shown while a new activity
186 // is being started.
187 static final boolean SHOW_APP_STARTING_ICON = true;
188
189 // How long we wait until giving up on the last activity to pause. This
190 // is short because it directly impacts the responsiveness of starting the
191 // next activity.
192 static final int PAUSE_TIMEOUT = 500;
193
194 /**
195 * How long we can hold the launch wake lock before giving up.
196 */
197 static final int LAUNCH_TIMEOUT = 10*1000;
198
199 // How long we wait for a launched process to attach to the activity manager
200 // before we decide it's never going to come up for real.
201 static final int PROC_START_TIMEOUT = 10*1000;
202
203 // How long we wait until giving up on the last activity telling us it
204 // is idle.
205 static final int IDLE_TIMEOUT = 10*1000;
206
207 // How long to wait after going idle before forcing apps to GC.
208 static final int GC_TIMEOUT = 5*1000;
209
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700210 // The minimum amount of time between successive GC requests for a process.
211 static final int GC_MIN_INTERVAL = 60*1000;
212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 // How long we wait until giving up on an activity telling us it has
214 // finished destroying itself.
215 static final int DESTROY_TIMEOUT = 10*1000;
216
217 // How long we allow a receiver to run before giving up on it.
218 static final int BROADCAST_TIMEOUT = 10*1000;
219
220 // How long we wait for a service to finish executing.
221 static final int SERVICE_TIMEOUT = 20*1000;
222
223 // How long a service needs to be running until restarting its process
224 // is no longer considered to be a relaunch of the service.
225 static final int SERVICE_RESTART_DURATION = 5*1000;
226
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700227 // How long a service needs to be running until it will start back at
228 // SERVICE_RESTART_DURATION after being killed.
229 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
230
231 // Multiplying factor to increase restart duration time by, for each time
232 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
233 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
234
235 // The minimum amount of time between restarting services that we allow.
236 // That is, when multiple services are restarting, we won't allow each
237 // to restart less than this amount of time from the last one.
238 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 // Maximum amount of time for there to be no activity on a service before
241 // we consider it non-essential and allow its process to go on the
242 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700243 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244
245 // How long we wait until we timeout on key dispatching.
246 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
247
248 // The minimum time we allow between crashes, for us to consider this
249 // application to be bad and stop and its services and reject broadcasts.
250 static final int MIN_CRASH_INTERVAL = 60*1000;
251
252 // How long we wait until we timeout on key dispatching during instrumentation.
253 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
254
255 // OOM adjustments for processes in various states:
256
257 // This is a process without anything currently running in it. Definitely
258 // the first to go! Value set in system/rootdir/init.rc on startup.
259 // This value is initalized in the constructor, careful when refering to
260 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800261 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262
263 // This is a process only hosting activities that are not visible,
264 // so it can be killed without any disruption. Value set in
265 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800266 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 static int HIDDEN_APP_MIN_ADJ;
268
The Android Open Source Project4df24232009-03-05 14:34:35 -0800269 // This is a process holding the home application -- we want to try
270 // avoiding killing it, even if it would normally be in the background,
271 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800272 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800273
Christopher Tate6fa95972009-06-05 18:43:55 -0700274 // This is a process currently hosting a backup operation. Killing it
275 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800276 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 // This is a process holding a secondary server -- killing it will not
279 // have much of an impact as far as the user is concerned. Value set in
280 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800281 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282
283 // This is a process only hosting activities that are visible to the
284 // user, so we'd prefer they don't disappear. Value set in
285 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
288 // This is the process running the current foreground app. We'd really
289 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800290 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
292 // This is a process running a core server, such as telephony. Definitely
293 // don't want to kill it, but doing so is not completely fatal.
294 static final int CORE_SERVER_ADJ = -12;
295
296 // The system process runs at the default adjustment.
297 static final int SYSTEM_ADJ = -16;
298
299 // Memory pages are 4K.
300 static final int PAGE_SIZE = 4*1024;
301
302 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800303 static final int EMPTY_APP_MEM;
304 static final int HIDDEN_APP_MEM;
305 static final int HOME_APP_MEM;
306 static final int BACKUP_APP_MEM;
307 static final int SECONDARY_SERVER_MEM;
308 static final int VISIBLE_APP_MEM;
309 static final int FOREGROUND_APP_MEM;
310
311 // The minimum number of hidden apps we want to be able to keep around,
312 // without empty apps being able to push them out of memory.
313 static final int MIN_HIDDEN_APPS = 2;
314
315 // We put empty content processes after any hidden processes that have
316 // been idle for less than 30 seconds.
317 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
318
319 // We put empty content processes after any hidden processes that have
320 // been idle for less than 60 seconds.
321 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
322
323 static {
324 // These values are set in system/rootdir/init.rc on startup.
325 FOREGROUND_APP_ADJ =
326 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
327 VISIBLE_APP_ADJ =
328 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
329 SECONDARY_SERVER_ADJ =
330 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
331 BACKUP_APP_ADJ =
332 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
333 HOME_APP_ADJ =
334 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
335 HIDDEN_APP_MIN_ADJ =
336 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
337 EMPTY_APP_ADJ =
338 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
339 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
340 FOREGROUND_APP_MEM =
341 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
342 VISIBLE_APP_MEM =
343 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
344 SECONDARY_SERVER_MEM =
345 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
346 BACKUP_APP_MEM =
347 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
348 HOME_APP_MEM =
349 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
350 HIDDEN_APP_MEM =
351 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
352 EMPTY_APP_MEM =
353 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355
Dan Egnor42471dd2010-01-07 17:25:22 -0800356 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357
358 static final String[] EMPTY_STRING_ARRAY = new String[0];
359
360 enum ActivityState {
361 INITIALIZING,
362 RESUMED,
363 PAUSING,
364 PAUSED,
365 STOPPING,
366 STOPPED,
367 FINISHING,
368 DESTROYING,
369 DESTROYED
370 }
371
372 /**
373 * The back history of all previous (and possibly still
374 * running) activities. It contains HistoryRecord objects.
375 */
376 final ArrayList mHistory = new ArrayList();
377
378 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700379 * Description of a request to start a new activity, which has been held
380 * due to app switches being disabled.
381 */
382 class PendingActivityLaunch {
383 HistoryRecord r;
384 HistoryRecord sourceRecord;
385 Uri[] grantedUriPermissions;
386 int grantedMode;
387 boolean onlyIfNeeded;
388 }
389
390 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
391 = new ArrayList<PendingActivityLaunch>();
392
393 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800394 * List of people waiting to find out about the next launched activity.
395 */
396 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
397 = new ArrayList<IActivityManager.WaitResult>();
398
399 /**
400 * List of people waiting to find out about the next visible activity.
401 */
402 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
403 = new ArrayList<IActivityManager.WaitResult>();
404
405 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 * List of all active broadcasts that are to be executed immediately
407 * (without waiting for another broadcast to finish). Currently this only
408 * contains broadcasts to registered receivers, to avoid spinning up
409 * a bunch of processes to execute IntentReceiver components.
410 */
411 final ArrayList<BroadcastRecord> mParallelBroadcasts
412 = new ArrayList<BroadcastRecord>();
413
414 /**
415 * List of all active broadcasts that are to be executed one at a time.
416 * The object at the top of the list is the currently activity broadcasts;
417 * those after it are waiting for the top to finish..
418 */
419 final ArrayList<BroadcastRecord> mOrderedBroadcasts
420 = new ArrayList<BroadcastRecord>();
421
422 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800423 * Historical data of past broadcasts, for debugging.
424 */
425 static final int MAX_BROADCAST_HISTORY = 100;
426 final BroadcastRecord[] mBroadcastHistory
427 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
428
429 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 * Set when we current have a BROADCAST_INTENT_MSG in flight.
431 */
432 boolean mBroadcastsScheduled = false;
433
434 /**
435 * Set to indicate whether to issue an onUserLeaving callback when a
436 * newly launched activity is being brought in front of us.
437 */
438 boolean mUserLeaving = false;
439
440 /**
441 * When we are in the process of pausing an activity, before starting the
442 * next one, this variable holds the activity that is currently being paused.
443 */
444 HistoryRecord mPausingActivity = null;
445
446 /**
447 * Current activity that is resumed, or null if there is none.
448 */
449 HistoryRecord mResumedActivity = null;
450
451 /**
452 * Activity we have told the window manager to have key focus.
453 */
454 HistoryRecord mFocusedActivity = null;
455
456 /**
457 * This is the last activity that we put into the paused state. This is
458 * used to determine if we need to do an activity transition while sleeping,
459 * when we normally hold the top activity paused.
460 */
461 HistoryRecord mLastPausedActivity = null;
462
463 /**
464 * List of activities that are waiting for a new activity
465 * to become visible before completing whatever operation they are
466 * supposed to do.
467 */
468 final ArrayList mWaitingVisibleActivities = new ArrayList();
469
470 /**
471 * List of activities that are ready to be stopped, but waiting
472 * for the next activity to settle down before doing so. It contains
473 * HistoryRecord objects.
474 */
475 final ArrayList<HistoryRecord> mStoppingActivities
476 = new ArrayList<HistoryRecord>();
477
478 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700479 * Animations that for the current transition have requested not to
480 * be considered for the transition animation.
481 */
482 final ArrayList<HistoryRecord> mNoAnimActivities
483 = new ArrayList<HistoryRecord>();
484
485 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 * List of intents that were used to start the most recent tasks.
487 */
488 final ArrayList<TaskRecord> mRecentTasks
489 = new ArrayList<TaskRecord>();
490
491 /**
492 * List of activities that are ready to be finished, but waiting
493 * for the previous activity to settle down before doing so. It contains
494 * HistoryRecord objects.
495 */
496 final ArrayList mFinishingActivities = new ArrayList();
497
498 /**
499 * All of the applications we currently have running organized by name.
500 * The keys are strings of the application package name (as
501 * returned by the package manager), and the keys are ApplicationRecord
502 * objects.
503 */
504 final ProcessMap<ProcessRecord> mProcessNames
505 = new ProcessMap<ProcessRecord>();
506
507 /**
508 * The last time that various processes have crashed.
509 */
510 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
511
512 /**
513 * Set of applications that we consider to be bad, and will reject
514 * incoming broadcasts from (which the user has no control over).
515 * Processes are added to this set when they have crashed twice within
516 * a minimum amount of time; they are removed from it when they are
517 * later restarted (hopefully due to some user action). The value is the
518 * time it was added to the list.
519 */
520 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
521
522 /**
523 * All of the processes we currently have running organized by pid.
524 * The keys are the pid running the application.
525 *
526 * <p>NOTE: This object is protected by its own lock, NOT the global
527 * activity manager lock!
528 */
529 final SparseArray<ProcessRecord> mPidsSelfLocked
530 = new SparseArray<ProcessRecord>();
531
532 /**
533 * All of the processes that have been forced to be foreground. The key
534 * is the pid of the caller who requested it (we hold a death
535 * link on it).
536 */
537 abstract class ForegroundToken implements IBinder.DeathRecipient {
538 int pid;
539 IBinder token;
540 }
541 final SparseArray<ForegroundToken> mForegroundProcesses
542 = new SparseArray<ForegroundToken>();
543
544 /**
545 * List of records for processes that someone had tried to start before the
546 * system was ready. We don't start them at that point, but ensure they
547 * are started by the time booting is complete.
548 */
549 final ArrayList<ProcessRecord> mProcessesOnHold
550 = new ArrayList<ProcessRecord>();
551
552 /**
553 * List of records for processes that we have started and are waiting
554 * for them to call back. This is really only needed when running in
555 * single processes mode, in which case we do not have a unique pid for
556 * each process.
557 */
558 final ArrayList<ProcessRecord> mStartingProcesses
559 = new ArrayList<ProcessRecord>();
560
561 /**
562 * List of persistent applications that are in the process
563 * of being started.
564 */
565 final ArrayList<ProcessRecord> mPersistentStartingProcesses
566 = new ArrayList<ProcessRecord>();
567
568 /**
569 * Processes that are being forcibly torn down.
570 */
571 final ArrayList<ProcessRecord> mRemovedProcesses
572 = new ArrayList<ProcessRecord>();
573
574 /**
575 * List of running applications, sorted by recent usage.
576 * The first entry in the list is the least recently used.
577 * It contains ApplicationRecord objects. This list does NOT include
578 * any persistent application records (since we never want to exit them).
579 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800580 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 = new ArrayList<ProcessRecord>();
582
583 /**
584 * List of processes that should gc as soon as things are idle.
585 */
586 final ArrayList<ProcessRecord> mProcessesToGc
587 = new ArrayList<ProcessRecord>();
588
589 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800590 * This is the process holding what we currently consider to be
591 * the "home" activity.
592 */
593 private ProcessRecord mHomeProcess;
594
595 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 * List of running activities, sorted by recent usage.
597 * The first entry in the list is the least recently used.
598 * It contains HistoryRecord objects.
599 */
600 private final ArrayList mLRUActivities = new ArrayList();
601
602 /**
603 * Set of PendingResultRecord objects that are currently active.
604 */
605 final HashSet mPendingResultRecords = new HashSet();
606
607 /**
608 * Set of IntentSenderRecord objects that are currently active.
609 */
610 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
611 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
612
613 /**
614 * Intent broadcast that we have tried to start, but are
615 * waiting for its application's process to be created. We only
616 * need one (instead of a list) because we always process broadcasts
617 * one at a time, so no others can be started while waiting for this
618 * one.
619 */
620 BroadcastRecord mPendingBroadcast = null;
621
622 /**
623 * Keeps track of all IIntentReceivers that have been registered for
624 * broadcasts. Hash keys are the receiver IBinder, hash value is
625 * a ReceiverList.
626 */
627 final HashMap mRegisteredReceivers = new HashMap();
628
629 /**
630 * Resolver for broadcast intents to registered receivers.
631 * Holds BroadcastFilter (subclass of IntentFilter).
632 */
633 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
634 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
635 @Override
636 protected boolean allowFilterResult(
637 BroadcastFilter filter, List<BroadcastFilter> dest) {
638 IBinder target = filter.receiverList.receiver.asBinder();
639 for (int i=dest.size()-1; i>=0; i--) {
640 if (dest.get(i).receiverList.receiver.asBinder() == target) {
641 return false;
642 }
643 }
644 return true;
645 }
646 };
647
648 /**
649 * State of all active sticky broadcasts. Keys are the action of the
650 * sticky Intent, values are an ArrayList of all broadcasted intents with
651 * that action (which should usually be one).
652 */
653 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
654 new HashMap<String, ArrayList<Intent>>();
655
656 /**
657 * All currently running services.
658 */
659 final HashMap<ComponentName, ServiceRecord> mServices =
660 new HashMap<ComponentName, ServiceRecord>();
661
662 /**
663 * All currently running services indexed by the Intent used to start them.
664 */
665 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
666 new HashMap<Intent.FilterComparison, ServiceRecord>();
667
668 /**
669 * All currently bound service connections. Keys are the IBinder of
670 * the client's IServiceConnection.
671 */
672 final HashMap<IBinder, ConnectionRecord> mServiceConnections
673 = new HashMap<IBinder, ConnectionRecord>();
674
675 /**
676 * List of services that we have been asked to start,
677 * but haven't yet been able to. It is used to hold start requests
678 * while waiting for their corresponding application thread to get
679 * going.
680 */
681 final ArrayList<ServiceRecord> mPendingServices
682 = new ArrayList<ServiceRecord>();
683
684 /**
685 * List of services that are scheduled to restart following a crash.
686 */
687 final ArrayList<ServiceRecord> mRestartingServices
688 = new ArrayList<ServiceRecord>();
689
690 /**
691 * List of services that are in the process of being stopped.
692 */
693 final ArrayList<ServiceRecord> mStoppingServices
694 = new ArrayList<ServiceRecord>();
695
696 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700697 * Backup/restore process management
698 */
699 String mBackupAppName = null;
700 BackupRecord mBackupTarget = null;
701
702 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 * List of PendingThumbnailsRecord objects of clients who are still
704 * waiting to receive all of the thumbnails for a task.
705 */
706 final ArrayList mPendingThumbnails = new ArrayList();
707
708 /**
709 * List of HistoryRecord objects that have been finished and must
710 * still report back to a pending thumbnail receiver.
711 */
712 final ArrayList mCancelledThumbnails = new ArrayList();
713
714 /**
715 * All of the currently running global content providers. Keys are a
716 * string containing the provider name and values are a
717 * ContentProviderRecord object containing the data about it. Note
718 * that a single provider may be published under multiple names, so
719 * there may be multiple entries here for a single one in mProvidersByClass.
720 */
721 final HashMap mProvidersByName = new HashMap();
722
723 /**
724 * All of the currently running global content providers. Keys are a
725 * string containing the provider's implementation class and values are a
726 * ContentProviderRecord object containing the data about it.
727 */
728 final HashMap mProvidersByClass = new HashMap();
729
730 /**
731 * List of content providers who have clients waiting for them. The
732 * application is currently being launched and the provider will be
733 * removed from this list once it is published.
734 */
735 final ArrayList mLaunchingProviders = new ArrayList();
736
737 /**
738 * Global set of specific Uri permissions that have been granted.
739 */
740 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
741 = new SparseArray<HashMap<Uri, UriPermission>>();
742
743 /**
744 * Thread-local storage used to carry caller permissions over through
745 * indirect content-provider access.
746 * @see #ActivityManagerService.openContentUri()
747 */
748 private class Identity {
749 public int pid;
750 public int uid;
751
752 Identity(int _pid, int _uid) {
753 pid = _pid;
754 uid = _uid;
755 }
756 }
757 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
758
759 /**
760 * All information we have collected about the runtime performance of
761 * any user id that can impact battery performance.
762 */
763 final BatteryStatsService mBatteryStatsService;
764
765 /**
766 * information about component usage
767 */
768 final UsageStatsService mUsageStatsService;
769
770 /**
771 * Current configuration information. HistoryRecord objects are given
772 * a reference to this object to indicate which configuration they are
773 * currently running in, so this object must be kept immutable.
774 */
775 Configuration mConfiguration = new Configuration();
776
777 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800778 * Current sequencing integer of the configuration, for skipping old
779 * configurations.
780 */
781 int mConfigurationSeq = 0;
782
783 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700784 * Hardware-reported OpenGLES version.
785 */
786 final int GL_ES_VERSION;
787
788 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 * List of initialization arguments to pass to all processes when binding applications to them.
790 * For example, references to the commonly used services.
791 */
792 HashMap<String, IBinder> mAppBindArgs;
793
794 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700795 * Temporary to avoid allocations. Protected by main lock.
796 */
797 final StringBuilder mStringBuilder = new StringBuilder(256);
798
799 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 * Used to control how we initialize the service.
801 */
802 boolean mStartRunning = false;
803 ComponentName mTopComponent;
804 String mTopAction;
805 String mTopData;
806 boolean mSystemReady = false;
807 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700808 boolean mWaitingUpdate = false;
809 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810
811 Context mContext;
812
813 int mFactoryTest;
814
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700815 boolean mCheckedForSetup;
816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700818 * The time at which we will allow normal application switches again,
819 * after a call to {@link #stopAppSwitches()}.
820 */
821 long mAppSwitchesAllowedTime;
822
823 /**
824 * This is set to true after the first switch after mAppSwitchesAllowedTime
825 * is set; any switches after that will clear the time.
826 */
827 boolean mDidAppSwitch;
828
829 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 * Set while we are wanting to sleep, to prevent any
831 * activities from being started/resumed.
832 */
833 boolean mSleeping = false;
834
835 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700836 * Set if we are shutting down the system, similar to sleeping.
837 */
838 boolean mShuttingDown = false;
839
840 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 * Set when the system is going to sleep, until we have
842 * successfully paused the current activity and released our wake lock.
843 * At that point the system is allowed to actually sleep.
844 */
845 PowerManager.WakeLock mGoingToSleep;
846
847 /**
848 * We don't want to allow the device to go to sleep while in the process
849 * of launching an activity. This is primarily to allow alarm intent
850 * receivers to launch an activity and get that to run before the device
851 * goes back to sleep.
852 */
853 PowerManager.WakeLock mLaunchingActivity;
854
855 /**
856 * Task identifier that activities are currently being started
857 * in. Incremented each time a new task is created.
858 * todo: Replace this with a TokenSpace class that generates non-repeating
859 * integers that won't wrap.
860 */
861 int mCurTask = 1;
862
863 /**
864 * Current sequence id for oom_adj computation traversal.
865 */
866 int mAdjSeq = 0;
867
868 /**
869 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
870 * is set, indicating the user wants processes started in such a way
871 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
872 * running in each process (thus no pre-initialized process, etc).
873 */
874 boolean mSimpleProcessManagement = false;
875
876 /**
877 * System monitoring: number of processes that died since the last
878 * N procs were started.
879 */
880 int[] mProcDeaths = new int[20];
881
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700882 /**
883 * This is set if we had to do a delayed dexopt of an app before launching
884 * it, to increasing the ANR timeouts in that case.
885 */
886 boolean mDidDexOpt;
887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888 String mDebugApp = null;
889 boolean mWaitForDebugger = false;
890 boolean mDebugTransient = false;
891 String mOrigDebugApp = null;
892 boolean mOrigWaitForDebugger = false;
893 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700894 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700896 final RemoteCallbackList<IActivityWatcher> mWatchers
897 = new RemoteCallbackList<IActivityWatcher>();
898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 /**
900 * Callback of last caller to {@link #requestPss}.
901 */
902 Runnable mRequestPssCallback;
903
904 /**
905 * Remaining processes for which we are waiting results from the last
906 * call to {@link #requestPss}.
907 */
908 final ArrayList<ProcessRecord> mRequestPssList
909 = new ArrayList<ProcessRecord>();
910
911 /**
912 * Runtime statistics collection thread. This object's lock is used to
913 * protect all related state.
914 */
915 final Thread mProcessStatsThread;
916
917 /**
918 * Used to collect process stats when showing not responding dialog.
919 * Protected by mProcessStatsThread.
920 */
921 final ProcessStats mProcessStats = new ProcessStats(
922 MONITOR_THREAD_CPU_USAGE);
923 long mLastCpuTime = 0;
924 long mLastWriteTime = 0;
925
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700926 long mInitialStartTime = 0;
927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 /**
929 * Set to true after the system has finished booting.
930 */
931 boolean mBooted = false;
932
933 int mProcessLimit = 0;
934
935 WindowManagerService mWindowManager;
936
937 static ActivityManagerService mSelf;
938 static ActivityThread mSystemThread;
939
940 private final class AppDeathRecipient implements IBinder.DeathRecipient {
941 final ProcessRecord mApp;
942 final int mPid;
943 final IApplicationThread mAppThread;
944
945 AppDeathRecipient(ProcessRecord app, int pid,
946 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800947 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 TAG, "New death recipient " + this
949 + " for thread " + thread.asBinder());
950 mApp = app;
951 mPid = pid;
952 mAppThread = thread;
953 }
954
955 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800956 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 TAG, "Death received in " + this
958 + " for thread " + mAppThread.asBinder());
959 removeRequestedPss(mApp);
960 synchronized(ActivityManagerService.this) {
961 appDiedLocked(mApp, mPid, mAppThread);
962 }
963 }
964 }
965
966 static final int SHOW_ERROR_MSG = 1;
967 static final int SHOW_NOT_RESPONDING_MSG = 2;
968 static final int SHOW_FACTORY_ERROR_MSG = 3;
969 static final int UPDATE_CONFIGURATION_MSG = 4;
970 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
971 static final int WAIT_FOR_DEBUGGER_MSG = 6;
972 static final int BROADCAST_INTENT_MSG = 7;
973 static final int BROADCAST_TIMEOUT_MSG = 8;
974 static final int PAUSE_TIMEOUT_MSG = 9;
975 static final int IDLE_TIMEOUT_MSG = 10;
976 static final int IDLE_NOW_MSG = 11;
977 static final int SERVICE_TIMEOUT_MSG = 12;
978 static final int UPDATE_TIME_ZONE = 13;
979 static final int SHOW_UID_ERROR_MSG = 14;
980 static final int IM_FEELING_LUCKY_MSG = 15;
981 static final int LAUNCH_TIMEOUT_MSG = 16;
982 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 static final int RESUME_TOP_ACTIVITY_MSG = 19;
984 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700985 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700986 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800987 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988
989 AlertDialog mUidAlert;
990
991 final Handler mHandler = new Handler() {
992 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800993 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 //}
995
996 public void handleMessage(Message msg) {
997 switch (msg.what) {
998 case SHOW_ERROR_MSG: {
999 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 synchronized (ActivityManagerService.this) {
1001 ProcessRecord proc = (ProcessRecord)data.get("app");
1002 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001003 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 return;
1005 }
1006 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001007 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001008 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 d.show();
1010 proc.crashDialog = d;
1011 } else {
1012 // The device is asleep, so just pretend that the user
1013 // saw a crash dialog and hit "force quit".
1014 res.set(0);
1015 }
1016 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001017
1018 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 } break;
1020 case SHOW_NOT_RESPONDING_MSG: {
1021 synchronized (ActivityManagerService.this) {
1022 HashMap data = (HashMap) msg.obj;
1023 ProcessRecord proc = (ProcessRecord)data.get("app");
1024 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001025 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 return;
1027 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001028
1029 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1030 null, null, 0, null, null, null,
1031 false, false, MY_PID, Process.SYSTEM_UID);
1032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1034 mContext, proc, (HistoryRecord)data.get("activity"));
1035 d.show();
1036 proc.anrDialog = d;
1037 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001038
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001039 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 } break;
1041 case SHOW_FACTORY_ERROR_MSG: {
1042 Dialog d = new FactoryErrorDialog(
1043 mContext, msg.getData().getCharSequence("msg"));
1044 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001045 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 } break;
1047 case UPDATE_CONFIGURATION_MSG: {
1048 final ContentResolver resolver = mContext.getContentResolver();
1049 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1050 } break;
1051 case GC_BACKGROUND_PROCESSES_MSG: {
1052 synchronized (ActivityManagerService.this) {
1053 performAppGcsIfAppropriateLocked();
1054 }
1055 } break;
1056 case WAIT_FOR_DEBUGGER_MSG: {
1057 synchronized (ActivityManagerService.this) {
1058 ProcessRecord app = (ProcessRecord)msg.obj;
1059 if (msg.arg1 != 0) {
1060 if (!app.waitedForDebugger) {
1061 Dialog d = new AppWaitingForDebuggerDialog(
1062 ActivityManagerService.this,
1063 mContext, app);
1064 app.waitDialog = d;
1065 app.waitedForDebugger = true;
1066 d.show();
1067 }
1068 } else {
1069 if (app.waitDialog != null) {
1070 app.waitDialog.dismiss();
1071 app.waitDialog = null;
1072 }
1073 }
1074 }
1075 } break;
1076 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001077 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001078 TAG, "Received BROADCAST_INTENT_MSG");
1079 processNextBroadcast(true);
1080 } break;
1081 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001082 if (mDidDexOpt) {
1083 mDidDexOpt = false;
1084 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1085 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1086 return;
1087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 broadcastTimeout();
1089 } break;
1090 case PAUSE_TIMEOUT_MSG: {
1091 IBinder token = (IBinder)msg.obj;
1092 // We don't at this point know if the activity is fullscreen,
1093 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001094 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001095 activityPaused(token, null, true);
1096 } break;
1097 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001098 if (mDidDexOpt) {
1099 mDidDexOpt = false;
1100 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1101 nmsg.obj = msg.obj;
1102 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1103 return;
1104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 // We don't at this point know if the activity is fullscreen,
1106 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001107 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001108 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001109 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 } break;
1111 case DESTROY_TIMEOUT_MSG: {
1112 IBinder token = (IBinder)msg.obj;
1113 // We don't at this point know if the activity is fullscreen,
1114 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001115 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 activityDestroyed(token);
1117 } break;
1118 case IDLE_NOW_MSG: {
1119 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001120 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 } break;
1122 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001123 if (mDidDexOpt) {
1124 mDidDexOpt = false;
1125 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1126 nmsg.obj = msg.obj;
1127 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1128 return;
1129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 serviceTimeout((ProcessRecord)msg.obj);
1131 } break;
1132 case UPDATE_TIME_ZONE: {
1133 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001134 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1135 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 if (r.thread != null) {
1137 try {
1138 r.thread.updateTimeZone();
1139 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001140 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 }
1142 }
1143 }
1144 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001145 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 case SHOW_UID_ERROR_MSG: {
1147 // XXX This is a temporary dialog, no need to localize.
1148 AlertDialog d = new BaseErrorDialog(mContext);
1149 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1150 d.setCancelable(false);
1151 d.setTitle("System UIDs Inconsistent");
1152 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1153 d.setButton("I'm Feeling Lucky",
1154 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1155 mUidAlert = d;
1156 d.show();
1157 } break;
1158 case IM_FEELING_LUCKY_MSG: {
1159 if (mUidAlert != null) {
1160 mUidAlert.dismiss();
1161 mUidAlert = null;
1162 }
1163 } break;
1164 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001165 if (mDidDexOpt) {
1166 mDidDexOpt = false;
1167 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1168 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1169 return;
1170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171 synchronized (ActivityManagerService.this) {
1172 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001173 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 mLaunchingActivity.release();
1175 }
1176 }
1177 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 case RESUME_TOP_ACTIVITY_MSG: {
1179 synchronized (ActivityManagerService.this) {
1180 resumeTopActivityLocked(null);
1181 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001182 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001183 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001184 if (mDidDexOpt) {
1185 mDidDexOpt = false;
1186 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1187 nmsg.obj = msg.obj;
1188 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1189 return;
1190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 ProcessRecord app = (ProcessRecord)msg.obj;
1192 synchronized (ActivityManagerService.this) {
1193 processStartTimedOutLocked(app);
1194 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001195 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001196 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1197 synchronized (ActivityManagerService.this) {
1198 doPendingActivityLaunchesLocked(true);
1199 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001200 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001201 case KILL_APPLICATION_MSG: {
1202 synchronized (ActivityManagerService.this) {
1203 int uid = msg.arg1;
1204 boolean restart = (msg.arg2 == 1);
1205 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001206 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001207 }
1208 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001209 case FINALIZE_PENDING_INTENT_MSG: {
1210 ((PendingIntentRecord)msg.obj).completeFinalize();
1211 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 }
1213 }
1214 };
1215
1216 public static void setSystemProcess() {
1217 try {
1218 ActivityManagerService m = mSelf;
1219
1220 ServiceManager.addService("activity", m);
1221 ServiceManager.addService("meminfo", new MemBinder(m));
1222 if (MONITOR_CPU_USAGE) {
1223 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 ServiceManager.addService("permission", new PermissionController(m));
1226
1227 ApplicationInfo info =
1228 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001229 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001230 mSystemThread.installSystemApplicationInfo(info);
1231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 synchronized (mSelf) {
1233 ProcessRecord app = mSelf.newProcessRecordLocked(
1234 mSystemThread.getApplicationThread(), info,
1235 info.processName);
1236 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001237 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 app.maxAdj = SYSTEM_ADJ;
1239 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1240 synchronized (mSelf.mPidsSelfLocked) {
1241 mSelf.mPidsSelfLocked.put(app.pid, app);
1242 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001243 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 }
1245 } catch (PackageManager.NameNotFoundException e) {
1246 throw new RuntimeException(
1247 "Unable to find android system package", e);
1248 }
1249 }
1250
1251 public void setWindowManager(WindowManagerService wm) {
1252 mWindowManager = wm;
1253 }
1254
1255 public static final Context main(int factoryTest) {
1256 AThread thr = new AThread();
1257 thr.start();
1258
1259 synchronized (thr) {
1260 while (thr.mService == null) {
1261 try {
1262 thr.wait();
1263 } catch (InterruptedException e) {
1264 }
1265 }
1266 }
1267
1268 ActivityManagerService m = thr.mService;
1269 mSelf = m;
1270 ActivityThread at = ActivityThread.systemMain();
1271 mSystemThread = at;
1272 Context context = at.getSystemContext();
1273 m.mContext = context;
1274 m.mFactoryTest = factoryTest;
1275 PowerManager pm =
1276 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1277 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1278 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1279 m.mLaunchingActivity.setReferenceCounted(false);
1280
1281 m.mBatteryStatsService.publish(context);
1282 m.mUsageStatsService.publish(context);
1283
1284 synchronized (thr) {
1285 thr.mReady = true;
1286 thr.notifyAll();
1287 }
1288
1289 m.startRunning(null, null, null, null);
1290
1291 return context;
1292 }
1293
1294 public static ActivityManagerService self() {
1295 return mSelf;
1296 }
1297
1298 static class AThread extends Thread {
1299 ActivityManagerService mService;
1300 boolean mReady = false;
1301
1302 public AThread() {
1303 super("ActivityManager");
1304 }
1305
1306 public void run() {
1307 Looper.prepare();
1308
1309 android.os.Process.setThreadPriority(
1310 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1311
1312 ActivityManagerService m = new ActivityManagerService();
1313
1314 synchronized (this) {
1315 mService = m;
1316 notifyAll();
1317 }
1318
1319 synchronized (this) {
1320 while (!mReady) {
1321 try {
1322 wait();
1323 } catch (InterruptedException e) {
1324 }
1325 }
1326 }
1327
1328 Looper.loop();
1329 }
1330 }
1331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332 static class MemBinder extends Binder {
1333 ActivityManagerService mActivityManagerService;
1334 MemBinder(ActivityManagerService activityManagerService) {
1335 mActivityManagerService = activityManagerService;
1336 }
1337
1338 @Override
1339 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1340 ActivityManagerService service = mActivityManagerService;
1341 ArrayList<ProcessRecord> procs;
1342 synchronized (mActivityManagerService) {
1343 if (args != null && args.length > 0
1344 && args[0].charAt(0) != '-') {
1345 procs = new ArrayList<ProcessRecord>();
1346 int pid = -1;
1347 try {
1348 pid = Integer.parseInt(args[0]);
1349 } catch (NumberFormatException e) {
1350
1351 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001352 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1353 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354 if (proc.pid == pid) {
1355 procs.add(proc);
1356 } else if (proc.processName.equals(args[0])) {
1357 procs.add(proc);
1358 }
1359 }
1360 if (procs.size() <= 0) {
1361 pw.println("No process found for: " + args[0]);
1362 return;
1363 }
1364 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001365 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 }
1367 }
1368 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1369 }
1370 }
1371
1372 static class CpuBinder extends Binder {
1373 ActivityManagerService mActivityManagerService;
1374 CpuBinder(ActivityManagerService activityManagerService) {
1375 mActivityManagerService = activityManagerService;
1376 }
1377
1378 @Override
1379 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1380 synchronized (mActivityManagerService.mProcessStatsThread) {
1381 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1382 }
1383 }
1384 }
1385
1386 private ActivityManagerService() {
1387 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1388 if (v != null && Integer.getInteger(v) != 0) {
1389 mSimpleProcessManagement = true;
1390 }
1391 v = System.getenv("ANDROID_DEBUG_APP");
1392 if (v != null) {
1393 mSimpleProcessManagement = true;
1394 }
1395
Joe Onorato8a9b2202010-02-26 18:56:32 -08001396 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 File dataDir = Environment.getDataDirectory();
1399 File systemDir = new File(dataDir, "system");
1400 systemDir.mkdirs();
1401 mBatteryStatsService = new BatteryStatsService(new File(
1402 systemDir, "batterystats.bin").toString());
1403 mBatteryStatsService.getActiveStatistics().readLocked();
1404 mBatteryStatsService.getActiveStatistics().writeLocked();
1405
1406 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001407 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408
Jack Palevichb90d28c2009-07-22 15:35:24 -07001409 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1410 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1411
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001412 mConfiguration.setToDefaults();
1413 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 mProcessStats.init();
1415
1416 // Add ourself to the Watchdog monitors.
1417 Watchdog.getInstance().addMonitor(this);
1418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 mProcessStatsThread = new Thread("ProcessStats") {
1420 public void run() {
1421 while (true) {
1422 try {
1423 try {
1424 synchronized(this) {
1425 final long now = SystemClock.uptimeMillis();
1426 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1427 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001428 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 // + ", write delay=" + nextWriteDelay);
1430 if (nextWriteDelay < nextCpuDelay) {
1431 nextCpuDelay = nextWriteDelay;
1432 }
1433 if (nextCpuDelay > 0) {
1434 this.wait(nextCpuDelay);
1435 }
1436 }
1437 } catch (InterruptedException e) {
1438 }
1439
1440 updateCpuStatsNow();
1441 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001442 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 }
1444 }
1445 }
1446 };
1447 mProcessStatsThread.start();
1448 }
1449
1450 @Override
1451 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1452 throws RemoteException {
1453 try {
1454 return super.onTransact(code, data, reply, flags);
1455 } catch (RuntimeException e) {
1456 // The activity manager only throws security exceptions, so let's
1457 // log all others.
1458 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001459 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 }
1461 throw e;
1462 }
1463 }
1464
1465 void updateCpuStats() {
1466 synchronized (mProcessStatsThread) {
1467 final long now = SystemClock.uptimeMillis();
1468 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1469 mProcessStatsThread.notify();
1470 }
1471 }
1472 }
1473
1474 void updateCpuStatsNow() {
1475 synchronized (mProcessStatsThread) {
1476 final long now = SystemClock.uptimeMillis();
1477 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 if (MONITOR_CPU_USAGE &&
1480 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1481 mLastCpuTime = now;
1482 haveNewCpuStats = true;
1483 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001484 //Slog.i(TAG, mProcessStats.printCurrentState());
1485 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 // + mProcessStats.getTotalCpuPercent() + "%");
1487
Joe Onorato8a9b2202010-02-26 18:56:32 -08001488 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 if ("true".equals(SystemProperties.get("events.cpu"))) {
1490 int user = mProcessStats.getLastUserTime();
1491 int system = mProcessStats.getLastSystemTime();
1492 int iowait = mProcessStats.getLastIoWaitTime();
1493 int irq = mProcessStats.getLastIrqTime();
1494 int softIrq = mProcessStats.getLastSoftIrqTime();
1495 int idle = mProcessStats.getLastIdleTime();
1496
1497 int total = user + system + iowait + irq + softIrq + idle;
1498 if (total == 0) total = 1;
1499
Doug Zongker2bec3d42009-12-04 12:52:44 -08001500 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 ((user+system+iowait+irq+softIrq) * 100) / total,
1502 (user * 100) / total,
1503 (system * 100) / total,
1504 (iowait * 100) / total,
1505 (irq * 100) / total,
1506 (softIrq * 100) / total);
1507 }
1508 }
1509
Amith Yamasanie43530a2009-08-21 13:11:37 -07001510 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001511 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001512 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 synchronized(mPidsSelfLocked) {
1514 if (haveNewCpuStats) {
1515 if (mBatteryStatsService.isOnBattery()) {
1516 final int N = mProcessStats.countWorkingStats();
1517 for (int i=0; i<N; i++) {
1518 ProcessStats.Stats st
1519 = mProcessStats.getWorkingStats(i);
1520 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1521 if (pr != null) {
1522 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1523 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001524 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001525 } else {
1526 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001527 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001528 if (ps != null) {
1529 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001530 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 }
1533 }
1534 }
1535 }
1536 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1539 mLastWriteTime = now;
1540 mBatteryStatsService.getActiveStatistics().writeLocked();
1541 }
1542 }
1543 }
1544 }
1545
1546 /**
1547 * Initialize the application bind args. These are passed to each
1548 * process when the bindApplication() IPC is sent to the process. They're
1549 * lazily setup to make sure the services are running when they're asked for.
1550 */
1551 private HashMap<String, IBinder> getCommonServicesLocked() {
1552 if (mAppBindArgs == null) {
1553 mAppBindArgs = new HashMap<String, IBinder>();
1554
1555 // Setup the application init args
1556 mAppBindArgs.put("package", ServiceManager.getService("package"));
1557 mAppBindArgs.put("window", ServiceManager.getService("window"));
1558 mAppBindArgs.put(Context.ALARM_SERVICE,
1559 ServiceManager.getService(Context.ALARM_SERVICE));
1560 }
1561 return mAppBindArgs;
1562 }
1563
1564 private final void setFocusedActivityLocked(HistoryRecord r) {
1565 if (mFocusedActivity != r) {
1566 mFocusedActivity = r;
1567 mWindowManager.setFocusedApp(r, true);
1568 }
1569 }
1570
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001571 private final void updateLruProcessLocked(ProcessRecord app,
1572 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001574 int lrui = mLruProcesses.indexOf(app);
1575 if (lrui >= 0) mLruProcesses.remove(lrui);
1576
1577 int i = mLruProcesses.size()-1;
1578 int skipTop = 0;
1579
1580 // compute the new weight for this process.
1581 if (updateActivityTime) {
1582 app.lastActivityTime = SystemClock.uptimeMillis();
1583 }
1584 if (app.activities.size() > 0) {
1585 // If this process has activities, we more strongly want to keep
1586 // it around.
1587 app.lruWeight = app.lastActivityTime;
1588 } else if (app.pubProviders.size() > 0) {
1589 // If this process contains content providers, we want to keep
1590 // it a little more strongly.
1591 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1592 // Also don't let it kick out the first few "real" hidden processes.
1593 skipTop = MIN_HIDDEN_APPS;
1594 } else {
1595 // If this process doesn't have activities, we less strongly
1596 // want to keep it around, and generally want to avoid getting
1597 // in front of any very recently used activities.
1598 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1599 // Also don't let it kick out the first few "real" hidden processes.
1600 skipTop = MIN_HIDDEN_APPS;
1601 }
1602 while (i >= 0) {
1603 ProcessRecord p = mLruProcesses.get(i);
1604 // If this app shouldn't be in front of the first N background
1605 // apps, then skip over that many that are currently hidden.
1606 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1607 skipTop--;
1608 }
1609 if (p.lruWeight <= app.lruWeight){
1610 mLruProcesses.add(i+1, app);
1611 break;
1612 }
1613 i--;
1614 }
1615 if (i < 0) {
1616 mLruProcesses.add(0, app);
1617 }
1618
Joe Onorato8a9b2202010-02-26 18:56:32 -08001619 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 if (oomAdj) {
1621 updateOomAdjLocked();
1622 }
1623 }
1624
1625 private final boolean updateLRUListLocked(HistoryRecord r) {
1626 final boolean hadit = mLRUActivities.remove(r);
1627 mLRUActivities.add(r);
1628 return hadit;
1629 }
1630
1631 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1632 int i = mHistory.size()-1;
1633 while (i >= 0) {
1634 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1635 if (!r.finishing && r != notTop) {
1636 return r;
1637 }
1638 i--;
1639 }
1640 return null;
1641 }
1642
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001643 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1644 int i = mHistory.size()-1;
1645 while (i >= 0) {
1646 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1647 if (!r.finishing && !r.delayedResume && r != notTop) {
1648 return r;
1649 }
1650 i--;
1651 }
1652 return null;
1653 }
1654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 /**
1656 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001657 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 *
1659 * @param token If non-null, any history records matching this token will be skipped.
1660 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1661 *
1662 * @return Returns the HistoryRecord of the next activity on the stack.
1663 */
1664 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1665 int i = mHistory.size()-1;
1666 while (i >= 0) {
1667 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1668 // Note: the taskId check depends on real taskId fields being non-zero
1669 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1670 return r;
1671 }
1672 i--;
1673 }
1674 return null;
1675 }
1676
1677 private final ProcessRecord getProcessRecordLocked(
1678 String processName, int uid) {
1679 if (uid == Process.SYSTEM_UID) {
1680 // The system gets to run in any process. If there are multiple
1681 // processes with the same uid, just pick the first (this
1682 // should never happen).
1683 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1684 processName);
1685 return procs != null ? procs.valueAt(0) : null;
1686 }
1687 ProcessRecord proc = mProcessNames.get(processName, uid);
1688 return proc;
1689 }
1690
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001691 private void ensurePackageDexOpt(String packageName) {
1692 IPackageManager pm = ActivityThread.getPackageManager();
1693 try {
1694 if (pm.performDexOpt(packageName)) {
1695 mDidDexOpt = true;
1696 }
1697 } catch (RemoteException e) {
1698 }
1699 }
1700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 private boolean isNextTransitionForward() {
1702 int transit = mWindowManager.getPendingAppTransition();
1703 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1704 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1705 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1706 }
1707
1708 private final boolean realStartActivityLocked(HistoryRecord r,
1709 ProcessRecord app, boolean andResume, boolean checkConfig)
1710 throws RemoteException {
1711
1712 r.startFreezingScreenLocked(app, 0);
1713 mWindowManager.setAppVisibility(r, true);
1714
1715 // Have the window manager re-evaluate the orientation of
1716 // the screen based on the new activity order. Note that
1717 // as a result of this, it can call back into the activity
1718 // manager with a new orientation. We don't care about that,
1719 // because the activity is not currently running so we are
1720 // just restarting it anyway.
1721 if (checkConfig) {
1722 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001723 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 r.mayFreezeScreenLocked(app) ? r : null);
1725 updateConfigurationLocked(config, r);
1726 }
1727
1728 r.app = app;
1729
Joe Onorato8a9b2202010-02-26 18:56:32 -08001730 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731
1732 int idx = app.activities.indexOf(r);
1733 if (idx < 0) {
1734 app.activities.add(r);
1735 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001736 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001737
1738 try {
1739 if (app.thread == null) {
1740 throw new RemoteException();
1741 }
1742 List<ResultInfo> results = null;
1743 List<Intent> newIntents = null;
1744 if (andResume) {
1745 results = r.results;
1746 newIntents = r.newIntents;
1747 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001748 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 + " icicle=" + r.icicle
1750 + " with results=" + results + " newIntents=" + newIntents
1751 + " andResume=" + andResume);
1752 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001753 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 System.identityHashCode(r),
1755 r.task.taskId, r.shortComponentName);
1756 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001757 if (r.isHomeActivity) {
1758 mHomeProcess = app;
1759 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001760 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001762 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 r.info, r.icicle, results, newIntents, !andResume,
1764 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 } catch (RemoteException e) {
1766 if (r.launchFailed) {
1767 // This is the second time we failed -- finish activity
1768 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001769 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 + r.intent.getComponent().flattenToShortString()
1771 + ", giving up", e);
1772 appDiedLocked(app, app.pid, app.thread);
1773 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1774 "2nd-crash");
1775 return false;
1776 }
1777
1778 // This is the first time we failed -- restart process and
1779 // retry.
1780 app.activities.remove(r);
1781 throw e;
1782 }
1783
1784 r.launchFailed = false;
1785 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001786 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 + " being launched, but already in LRU list");
1788 }
1789
1790 if (andResume) {
1791 // As part of the process of launching, ActivityThread also performs
1792 // a resume.
1793 r.state = ActivityState.RESUMED;
1794 r.icicle = null;
1795 r.haveState = false;
1796 r.stopped = false;
1797 mResumedActivity = r;
1798 r.task.touchActiveTime();
1799 completeResumeLocked(r);
1800 pauseIfSleepingLocked();
1801 } else {
1802 // This activity is not starting in the resumed state... which
1803 // should look like we asked it to pause+stop (but remain visible),
1804 // and it has done so and reported back the current icicle and
1805 // other state.
1806 r.state = ActivityState.STOPPED;
1807 r.stopped = true;
1808 }
1809
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001810 // Launch the new version setup screen if needed. We do this -after-
1811 // launching the initial activity (that is, home), so that it can have
1812 // a chance to initialize itself while in the background, making the
1813 // switch back to it faster and look better.
1814 startSetupActivityLocked();
1815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 return true;
1817 }
1818
1819 private final void startSpecificActivityLocked(HistoryRecord r,
1820 boolean andResume, boolean checkConfig) {
1821 // Is this activity's application already running?
1822 ProcessRecord app = getProcessRecordLocked(r.processName,
1823 r.info.applicationInfo.uid);
1824
1825 if (r.startTime == 0) {
1826 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001827 if (mInitialStartTime == 0) {
1828 mInitialStartTime = r.startTime;
1829 }
1830 } else if (mInitialStartTime == 0) {
1831 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 }
1833
1834 if (app != null && app.thread != null) {
1835 try {
1836 realStartActivityLocked(r, app, andResume, checkConfig);
1837 return;
1838 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001839 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 + r.intent.getComponent().flattenToShortString(), e);
1841 }
1842
1843 // If a dead object exception was thrown -- fall through to
1844 // restart the application.
1845 }
1846
1847 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001848 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 }
1850
1851 private final ProcessRecord startProcessLocked(String processName,
1852 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001853 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1855 // We don't have to do anything more if:
1856 // (1) There is an existing application record; and
1857 // (2) The caller doesn't think it is dead, OR there is no thread
1858 // object attached to it so we know it couldn't have crashed; and
1859 // (3) There is a pid assigned to it, so it is either starting or
1860 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001861 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 + " app=" + app + " knownToBeDead=" + knownToBeDead
1863 + " thread=" + (app != null ? app.thread : null)
1864 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001865 if (app != null && app.pid > 0) {
1866 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001867 // We already have the app running, or are waiting for it to
1868 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001869 return app;
1870 } else {
1871 // An application record is attached to a previous process,
1872 // clean it up now.
1873 handleAppDiedLocked(app, true);
1874 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001875 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 String hostingNameStr = hostingName != null
1878 ? hostingName.flattenToShortString() : null;
1879
1880 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1881 // If we are in the background, then check to see if this process
1882 // is bad. If so, we will just silently fail.
1883 if (mBadProcesses.get(info.processName, info.uid) != null) {
1884 return null;
1885 }
1886 } else {
1887 // When the user is explicitly starting a process, then clear its
1888 // crash count so that we won't make it bad until they see at
1889 // least one crash dialog again, and make the process good again
1890 // if it had been bad.
1891 mProcessCrashTimes.remove(info.processName, info.uid);
1892 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001893 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 info.processName);
1895 mBadProcesses.remove(info.processName, info.uid);
1896 if (app != null) {
1897 app.bad = false;
1898 }
1899 }
1900 }
1901
1902 if (app == null) {
1903 app = newProcessRecordLocked(null, info, processName);
1904 mProcessNames.put(processName, info.uid, app);
1905 } else {
1906 // If this is a new package in the process, add the package to the list
1907 app.addPackage(info.packageName);
1908 }
1909
1910 // If the system is not ready yet, then hold off on starting this
1911 // process until it is.
1912 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001913 && !isAllowedWhileBooting(info)
1914 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 if (!mProcessesOnHold.contains(app)) {
1916 mProcessesOnHold.add(app);
1917 }
1918 return app;
1919 }
1920
1921 startProcessLocked(app, hostingType, hostingNameStr);
1922 return (app.pid != 0) ? app : null;
1923 }
1924
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001925 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1926 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1927 }
1928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 private final void startProcessLocked(ProcessRecord app,
1930 String hostingType, String hostingNameStr) {
1931 if (app.pid > 0 && app.pid != MY_PID) {
1932 synchronized (mPidsSelfLocked) {
1933 mPidsSelfLocked.remove(app.pid);
1934 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1935 }
1936 app.pid = 0;
1937 }
1938
1939 mProcessesOnHold.remove(app);
1940
1941 updateCpuStats();
1942
1943 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1944 mProcDeaths[0] = 0;
1945
1946 try {
1947 int uid = app.info.uid;
1948 int[] gids = null;
1949 try {
1950 gids = mContext.getPackageManager().getPackageGids(
1951 app.info.packageName);
1952 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001953 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001954 }
1955 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1956 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1957 && mTopComponent != null
1958 && app.processName.equals(mTopComponent.getPackageName())) {
1959 uid = 0;
1960 }
1961 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1962 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1963 uid = 0;
1964 }
1965 }
1966 int debugFlags = 0;
1967 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1968 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1969 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001970 // Run the app in safe mode if its manifest requests so or the
1971 // system is booted in safe mode.
1972 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1973 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001974 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1977 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1978 }
1979 if ("1".equals(SystemProperties.get("debug.assert"))) {
1980 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1981 }
1982 int pid = Process.start("android.app.ActivityThread",
1983 mSimpleProcessManagement ? app.processName : null, uid, uid,
1984 gids, debugFlags, null);
1985 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1986 synchronized (bs) {
1987 if (bs.isOnBattery()) {
1988 app.batteryStats.incStartsLocked();
1989 }
1990 }
1991
Doug Zongker2bec3d42009-12-04 12:52:44 -08001992 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 app.processName, hostingType,
1994 hostingNameStr != null ? hostingNameStr : "");
1995
1996 if (app.persistent) {
1997 Watchdog.getInstance().processStarted(app, app.processName, pid);
1998 }
1999
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002000 StringBuilder buf = mStringBuilder;
2001 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002002 buf.append("Start proc ");
2003 buf.append(app.processName);
2004 buf.append(" for ");
2005 buf.append(hostingType);
2006 if (hostingNameStr != null) {
2007 buf.append(" ");
2008 buf.append(hostingNameStr);
2009 }
2010 buf.append(": pid=");
2011 buf.append(pid);
2012 buf.append(" uid=");
2013 buf.append(uid);
2014 buf.append(" gids={");
2015 if (gids != null) {
2016 for (int gi=0; gi<gids.length; gi++) {
2017 if (gi != 0) buf.append(", ");
2018 buf.append(gids[gi]);
2019
2020 }
2021 }
2022 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002023 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002024 if (pid == 0 || pid == MY_PID) {
2025 // Processes are being emulated with threads.
2026 app.pid = MY_PID;
2027 app.removed = false;
2028 mStartingProcesses.add(app);
2029 } else if (pid > 0) {
2030 app.pid = pid;
2031 app.removed = false;
2032 synchronized (mPidsSelfLocked) {
2033 this.mPidsSelfLocked.put(pid, app);
2034 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2035 msg.obj = app;
2036 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2037 }
2038 } else {
2039 app.pid = 0;
2040 RuntimeException e = new RuntimeException(
2041 "Failure starting process " + app.processName
2042 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002043 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 }
2045 } catch (RuntimeException e) {
2046 // XXX do better error recovery.
2047 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002048 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002049 }
2050 }
2051
2052 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2053 if (mPausingActivity != null) {
2054 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002055 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 + mPausingActivity, e);
2057 }
2058 HistoryRecord prev = mResumedActivity;
2059 if (prev == null) {
2060 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002061 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 resumeTopActivityLocked(null);
2063 return;
2064 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002065 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 mResumedActivity = null;
2067 mPausingActivity = prev;
2068 mLastPausedActivity = prev;
2069 prev.state = ActivityState.PAUSING;
2070 prev.task.touchActiveTime();
2071
2072 updateCpuStats();
2073
2074 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002075 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002077 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 System.identityHashCode(prev),
2079 prev.shortComponentName);
2080 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2081 prev.configChangeFlags);
2082 updateUsageStats(prev, false);
2083 } catch (Exception e) {
2084 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002085 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002086 mPausingActivity = null;
2087 mLastPausedActivity = null;
2088 }
2089 } else {
2090 mPausingActivity = null;
2091 mLastPausedActivity = null;
2092 }
2093
2094 // If we are not going to sleep, we want to ensure the device is
2095 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002096 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 mLaunchingActivity.acquire();
2098 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2099 // To be safe, don't allow the wake lock to be held for too long.
2100 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2101 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2102 }
2103 }
2104
2105
2106 if (mPausingActivity != null) {
2107 // Have the window manager pause its key dispatching until the new
2108 // activity has started. If we're pausing the activity just because
2109 // the screen is being turned off and the UI is sleeping, don't interrupt
2110 // key dispatch; the same activity will pick it up again on wakeup.
2111 if (!uiSleeping) {
2112 prev.pauseKeyDispatchingLocked();
2113 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002114 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002115 }
2116
2117 // Schedule a pause timeout in case the app doesn't respond.
2118 // We don't give it much time because this directly impacts the
2119 // responsiveness seen by the user.
2120 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2121 msg.obj = prev;
2122 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002123 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 } else {
2125 // This activity failed to schedule the
2126 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002127 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002128 resumeTopActivityLocked(null);
2129 }
2130 }
2131
2132 private final void completePauseLocked() {
2133 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002134 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135
2136 if (prev != null) {
2137 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002138 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2140 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002141 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 if (prev.waitingVisible) {
2143 prev.waitingVisible = false;
2144 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002145 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 TAG, "Complete pause, no longer waiting: " + prev);
2147 }
2148 if (prev.configDestroy) {
2149 // The previous is being paused because the configuration
2150 // is changing, which means it is actually stopping...
2151 // To juggle the fact that we are also starting a new
2152 // instance right now, we need to first completely stop
2153 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002154 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 destroyActivityLocked(prev, true);
2156 } else {
2157 mStoppingActivities.add(prev);
2158 if (mStoppingActivities.size() > 3) {
2159 // If we already have a few activities waiting to stop,
2160 // then give up on things going idle and start clearing
2161 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002162 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 Message msg = Message.obtain();
2164 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2165 mHandler.sendMessage(msg);
2166 }
2167 }
2168 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002169 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 prev = null;
2171 }
2172 mPausingActivity = null;
2173 }
2174
Dianne Hackborn55280a92009-05-07 15:53:46 -07002175 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 resumeTopActivityLocked(prev);
2177 } else {
2178 if (mGoingToSleep.isHeld()) {
2179 mGoingToSleep.release();
2180 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002181 if (mShuttingDown) {
2182 notifyAll();
2183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184 }
2185
2186 if (prev != null) {
2187 prev.resumeKeyDispatchingLocked();
2188 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002189
2190 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2191 long diff = 0;
2192 synchronized (mProcessStatsThread) {
2193 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2194 }
2195 if (diff > 0) {
2196 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2197 synchronized (bsi) {
2198 BatteryStatsImpl.Uid.Proc ps =
2199 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2200 prev.info.packageName);
2201 if (ps != null) {
2202 ps.addForegroundTimeLocked(diff);
2203 }
2204 }
2205 }
2206 }
2207 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208 }
2209
2210 /**
2211 * Once we know that we have asked an application to put an activity in
2212 * the resumed state (either by launching it or explicitly telling it),
2213 * this function updates the rest of our state to match that fact.
2214 */
2215 private final void completeResumeLocked(HistoryRecord next) {
2216 next.idle = false;
2217 next.results = null;
2218 next.newIntents = null;
2219
2220 // schedule an idle timeout in case the app doesn't do it for us.
2221 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2222 msg.obj = next;
2223 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2224
2225 if (false) {
2226 // The activity was never told to pause, so just keep
2227 // things going as-is. To maintain our own state,
2228 // we need to emulate it coming back and saying it is
2229 // idle.
2230 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2231 msg.obj = next;
2232 mHandler.sendMessage(msg);
2233 }
2234
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002235 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237 next.thumbnail = null;
2238 setFocusedActivityLocked(next);
2239 next.resumeKeyDispatchingLocked();
2240 ensureActivitiesVisibleLocked(null, 0);
2241 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002242 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002243
2244 // Mark the point when the activity is resuming
2245 // TODO: To be more accurate, the mark should be before the onCreate,
2246 // not after the onResume. But for subsequent starts, onResume is fine.
2247 if (next.app != null) {
2248 synchronized (mProcessStatsThread) {
2249 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2250 }
2251 } else {
2252 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 }
2255
2256 /**
2257 * Make sure that all activities that need to be visible (that is, they
2258 * currently can be seen by the user) actually are.
2259 */
2260 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2261 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002262 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263 TAG, "ensureActivitiesVisible behind " + top
2264 + " configChanges=0x" + Integer.toHexString(configChanges));
2265
2266 // If the top activity is not fullscreen, then we need to
2267 // make sure any activities under it are now visible.
2268 final int count = mHistory.size();
2269 int i = count-1;
2270 while (mHistory.get(i) != top) {
2271 i--;
2272 }
2273 HistoryRecord r;
2274 boolean behindFullscreen = false;
2275 for (; i>=0; i--) {
2276 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002277 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278 TAG, "Make visible? " + r + " finishing=" + r.finishing
2279 + " state=" + r.state);
2280 if (r.finishing) {
2281 continue;
2282 }
2283
2284 final boolean doThisProcess = onlyThisProcess == null
2285 || onlyThisProcess.equals(r.processName);
2286
2287 // First: if this is not the current activity being started, make
2288 // sure it matches the current configuration.
2289 if (r != starting && doThisProcess) {
2290 ensureActivityConfigurationLocked(r, 0);
2291 }
2292
2293 if (r.app == null || r.app.thread == null) {
2294 if (onlyThisProcess == null
2295 || onlyThisProcess.equals(r.processName)) {
2296 // This activity needs to be visible, but isn't even
2297 // running... get it started, but don't resume it
2298 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002299 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002300 TAG, "Start and freeze screen for " + r);
2301 if (r != starting) {
2302 r.startFreezingScreenLocked(r.app, configChanges);
2303 }
2304 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002305 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002306 TAG, "Starting and making visible: " + r);
2307 mWindowManager.setAppVisibility(r, true);
2308 }
2309 if (r != starting) {
2310 startSpecificActivityLocked(r, false, false);
2311 }
2312 }
2313
2314 } else if (r.visible) {
2315 // If this activity is already visible, then there is nothing
2316 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002317 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 TAG, "Skipping: already visible at " + r);
2319 r.stopFreezingScreenLocked(false);
2320
2321 } else if (onlyThisProcess == null) {
2322 // This activity is not currently visible, but is running.
2323 // Tell it to become visible.
2324 r.visible = true;
2325 if (r.state != ActivityState.RESUMED && r != starting) {
2326 // If this activity is paused, tell it
2327 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002328 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329 TAG, "Making visible and scheduling visibility: " + r);
2330 try {
2331 mWindowManager.setAppVisibility(r, true);
2332 r.app.thread.scheduleWindowVisibility(r, true);
2333 r.stopFreezingScreenLocked(false);
2334 } catch (Exception e) {
2335 // Just skip on any failure; we'll make it
2336 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002337 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 + r.intent.getComponent(), e);
2339 }
2340 }
2341 }
2342
2343 // Aggregate current change flags.
2344 configChanges |= r.configChangeFlags;
2345
2346 if (r.fullscreen) {
2347 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002348 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002349 TAG, "Stopping: fullscreen at " + r);
2350 behindFullscreen = true;
2351 i--;
2352 break;
2353 }
2354 }
2355
2356 // Now for any activities that aren't visible to the user, make
2357 // sure they no longer are keeping the screen frozen.
2358 while (i >= 0) {
2359 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002360 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2362 + " state=" + r.state
2363 + " behindFullscreen=" + behindFullscreen);
2364 if (!r.finishing) {
2365 if (behindFullscreen) {
2366 if (r.visible) {
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, "Making invisible: " + r);
2369 r.visible = false;
2370 try {
2371 mWindowManager.setAppVisibility(r, false);
2372 if ((r.state == ActivityState.STOPPING
2373 || r.state == ActivityState.STOPPED)
2374 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002375 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 TAG, "Scheduling invisibility: " + r);
2377 r.app.thread.scheduleWindowVisibility(r, false);
2378 }
2379 } catch (Exception e) {
2380 // Just skip on any failure; we'll make it
2381 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002382 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 + r.intent.getComponent(), e);
2384 }
2385 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002386 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 TAG, "Already invisible: " + r);
2388 }
2389 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002390 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002391 TAG, "Now behindFullscreen: " + r);
2392 behindFullscreen = true;
2393 }
2394 }
2395 i--;
2396 }
2397 }
2398
2399 /**
2400 * Version of ensureActivitiesVisible that can easily be called anywhere.
2401 */
2402 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2403 int configChanges) {
2404 HistoryRecord r = topRunningActivityLocked(null);
2405 if (r != null) {
2406 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2407 }
2408 }
2409
2410 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2411 if (resumed) {
2412 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2413 } else {
2414 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2415 }
2416 }
2417
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002418 private boolean startHomeActivityLocked() {
2419 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2420 && mTopAction == null) {
2421 // We are running in factory test mode, but unable to find
2422 // the factory test app, so just sit around displaying the
2423 // error message and don't try to start anything.
2424 return false;
2425 }
2426 Intent intent = new Intent(
2427 mTopAction,
2428 mTopData != null ? Uri.parse(mTopData) : null);
2429 intent.setComponent(mTopComponent);
2430 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2431 intent.addCategory(Intent.CATEGORY_HOME);
2432 }
2433 ActivityInfo aInfo =
2434 intent.resolveActivityInfo(mContext.getPackageManager(),
2435 STOCK_PM_FLAGS);
2436 if (aInfo != null) {
2437 intent.setComponent(new ComponentName(
2438 aInfo.applicationInfo.packageName, aInfo.name));
2439 // Don't do this if the home app is currently being
2440 // instrumented.
2441 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2442 aInfo.applicationInfo.uid);
2443 if (app == null || app.instrumentationClass == null) {
2444 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2445 startActivityLocked(null, intent, null, null, 0, aInfo,
2446 null, null, 0, 0, 0, false, false);
2447 }
2448 }
2449
2450
2451 return true;
2452 }
2453
2454 /**
2455 * Starts the "new version setup screen" if appropriate.
2456 */
2457 private void startSetupActivityLocked() {
2458 // Only do this once per boot.
2459 if (mCheckedForSetup) {
2460 return;
2461 }
2462
2463 // We will show this screen if the current one is a different
2464 // version than the last one shown, and we are not running in
2465 // low-level factory test mode.
2466 final ContentResolver resolver = mContext.getContentResolver();
2467 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2468 Settings.Secure.getInt(resolver,
2469 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2470 mCheckedForSetup = true;
2471
2472 // See if we should be showing the platform update setup UI.
2473 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2474 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2475 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2476
2477 // We don't allow third party apps to replace this.
2478 ResolveInfo ri = null;
2479 for (int i=0; ris != null && i<ris.size(); i++) {
2480 if ((ris.get(i).activityInfo.applicationInfo.flags
2481 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2482 ri = ris.get(i);
2483 break;
2484 }
2485 }
2486
2487 if (ri != null) {
2488 String vers = ri.activityInfo.metaData != null
2489 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2490 : null;
2491 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2492 vers = ri.activityInfo.applicationInfo.metaData.getString(
2493 Intent.METADATA_SETUP_VERSION);
2494 }
2495 String lastVers = Settings.Secure.getString(
2496 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2497 if (vers != null && !vers.equals(lastVers)) {
2498 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2499 intent.setComponent(new ComponentName(
2500 ri.activityInfo.packageName, ri.activityInfo.name));
2501 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2502 null, null, 0, 0, 0, false, false);
2503 }
2504 }
2505 }
2506 }
2507
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002508 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002509 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002510
2511 final int identHash = System.identityHashCode(r);
2512 updateUsageStats(r, true);
2513
2514 int i = mWatchers.beginBroadcast();
2515 while (i > 0) {
2516 i--;
2517 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2518 if (w != null) {
2519 try {
2520 w.activityResuming(identHash);
2521 } catch (RemoteException e) {
2522 }
2523 }
2524 }
2525 mWatchers.finishBroadcast();
2526 }
2527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 /**
2529 * Ensure that the top activity in the stack is resumed.
2530 *
2531 * @param prev The previously resumed activity, for when in the process
2532 * of pausing; can be null to call from elsewhere.
2533 *
2534 * @return Returns true if something is being resumed, or false if
2535 * nothing happened.
2536 */
2537 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2538 // Find the first activity that is not finishing.
2539 HistoryRecord next = topRunningActivityLocked(null);
2540
2541 // Remember how we'll process this pause/resume situation, and ensure
2542 // that the state is reset however we wind up proceeding.
2543 final boolean userLeaving = mUserLeaving;
2544 mUserLeaving = false;
2545
2546 if (next == null) {
2547 // There are no more activities! Let's just start up the
2548 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002549 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 }
2551
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002552 next.delayedResume = false;
2553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 // If the top activity is the resumed one, nothing to do.
2555 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2556 // Make sure we have executed any pending transitions, since there
2557 // should be nothing left to do at this point.
2558 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002559 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 return false;
2561 }
2562
2563 // If we are sleeping, and there is no resumed activity, and the top
2564 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002565 if ((mSleeping || mShuttingDown)
2566 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 // Make sure we have executed any pending transitions, since there
2568 // should be nothing left to do at this point.
2569 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002570 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 return false;
2572 }
2573
2574 // The activity may be waiting for stop, but that is no longer
2575 // appropriate for it.
2576 mStoppingActivities.remove(next);
2577 mWaitingVisibleActivities.remove(next);
2578
Joe Onorato8a9b2202010-02-26 18:56:32 -08002579 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580
2581 // If we are currently pausing an activity, then don't do anything
2582 // until that is done.
2583 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002584 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 return false;
2586 }
2587
2588 // We need to start pausing the current activity so the top one
2589 // can be resumed...
2590 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002591 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002592 startPausingLocked(userLeaving, false);
2593 return true;
2594 }
2595
2596 if (prev != null && prev != next) {
2597 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2598 prev.waitingVisible = true;
2599 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002600 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002601 TAG, "Resuming top, waiting visible to hide: " + prev);
2602 } else {
2603 // The next activity is already visible, so hide the previous
2604 // activity's windows right now so we can show the new one ASAP.
2605 // We only do this if the previous is finishing, which should mean
2606 // it is on top of the one being resumed so hiding it quickly
2607 // is good. Otherwise, we want to do the normal route of allowing
2608 // the resumed activity to be shown so we can decide if the
2609 // previous should actually be hidden depending on whether the
2610 // new one is found to be full-screen or not.
2611 if (prev.finishing) {
2612 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002613 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614 + prev + ", waitingVisible="
2615 + (prev != null ? prev.waitingVisible : null)
2616 + ", nowVisible=" + next.nowVisible);
2617 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002618 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619 + prev + ", waitingVisible="
2620 + (prev != null ? prev.waitingVisible : null)
2621 + ", nowVisible=" + next.nowVisible);
2622 }
2623 }
2624 }
2625
2626 // We are starting up the next activity, so tell the window manager
2627 // that the previous one will be hidden soon. This way it can know
2628 // to ignore it when computing the desired screen orientation.
2629 if (prev != null) {
2630 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002631 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002633 if (mNoAnimActivities.contains(prev)) {
2634 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2635 } else {
2636 mWindowManager.prepareAppTransition(prev.task == next.task
2637 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2638 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640 mWindowManager.setAppWillBeHidden(prev);
2641 mWindowManager.setAppVisibility(prev, false);
2642 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002643 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002645 if (mNoAnimActivities.contains(next)) {
2646 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2647 } else {
2648 mWindowManager.prepareAppTransition(prev.task == next.task
2649 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2650 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002652 }
2653 if (false) {
2654 mWindowManager.setAppWillBeHidden(prev);
2655 mWindowManager.setAppVisibility(prev, false);
2656 }
2657 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002658 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002659 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002660 if (mNoAnimActivities.contains(next)) {
2661 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2662 } else {
2663 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 }
2666
2667 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002668 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002669
2670 // This activity is now becoming visible.
2671 mWindowManager.setAppVisibility(next, true);
2672
2673 HistoryRecord lastResumedActivity = mResumedActivity;
2674 ActivityState lastState = next.state;
2675
2676 updateCpuStats();
2677
2678 next.state = ActivityState.RESUMED;
2679 mResumedActivity = next;
2680 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002681 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002682 updateLRUListLocked(next);
2683
2684 // Have the window manager re-evaluate the orientation of
2685 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002686 boolean updated;
2687 synchronized (this) {
2688 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2689 mConfiguration,
2690 next.mayFreezeScreenLocked(next.app) ? next : null);
2691 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002692 next.frozenBeforeDestroy = true;
2693 }
2694 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002695 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002696 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 // The configuration update wasn't able to keep the existing
2698 // instance of the activity, and instead started a new one.
2699 // We should be all done, but let's just make sure our activity
2700 // is still at the top and schedule another run if something
2701 // weird happened.
2702 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002703 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704 "Activity config changed during resume: " + next
2705 + ", new next: " + nextNext);
2706 if (nextNext != next) {
2707 // Do over!
2708 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2709 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002710 setFocusedActivityLocked(next);
2711 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002713 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 return true;
2715 }
2716
2717 try {
2718 // Deliver all pending results.
2719 ArrayList a = next.results;
2720 if (a != null) {
2721 final int N = a.size();
2722 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002723 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724 TAG, "Delivering results to " + next
2725 + ": " + a);
2726 next.app.thread.scheduleSendResult(next, a);
2727 }
2728 }
2729
2730 if (next.newIntents != null) {
2731 next.app.thread.scheduleNewIntent(next.newIntents, next);
2732 }
2733
Doug Zongker2bec3d42009-12-04 12:52:44 -08002734 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002735 System.identityHashCode(next),
2736 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737
2738 next.app.thread.scheduleResumeActivity(next,
2739 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 pauseIfSleepingLocked();
2742
2743 } catch (Exception e) {
2744 // Whoops, need to restart this activity!
2745 next.state = lastState;
2746 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002747 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 if (!next.hasBeenLaunched) {
2749 next.hasBeenLaunched = true;
2750 } else {
2751 if (SHOW_APP_STARTING_ICON) {
2752 mWindowManager.setAppStartingWindow(
2753 next, next.packageName, next.theme,
2754 next.nonLocalizedLabel,
2755 next.labelRes, next.icon, null, true);
2756 }
2757 }
2758 startSpecificActivityLocked(next, true, false);
2759 return true;
2760 }
2761
2762 // From this point on, if something goes wrong there is no way
2763 // to recover the activity.
2764 try {
2765 next.visible = true;
2766 completeResumeLocked(next);
2767 } catch (Exception e) {
2768 // If any exception gets thrown, toss away this
2769 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002770 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002771 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2772 "resume-exception");
2773 return true;
2774 }
2775
2776 // Didn't need to use the icicle, and it is now out of date.
2777 next.icicle = null;
2778 next.haveState = false;
2779 next.stopped = false;
2780
2781 } else {
2782 // Whoops, need to restart this activity!
2783 if (!next.hasBeenLaunched) {
2784 next.hasBeenLaunched = true;
2785 } else {
2786 if (SHOW_APP_STARTING_ICON) {
2787 mWindowManager.setAppStartingWindow(
2788 next, next.packageName, next.theme,
2789 next.nonLocalizedLabel,
2790 next.labelRes, next.icon, null, true);
2791 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002792 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002793 }
2794 startSpecificActivityLocked(next, true, true);
2795 }
2796
2797 return true;
2798 }
2799
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002800 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2801 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002802 final int NH = mHistory.size();
2803
2804 int addPos = -1;
2805
2806 if (!newTask) {
2807 // If starting in an existing task, find where that is...
2808 HistoryRecord next = null;
2809 boolean startIt = true;
2810 for (int i = NH-1; i >= 0; i--) {
2811 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2812 if (p.finishing) {
2813 continue;
2814 }
2815 if (p.task == r.task) {
2816 // Here it is! Now, if this is not yet visible to the
2817 // user, then just add it without starting; it will
2818 // get started when the user navigates back to it.
2819 addPos = i+1;
2820 if (!startIt) {
2821 mHistory.add(addPos, r);
2822 r.inHistory = true;
2823 r.task.numActivities++;
2824 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2825 r.info.screenOrientation, r.fullscreen);
2826 if (VALIDATE_TOKENS) {
2827 mWindowManager.validateAppTokens(mHistory);
2828 }
2829 return;
2830 }
2831 break;
2832 }
2833 if (p.fullscreen) {
2834 startIt = false;
2835 }
2836 next = p;
2837 }
2838 }
2839
2840 // Place a new activity at top of stack, so it is next to interact
2841 // with the user.
2842 if (addPos < 0) {
2843 addPos = mHistory.size();
2844 }
2845
2846 // If we are not placing the new activity frontmost, we do not want
2847 // to deliver the onUserLeaving callback to the actual frontmost
2848 // activity
2849 if (addPos < NH) {
2850 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002851 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002852 }
2853
2854 // Slot the activity into the history stack and proceed
2855 mHistory.add(addPos, r);
2856 r.inHistory = true;
2857 r.frontOfTask = newTask;
2858 r.task.numActivities++;
2859 if (NH > 0) {
2860 // We want to show the starting preview window if we are
2861 // switching to a new task, or the next activity's process is
2862 // not currently running.
2863 boolean showStartingIcon = newTask;
2864 ProcessRecord proc = r.app;
2865 if (proc == null) {
2866 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2867 }
2868 if (proc == null || proc.thread == null) {
2869 showStartingIcon = true;
2870 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002871 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002873 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2874 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2875 mNoAnimActivities.add(r);
2876 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2877 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2878 mNoAnimActivities.remove(r);
2879 } else {
2880 mWindowManager.prepareAppTransition(newTask
2881 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2882 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2883 mNoAnimActivities.remove(r);
2884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002885 mWindowManager.addAppToken(
2886 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2887 boolean doShow = true;
2888 if (newTask) {
2889 // Even though this activity is starting fresh, we still need
2890 // to reset it to make sure we apply affinities to move any
2891 // existing activities from other tasks in to it.
2892 // If the caller has requested that the target task be
2893 // reset, then do so.
2894 if ((r.intent.getFlags()
2895 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2896 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002897 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002898 }
2899 }
2900 if (SHOW_APP_STARTING_ICON && doShow) {
2901 // Figure out if we are transitioning from another activity that is
2902 // "has the same starting icon" as the next one. This allows the
2903 // window manager to keep the previous window it had previously
2904 // created, if it still had one.
2905 HistoryRecord prev = mResumedActivity;
2906 if (prev != null) {
2907 // We don't want to reuse the previous starting preview if:
2908 // (1) The current activity is in a different task.
2909 if (prev.task != r.task) prev = null;
2910 // (2) The current activity is already displayed.
2911 else if (prev.nowVisible) prev = null;
2912 }
2913 mWindowManager.setAppStartingWindow(
2914 r, r.packageName, r.theme, r.nonLocalizedLabel,
2915 r.labelRes, r.icon, prev, showStartingIcon);
2916 }
2917 } else {
2918 // If this is the first activity, don't do any fancy animations,
2919 // because there is nothing for it to animate on top of.
2920 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2921 r.info.screenOrientation, r.fullscreen);
2922 }
2923 if (VALIDATE_TOKENS) {
2924 mWindowManager.validateAppTokens(mHistory);
2925 }
2926
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002927 if (doResume) {
2928 resumeTopActivityLocked(null);
2929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 }
2931
2932 /**
2933 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002934 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2935 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 * an instance of that activity in the stack and, if found, finish all
2937 * activities on top of it and return the instance.
2938 *
2939 * @param newR Description of the new activity being started.
2940 * @return Returns the old activity that should be continue to be used,
2941 * or null if none was found.
2942 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002943 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002944 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002946
2947 // First find the requested task.
2948 while (i > 0) {
2949 i--;
2950 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2951 if (r.task.taskId == taskId) {
2952 i++;
2953 break;
2954 }
2955 }
2956
2957 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 while (i > 0) {
2959 i--;
2960 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2961 if (r.finishing) {
2962 continue;
2963 }
2964 if (r.task.taskId != taskId) {
2965 return null;
2966 }
2967 if (r.realActivity.equals(newR.realActivity)) {
2968 // Here it is! Now finish everything in front...
2969 HistoryRecord ret = r;
2970 if (doClear) {
2971 while (i < (mHistory.size()-1)) {
2972 i++;
2973 r = (HistoryRecord)mHistory.get(i);
2974 if (r.finishing) {
2975 continue;
2976 }
2977 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2978 null, "clear")) {
2979 i--;
2980 }
2981 }
2982 }
2983
2984 // Finally, if this is a normal launch mode (that is, not
2985 // expecting onNewIntent()), then we will finish the current
2986 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002987 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2988 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002990 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 if (index >= 0) {
2992 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2993 null, "clear");
2994 }
2995 return null;
2996 }
2997 }
2998
2999 return ret;
3000 }
3001 }
3002
3003 return null;
3004 }
3005
3006 /**
3007 * Find the activity in the history stack within the given task. Returns
3008 * the index within the history at which it's found, or < 0 if not found.
3009 */
3010 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3011 int i = mHistory.size();
3012 while (i > 0) {
3013 i--;
3014 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3015 if (candidate.task.taskId != task) {
3016 break;
3017 }
3018 if (candidate.realActivity.equals(r.realActivity)) {
3019 return i;
3020 }
3021 }
3022
3023 return -1;
3024 }
3025
3026 /**
3027 * Reorder the history stack so that the activity at the given index is
3028 * brought to the front.
3029 */
3030 private final HistoryRecord moveActivityToFrontLocked(int where) {
3031 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3032 int top = mHistory.size();
3033 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3034 mHistory.add(top, newTop);
3035 oldTop.frontOfTask = false;
3036 newTop.frontOfTask = true;
3037 return newTop;
3038 }
3039
3040 /**
3041 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3042 * method will be called at the proper time.
3043 */
3044 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3045 boolean sent = false;
3046 if (r.state == ActivityState.RESUMED
3047 && r.app != null && r.app.thread != null) {
3048 try {
3049 ArrayList<Intent> ar = new ArrayList<Intent>();
3050 ar.add(new Intent(intent));
3051 r.app.thread.scheduleNewIntent(ar, r);
3052 sent = true;
3053 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003054 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 }
3056 }
3057 if (!sent) {
3058 r.addNewIntentLocked(new Intent(intent));
3059 }
3060 }
3061
3062 private final void logStartActivity(int tag, HistoryRecord r,
3063 TaskRecord task) {
3064 EventLog.writeEvent(tag,
3065 System.identityHashCode(r), task.taskId,
3066 r.shortComponentName, r.intent.getAction(),
3067 r.intent.getType(), r.intent.getDataString(),
3068 r.intent.getFlags());
3069 }
3070
3071 private final int startActivityLocked(IApplicationThread caller,
3072 Intent intent, String resolvedType,
3073 Uri[] grantedUriPermissions,
3074 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3075 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003076 int callingPid, int callingUid, boolean onlyIfNeeded,
3077 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003078 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003079
3080 HistoryRecord sourceRecord = null;
3081 HistoryRecord resultRecord = null;
3082 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003083 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003084 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003085 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3086 if (index >= 0) {
3087 sourceRecord = (HistoryRecord)mHistory.get(index);
3088 if (requestCode >= 0 && !sourceRecord.finishing) {
3089 resultRecord = sourceRecord;
3090 }
3091 }
3092 }
3093
3094 int launchFlags = intent.getFlags();
3095
3096 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3097 && sourceRecord != null) {
3098 // Transfer the result target from the source activity to the new
3099 // one being started, including any failures.
3100 if (requestCode >= 0) {
3101 return START_FORWARD_AND_REQUEST_CONFLICT;
3102 }
3103 resultRecord = sourceRecord.resultTo;
3104 resultWho = sourceRecord.resultWho;
3105 requestCode = sourceRecord.requestCode;
3106 sourceRecord.resultTo = null;
3107 if (resultRecord != null) {
3108 resultRecord.removeResultsLocked(
3109 sourceRecord, resultWho, requestCode);
3110 }
3111 }
3112
3113 int err = START_SUCCESS;
3114
3115 if (intent.getComponent() == null) {
3116 // We couldn't find a class that can handle the given Intent.
3117 // That's the end of that!
3118 err = START_INTENT_NOT_RESOLVED;
3119 }
3120
3121 if (err == START_SUCCESS && aInfo == null) {
3122 // We couldn't find the specific class specified in the Intent.
3123 // Also the end of the line.
3124 err = START_CLASS_NOT_FOUND;
3125 }
3126
3127 ProcessRecord callerApp = null;
3128 if (err == START_SUCCESS && caller != null) {
3129 callerApp = getRecordForAppLocked(caller);
3130 if (callerApp != null) {
3131 callingPid = callerApp.pid;
3132 callingUid = callerApp.info.uid;
3133 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003134 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003135 + " (pid=" + callingPid + ") when starting: "
3136 + intent.toString());
3137 err = START_PERMISSION_DENIED;
3138 }
3139 }
3140
3141 if (err != START_SUCCESS) {
3142 if (resultRecord != null) {
3143 sendActivityResultLocked(-1,
3144 resultRecord, resultWho, requestCode,
3145 Activity.RESULT_CANCELED, null);
3146 }
3147 return err;
3148 }
3149
3150 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3151 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3152 if (perm != PackageManager.PERMISSION_GRANTED) {
3153 if (resultRecord != null) {
3154 sendActivityResultLocked(-1,
3155 resultRecord, resultWho, requestCode,
3156 Activity.RESULT_CANCELED, null);
3157 }
3158 String msg = "Permission Denial: starting " + intent.toString()
3159 + " from " + callerApp + " (pid=" + callingPid
3160 + ", uid=" + callingUid + ")"
3161 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003162 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 throw new SecurityException(msg);
3164 }
3165
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003166 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003167 boolean abort = false;
3168 try {
3169 // The Intent we give to the watcher has the extra data
3170 // stripped off, since it can contain private information.
3171 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003172 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003173 aInfo.applicationInfo.packageName);
3174 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003175 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003176 }
3177
3178 if (abort) {
3179 if (resultRecord != null) {
3180 sendActivityResultLocked(-1,
3181 resultRecord, resultWho, requestCode,
3182 Activity.RESULT_CANCELED, null);
3183 }
3184 // We pretend to the caller that it was really started, but
3185 // they will just get a cancel result.
3186 return START_SUCCESS;
3187 }
3188 }
3189
3190 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3191 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003192 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003193
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003194 if (mResumedActivity == null
3195 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3196 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3197 PendingActivityLaunch pal = new PendingActivityLaunch();
3198 pal.r = r;
3199 pal.sourceRecord = sourceRecord;
3200 pal.grantedUriPermissions = grantedUriPermissions;
3201 pal.grantedMode = grantedMode;
3202 pal.onlyIfNeeded = onlyIfNeeded;
3203 mPendingActivityLaunches.add(pal);
3204 return START_SWITCHES_CANCELED;
3205 }
3206 }
3207
3208 if (mDidAppSwitch) {
3209 // This is the second allowed switch since we stopped switches,
3210 // so now just generally allow switches. Use case: user presses
3211 // home (switches disabled, switch to home, mDidAppSwitch now true);
3212 // user taps a home icon (coming from home so allowed, we hit here
3213 // and now allow anyone to switch again).
3214 mAppSwitchesAllowedTime = 0;
3215 } else {
3216 mDidAppSwitch = true;
3217 }
3218
3219 doPendingActivityLaunchesLocked(false);
3220
3221 return startActivityUncheckedLocked(r, sourceRecord,
3222 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3223 }
3224
3225 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3226 final int N = mPendingActivityLaunches.size();
3227 if (N <= 0) {
3228 return;
3229 }
3230 for (int i=0; i<N; i++) {
3231 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3232 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3233 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3234 doResume && i == (N-1));
3235 }
3236 mPendingActivityLaunches.clear();
3237 }
3238
3239 private final int startActivityUncheckedLocked(HistoryRecord r,
3240 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3241 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3242 final Intent intent = r.intent;
3243 final int callingUid = r.launchedFromUid;
3244
3245 int launchFlags = intent.getFlags();
3246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003247 // We'll invoke onUserLeaving before onPause only if the launching
3248 // activity did not explicitly state that this is an automated launch.
3249 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003250 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 "startActivity() => mUserLeaving=" + mUserLeaving);
3252
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003253 // If the caller has asked not to resume at this point, we make note
3254 // of this in the record so that we can skip it when trying to find
3255 // the top running activity.
3256 if (!doResume) {
3257 r.delayedResume = true;
3258 }
3259
3260 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3261 != 0 ? r : null;
3262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 // If the onlyIfNeeded flag is set, then we can do this if the activity
3264 // being launched is the same as the one making the call... or, as
3265 // a special case, if we do not know the caller then we count the
3266 // current top activity as the caller.
3267 if (onlyIfNeeded) {
3268 HistoryRecord checkedCaller = sourceRecord;
3269 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003270 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003271 }
3272 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3273 // Caller is not the same as launcher, so always needed.
3274 onlyIfNeeded = false;
3275 }
3276 }
3277
3278 if (grantedUriPermissions != null && callingUid > 0) {
3279 for (int i=0; i<grantedUriPermissions.length; i++) {
3280 grantUriPermissionLocked(callingUid, r.packageName,
3281 grantedUriPermissions[i], grantedMode, r);
3282 }
3283 }
3284
3285 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3286 intent, r);
3287
3288 if (sourceRecord == null) {
3289 // This activity is not being started from another... in this
3290 // case we -always- start a new task.
3291 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003292 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 -08003293 + intent);
3294 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3295 }
3296 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3297 // The original activity who is starting us is running as a single
3298 // instance... this new activity it is starting must go on its
3299 // own task.
3300 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3301 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3302 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3303 // The activity being started is a single instance... it always
3304 // gets launched into its own task.
3305 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3306 }
3307
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003308 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 // For whatever reason this activity is being launched into a new
3310 // task... yet the caller has requested a result back. Well, that
3311 // is pretty messed up, so instead immediately send back a cancel
3312 // and let the new task continue launched as normal without a
3313 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003314 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003316 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 Activity.RESULT_CANCELED, null);
3318 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 }
3320
3321 boolean addingToTask = false;
3322 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3323 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3324 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3325 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3326 // If bring to front is requested, and no result is requested, and
3327 // we can find a task that was started with this same
3328 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003329 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003330 // See if there is a task to bring to the front. If this is
3331 // a SINGLE_INSTANCE activity, there can be one and only one
3332 // instance of it in the history, and it is always in its own
3333 // unique task, so we do a special search.
3334 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3335 ? findTaskLocked(intent, r.info)
3336 : findActivityLocked(intent, r.info);
3337 if (taskTop != null) {
3338 if (taskTop.task.intent == null) {
3339 // This task was started because of movement of
3340 // the activity based on affinity... now that we
3341 // are actually launching it, we can assign the
3342 // base intent.
3343 taskTop.task.setIntent(intent, r.info);
3344 }
3345 // If the target task is not in the front, then we need
3346 // to bring it to the front... except... well, with
3347 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3348 // to have the same behavior as if a new instance was
3349 // being started, which means not bringing it to the front
3350 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003351 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 if (curTop.task != taskTop.task) {
3353 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3354 boolean callerAtFront = sourceRecord == null
3355 || curTop.task == sourceRecord.task;
3356 if (callerAtFront) {
3357 // We really do want to push this one into the
3358 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003359 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003360 }
3361 }
3362 // If the caller has requested that the target task be
3363 // reset, then do so.
3364 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3365 taskTop = resetTaskIfNeededLocked(taskTop, r);
3366 }
3367 if (onlyIfNeeded) {
3368 // We don't need to start a new activity, and
3369 // the client said not to do anything if that
3370 // is the case, so this is it! And for paranoia, make
3371 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003372 if (doResume) {
3373 resumeTopActivityLocked(null);
3374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003375 return START_RETURN_INTENT_TO_CALLER;
3376 }
3377 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3378 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3379 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3380 // In this situation we want to remove all activities
3381 // from the task up to the one being started. In most
3382 // cases this means we are resetting the task to its
3383 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003384 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003385 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003386 if (top != null) {
3387 if (top.frontOfTask) {
3388 // Activity aliases may mean we use different
3389 // intents for the top activity, so make sure
3390 // the task now has the identity of the new
3391 // intent.
3392 top.task.setIntent(r.intent, r.info);
3393 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003394 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 deliverNewIntentLocked(top, r.intent);
3396 } else {
3397 // A special case: we need to
3398 // start the activity because it is not currently
3399 // running, and the caller has asked to clear the
3400 // current task to have this activity at the top.
3401 addingToTask = true;
3402 // Now pretend like this activity is being started
3403 // by the top of its task, so it is put in the
3404 // right place.
3405 sourceRecord = taskTop;
3406 }
3407 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3408 // In this case the top activity on the task is the
3409 // same as the one being launched, so we take that
3410 // as a request to bring the task to the foreground.
3411 // If the top activity in the task is the root
3412 // activity, deliver this new intent to it if it
3413 // desires.
3414 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3415 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003416 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003417 if (taskTop.frontOfTask) {
3418 taskTop.task.setIntent(r.intent, r.info);
3419 }
3420 deliverNewIntentLocked(taskTop, r.intent);
3421 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3422 // In this case we are launching the root activity
3423 // of the task, but with a different intent. We
3424 // should start a new instance on top.
3425 addingToTask = true;
3426 sourceRecord = taskTop;
3427 }
3428 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3429 // In this case an activity is being launched in to an
3430 // existing task, without resetting that task. This
3431 // is typically the situation of launching an activity
3432 // from a notification or shortcut. We want to place
3433 // the new activity on top of the current task.
3434 addingToTask = true;
3435 sourceRecord = taskTop;
3436 } else if (!taskTop.task.rootWasReset) {
3437 // In this case we are launching in to an existing task
3438 // that has not yet been started from its front door.
3439 // The current task has been brought to the front.
3440 // Ideally, we'd probably like to place this new task
3441 // at the bottom of its stack, but that's a little hard
3442 // to do with the current organization of the code so
3443 // for now we'll just drop it.
3444 taskTop.task.setIntent(r.intent, r.info);
3445 }
3446 if (!addingToTask) {
3447 // We didn't do anything... but it was needed (a.k.a., client
3448 // don't use that intent!) And for paranoia, make
3449 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003450 if (doResume) {
3451 resumeTopActivityLocked(null);
3452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 return START_TASK_TO_FRONT;
3454 }
3455 }
3456 }
3457 }
3458
3459 //String uri = r.intent.toURI();
3460 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003461 //Slog.i(TAG, "Given intent: " + r.intent);
3462 //Slog.i(TAG, "URI is: " + uri);
3463 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464
3465 if (r.packageName != null) {
3466 // If the activity being launched is the same as the one currently
3467 // at the top, then we need to check if it should only be launched
3468 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003469 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3470 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471 if (top.realActivity.equals(r.realActivity)) {
3472 if (top.app != null && top.app.thread != null) {
3473 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3474 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3475 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003476 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477 // For paranoia, make sure we have correctly
3478 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003479 if (doResume) {
3480 resumeTopActivityLocked(null);
3481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003482 if (onlyIfNeeded) {
3483 // We don't need to start a new activity, and
3484 // the client said not to do anything if that
3485 // is the case, so this is it!
3486 return START_RETURN_INTENT_TO_CALLER;
3487 }
3488 deliverNewIntentLocked(top, r.intent);
3489 return START_DELIVERED_TO_TOP;
3490 }
3491 }
3492 }
3493 }
3494
3495 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003496 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003498 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499 Activity.RESULT_CANCELED, null);
3500 }
3501 return START_CLASS_NOT_FOUND;
3502 }
3503
3504 boolean newTask = false;
3505
3506 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003507 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003508 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3509 // todo: should do better management of integers.
3510 mCurTask++;
3511 if (mCurTask <= 0) {
3512 mCurTask = 1;
3513 }
3514 r.task = new TaskRecord(mCurTask, r.info, intent,
3515 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003516 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003517 + " in new task " + r.task);
3518 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003519 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520
3521 } else if (sourceRecord != null) {
3522 if (!addingToTask &&
3523 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3524 // In this case, we are adding the activity to an existing
3525 // task, but the caller has asked to clear that task if the
3526 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003527 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003528 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003530 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531 deliverNewIntentLocked(top, r.intent);
3532 // For paranoia, make sure we have correctly
3533 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003534 if (doResume) {
3535 resumeTopActivityLocked(null);
3536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 return START_DELIVERED_TO_TOP;
3538 }
3539 } else if (!addingToTask &&
3540 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3541 // In this case, we are launching an activity in our own task
3542 // that may already be running somewhere in the history, and
3543 // we want to shuffle it to the front of the stack if so.
3544 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3545 if (where >= 0) {
3546 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003547 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003549 if (doResume) {
3550 resumeTopActivityLocked(null);
3551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 return START_DELIVERED_TO_TOP;
3553 }
3554 }
3555 // An existing activity is starting this new activity, so we want
3556 // to keep the new one in the same task as the one that is starting
3557 // it.
3558 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003559 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003560 + " in existing task " + r.task);
3561
3562 } else {
3563 // This not being started from an existing activity, and not part
3564 // of a new task... just put it in the top task, though these days
3565 // this case should never happen.
3566 final int N = mHistory.size();
3567 HistoryRecord prev =
3568 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3569 r.task = prev != null
3570 ? prev.task
3571 : new TaskRecord(mCurTask, r.info, intent,
3572 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003573 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003574 + " in new guessed " + r.task);
3575 }
3576 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003577 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003579 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003580 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581 return START_SUCCESS;
3582 }
3583
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003584 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3585 long thisTime, long totalTime) {
3586 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3587 WaitResult w = mWaitingActivityLaunched.get(i);
3588 w.timeout = timeout;
3589 if (r != null) {
3590 w.who = new ComponentName(r.info.packageName, r.info.name);
3591 }
3592 w.thisTime = thisTime;
3593 w.totalTime = totalTime;
3594 }
3595 notify();
3596 }
3597
3598 void reportActivityVisibleLocked(HistoryRecord r) {
3599 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3600 WaitResult w = mWaitingActivityVisible.get(i);
3601 w.timeout = false;
3602 if (r != null) {
3603 w.who = new ComponentName(r.info.packageName, r.info.name);
3604 }
3605 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3606 w.thisTime = w.totalTime;
3607 }
3608 notify();
3609 }
3610
3611 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003612 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3613 int grantedMode, IBinder resultTo,
3614 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003615 boolean debug, WaitResult outResult) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 // Refuse possible leaked file descriptors
3617 if (intent != null && intent.hasFileDescriptors()) {
3618 throw new IllegalArgumentException("File descriptors passed in Intent");
3619 }
3620
The Android Open Source Project4df24232009-03-05 14:34:35 -08003621 final boolean componentSpecified = intent.getComponent() != null;
3622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003623 // Don't modify the client's object!
3624 intent = new Intent(intent);
3625
3626 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 ActivityInfo aInfo;
3628 try {
3629 ResolveInfo rInfo =
3630 ActivityThread.getPackageManager().resolveIntent(
3631 intent, resolvedType,
3632 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003633 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 aInfo = rInfo != null ? rInfo.activityInfo : null;
3635 } catch (RemoteException e) {
3636 aInfo = null;
3637 }
3638
3639 if (aInfo != null) {
3640 // Store the found target back into the intent, because now that
3641 // we have it we never want to do this again. For example, if the
3642 // user navigates back to this point in the history, we should
3643 // always restart the exact same activity.
3644 intent.setComponent(new ComponentName(
3645 aInfo.applicationInfo.packageName, aInfo.name));
3646
3647 // Don't debug things in the system process
3648 if (debug) {
3649 if (!aInfo.processName.equals("system")) {
3650 setDebugApp(aInfo.processName, true, false);
3651 }
3652 }
3653 }
3654
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003655 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003656 int callingPid;
3657 int callingUid;
3658 if (caller == null) {
3659 callingPid = Binder.getCallingPid();
3660 callingUid = Binder.getCallingUid();
3661 } else {
3662 callingPid = callingUid = -1;
3663 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 final long origId = Binder.clearCallingIdentity();
3665 int res = startActivityLocked(caller, intent, resolvedType,
3666 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003667 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003668 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003670
3671 if (outResult != null) {
3672 outResult.result = res;
3673 if (res == IActivityManager.START_SUCCESS) {
3674 mWaitingActivityLaunched.add(outResult);
3675 do {
3676 try {
3677 wait();
3678 } catch (InterruptedException e) {
3679 }
3680 } while (!outResult.timeout && outResult.who == null);
3681 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3682 HistoryRecord r = this.topRunningActivityLocked(null);
3683 if (r.nowVisible) {
3684 outResult.timeout = false;
3685 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3686 outResult.totalTime = 0;
3687 outResult.thisTime = 0;
3688 } else {
3689 outResult.thisTime = SystemClock.uptimeMillis();
3690 mWaitingActivityVisible.add(outResult);
3691 do {
3692 try {
3693 wait();
3694 } catch (InterruptedException e) {
3695 }
3696 } while (!outResult.timeout && outResult.who == null);
3697 }
3698 }
3699 }
3700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 return res;
3702 }
3703 }
3704
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003705 public final int startActivity(IApplicationThread caller,
3706 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3707 int grantedMode, IBinder resultTo,
3708 String resultWho, int requestCode, boolean onlyIfNeeded,
3709 boolean debug) {
3710 return startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3711 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, null);
3712 }
3713
3714 public final WaitResult startActivityAndWait(IApplicationThread caller,
3715 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3716 int grantedMode, IBinder resultTo,
3717 String resultWho, int requestCode, boolean onlyIfNeeded,
3718 boolean debug) {
3719 WaitResult res = new WaitResult();
3720 startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3721 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, res);
3722 return res;
3723 }
3724
3725 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003726 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003727 IBinder resultTo, String resultWho, int requestCode,
3728 int flagsMask, int flagsValues) {
3729 // Refuse possible leaked file descriptors
3730 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3731 throw new IllegalArgumentException("File descriptors passed in Intent");
3732 }
3733
3734 IIntentSender sender = intent.getTarget();
3735 if (!(sender instanceof PendingIntentRecord)) {
3736 throw new IllegalArgumentException("Bad PendingIntent object");
3737 }
3738
3739 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003740
3741 synchronized (this) {
3742 // If this is coming from the currently resumed activity, it is
3743 // effectively saying that app switches are allowed at this point.
3744 if (mResumedActivity != null
3745 && mResumedActivity.info.applicationInfo.uid ==
3746 Binder.getCallingUid()) {
3747 mAppSwitchesAllowedTime = 0;
3748 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003749 }
3750
3751 return pir.sendInner(0, fillInIntent, resolvedType,
3752 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3753 }
3754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 public boolean startNextMatchingActivity(IBinder callingActivity,
3756 Intent intent) {
3757 // Refuse possible leaked file descriptors
3758 if (intent != null && intent.hasFileDescriptors() == true) {
3759 throw new IllegalArgumentException("File descriptors passed in Intent");
3760 }
3761
3762 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003763 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 if (index < 0) {
3765 return false;
3766 }
3767 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3768 if (r.app == null || r.app.thread == null) {
3769 // The caller is not running... d'oh!
3770 return false;
3771 }
3772 intent = new Intent(intent);
3773 // The caller is not allowed to change the data.
3774 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3775 // And we are resetting to find the next component...
3776 intent.setComponent(null);
3777
3778 ActivityInfo aInfo = null;
3779 try {
3780 List<ResolveInfo> resolves =
3781 ActivityThread.getPackageManager().queryIntentActivities(
3782 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003783 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784
3785 // Look for the original activity in the list...
3786 final int N = resolves != null ? resolves.size() : 0;
3787 for (int i=0; i<N; i++) {
3788 ResolveInfo rInfo = resolves.get(i);
3789 if (rInfo.activityInfo.packageName.equals(r.packageName)
3790 && rInfo.activityInfo.name.equals(r.info.name)) {
3791 // We found the current one... the next matching is
3792 // after it.
3793 i++;
3794 if (i<N) {
3795 aInfo = resolves.get(i).activityInfo;
3796 }
3797 break;
3798 }
3799 }
3800 } catch (RemoteException e) {
3801 }
3802
3803 if (aInfo == null) {
3804 // Nobody who is next!
3805 return false;
3806 }
3807
3808 intent.setComponent(new ComponentName(
3809 aInfo.applicationInfo.packageName, aInfo.name));
3810 intent.setFlags(intent.getFlags()&~(
3811 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3812 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3813 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3814 Intent.FLAG_ACTIVITY_NEW_TASK));
3815
3816 // Okay now we need to start the new activity, replacing the
3817 // currently running activity. This is a little tricky because
3818 // we want to start the new one as if the current one is finished,
3819 // but not finish the current one first so that there is no flicker.
3820 // And thus...
3821 final boolean wasFinishing = r.finishing;
3822 r.finishing = true;
3823
3824 // Propagate reply information over to the new activity.
3825 final HistoryRecord resultTo = r.resultTo;
3826 final String resultWho = r.resultWho;
3827 final int requestCode = r.requestCode;
3828 r.resultTo = null;
3829 if (resultTo != null) {
3830 resultTo.removeResultsLocked(r, resultWho, requestCode);
3831 }
3832
3833 final long origId = Binder.clearCallingIdentity();
3834 // XXX we are not dealing with propagating grantedUriPermissions...
3835 // those are not yet exposed to user code, so there is no need.
3836 int res = startActivityLocked(r.app.thread, intent,
3837 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003838 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 Binder.restoreCallingIdentity(origId);
3840
3841 r.finishing = wasFinishing;
3842 if (res != START_SUCCESS) {
3843 return false;
3844 }
3845 return true;
3846 }
3847 }
3848
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003849 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003850 Intent intent, String resolvedType, IBinder resultTo,
3851 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003852
3853 // This is so super not safe, that only the system (or okay root)
3854 // can do it.
3855 final int callingUid = Binder.getCallingUid();
3856 if (callingUid != 0 && callingUid != Process.myUid()) {
3857 throw new SecurityException(
3858 "startActivityInPackage only available to the system");
3859 }
3860
The Android Open Source Project4df24232009-03-05 14:34:35 -08003861 final boolean componentSpecified = intent.getComponent() != null;
3862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 // Don't modify the client's object!
3864 intent = new Intent(intent);
3865
3866 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867 ActivityInfo aInfo;
3868 try {
3869 ResolveInfo rInfo =
3870 ActivityThread.getPackageManager().resolveIntent(
3871 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003872 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873 aInfo = rInfo != null ? rInfo.activityInfo : null;
3874 } catch (RemoteException e) {
3875 aInfo = null;
3876 }
3877
3878 if (aInfo != null) {
3879 // Store the found target back into the intent, because now that
3880 // we have it we never want to do this again. For example, if the
3881 // user navigates back to this point in the history, we should
3882 // always restart the exact same activity.
3883 intent.setComponent(new ComponentName(
3884 aInfo.applicationInfo.packageName, aInfo.name));
3885 }
3886
3887 synchronized(this) {
3888 return startActivityLocked(null, intent, resolvedType,
3889 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003890 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003891 }
3892 }
3893
Josh Bartel7f208742010-02-25 11:01:44 -06003894 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003895 // Remove any existing entries that are the same kind of task.
3896 int N = mRecentTasks.size();
3897 for (int i=0; i<N; i++) {
3898 TaskRecord tr = mRecentTasks.get(i);
3899 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3900 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3901 mRecentTasks.remove(i);
3902 i--;
3903 N--;
3904 if (task.intent == null) {
3905 // If the new recent task we are adding is not fully
3906 // specified, then replace it with the existing recent task.
3907 task = tr;
3908 }
3909 }
3910 }
3911 if (N >= MAX_RECENT_TASKS) {
3912 mRecentTasks.remove(N-1);
3913 }
3914 mRecentTasks.add(0, task);
3915 }
3916
3917 public void setRequestedOrientation(IBinder token,
3918 int requestedOrientation) {
3919 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003920 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003921 if (index < 0) {
3922 return;
3923 }
3924 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3925 final long origId = Binder.clearCallingIdentity();
3926 mWindowManager.setAppOrientation(r, requestedOrientation);
3927 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003928 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 r.mayFreezeScreenLocked(r.app) ? r : null);
3930 if (config != null) {
3931 r.frozenBeforeDestroy = true;
3932 if (!updateConfigurationLocked(config, r)) {
3933 resumeTopActivityLocked(null);
3934 }
3935 }
3936 Binder.restoreCallingIdentity(origId);
3937 }
3938 }
3939
3940 public int getRequestedOrientation(IBinder token) {
3941 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003942 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 if (index < 0) {
3944 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3945 }
3946 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3947 return mWindowManager.getAppOrientation(r);
3948 }
3949 }
3950
3951 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003952 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3954 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3955 if (!r.finishing) {
3956 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3957 "no-history");
3958 }
3959 } else if (r.app != null && r.app.thread != null) {
3960 if (mFocusedActivity == r) {
3961 setFocusedActivityLocked(topRunningActivityLocked(null));
3962 }
3963 r.resumeKeyDispatchingLocked();
3964 try {
3965 r.stopped = false;
3966 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003967 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 TAG, "Stopping visible=" + r.visible + " for " + r);
3969 if (!r.visible) {
3970 mWindowManager.setAppVisibility(r, false);
3971 }
3972 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3973 } catch (Exception e) {
3974 // Maybe just ignore exceptions here... if the process
3975 // has crashed, our death notification will clean things
3976 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003977 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003978 // Just in case, assume it to be stopped.
3979 r.stopped = true;
3980 r.state = ActivityState.STOPPED;
3981 if (r.configDestroy) {
3982 destroyActivityLocked(r, true);
3983 }
3984 }
3985 }
3986 }
3987
3988 /**
3989 * @return Returns true if the activity is being finished, false if for
3990 * some reason it is being left as-is.
3991 */
3992 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3993 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003994 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 TAG, "Finishing activity: token=" + token
3996 + ", result=" + resultCode + ", data=" + resultData);
3997
Dianne Hackborn75b03852009-06-12 15:43:26 -07003998 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 if (index < 0) {
4000 return false;
4001 }
4002 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4003
4004 // Is this the last activity left?
4005 boolean lastActivity = true;
4006 for (int i=mHistory.size()-1; i>=0; i--) {
4007 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4008 if (!p.finishing && p != r) {
4009 lastActivity = false;
4010 break;
4011 }
4012 }
4013
4014 // If this is the last activity, but it is the home activity, then
4015 // just don't finish it.
4016 if (lastActivity) {
4017 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4018 return false;
4019 }
4020 }
4021
4022 finishActivityLocked(r, index, resultCode, resultData, reason);
4023 return true;
4024 }
4025
4026 /**
4027 * @return Returns true if this activity has been removed from the history
4028 * list, or false if it is still in the list and will be removed later.
4029 */
4030 private final boolean finishActivityLocked(HistoryRecord r, int index,
4031 int resultCode, Intent resultData, String reason) {
4032 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004033 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 return false;
4035 }
4036
4037 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004038 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004039 System.identityHashCode(r),
4040 r.task.taskId, r.shortComponentName, reason);
4041 r.task.numActivities--;
4042 if (r.frontOfTask && index < (mHistory.size()-1)) {
4043 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4044 if (next.task == r.task) {
4045 next.frontOfTask = true;
4046 }
4047 }
4048
4049 r.pauseKeyDispatchingLocked();
4050 if (mFocusedActivity == r) {
4051 setFocusedActivityLocked(topRunningActivityLocked(null));
4052 }
4053
4054 // send the result
4055 HistoryRecord resultTo = r.resultTo;
4056 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004057 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004058 + " who=" + r.resultWho + " req=" + r.requestCode
4059 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060 if (r.info.applicationInfo.uid > 0) {
4061 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4062 r.packageName, resultData, r);
4063 }
4064 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4065 resultData);
4066 r.resultTo = null;
4067 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004068 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004069
4070 // Make sure this HistoryRecord is not holding on to other resources,
4071 // because clients have remote IPC references to this object so we
4072 // can't assume that will go away and want to avoid circular IPC refs.
4073 r.results = null;
4074 r.pendingResults = null;
4075 r.newIntents = null;
4076 r.icicle = null;
4077
4078 if (mPendingThumbnails.size() > 0) {
4079 // There are clients waiting to receive thumbnails so, in case
4080 // this is an activity that someone is waiting for, add it
4081 // to the pending list so we can correctly update the clients.
4082 mCancelledThumbnails.add(r);
4083 }
4084
4085 if (mResumedActivity == r) {
4086 boolean endTask = index <= 0
4087 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004088 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004089 "Prepare close transition: finishing " + r);
4090 mWindowManager.prepareAppTransition(endTask
4091 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4092 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4093
4094 // Tell window manager to prepare for this one to be removed.
4095 mWindowManager.setAppVisibility(r, false);
4096
4097 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004098 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4099 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100 startPausingLocked(false, false);
4101 }
4102
4103 } else if (r.state != ActivityState.PAUSING) {
4104 // If the activity is PAUSING, we will complete the finish once
4105 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004106 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 return finishCurrentActivityLocked(r, index,
4108 FINISH_AFTER_PAUSE) == null;
4109 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004110 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004111 }
4112
4113 return false;
4114 }
4115
4116 private static final int FINISH_IMMEDIATELY = 0;
4117 private static final int FINISH_AFTER_PAUSE = 1;
4118 private static final int FINISH_AFTER_VISIBLE = 2;
4119
4120 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4121 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004122 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 if (index < 0) {
4124 return null;
4125 }
4126
4127 return finishCurrentActivityLocked(r, index, mode);
4128 }
4129
4130 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4131 int index, int mode) {
4132 // First things first: if this activity is currently visible,
4133 // and the resumed activity is not yet visible, then hold off on
4134 // finishing until the resumed one becomes visible.
4135 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4136 if (!mStoppingActivities.contains(r)) {
4137 mStoppingActivities.add(r);
4138 if (mStoppingActivities.size() > 3) {
4139 // If we already have a few activities waiting to stop,
4140 // then give up on things going idle and start clearing
4141 // them out.
4142 Message msg = Message.obtain();
4143 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4144 mHandler.sendMessage(msg);
4145 }
4146 }
4147 r.state = ActivityState.STOPPING;
4148 updateOomAdjLocked();
4149 return r;
4150 }
4151
4152 // make sure the record is cleaned out of other places.
4153 mStoppingActivities.remove(r);
4154 mWaitingVisibleActivities.remove(r);
4155 if (mResumedActivity == r) {
4156 mResumedActivity = null;
4157 }
4158 final ActivityState prevState = r.state;
4159 r.state = ActivityState.FINISHING;
4160
4161 if (mode == FINISH_IMMEDIATELY
4162 || prevState == ActivityState.STOPPED
4163 || prevState == ActivityState.INITIALIZING) {
4164 // If this activity is already stopped, we can just finish
4165 // it right now.
4166 return destroyActivityLocked(r, true) ? null : r;
4167 } else {
4168 // Need to go through the full pause cycle to get this
4169 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004170 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171 mFinishingActivities.add(r);
4172 resumeTopActivityLocked(null);
4173 }
4174 return r;
4175 }
4176
4177 /**
4178 * This is the internal entry point for handling Activity.finish().
4179 *
4180 * @param token The Binder token referencing the Activity we want to finish.
4181 * @param resultCode Result code, if any, from this Activity.
4182 * @param resultData Result data (Intent), if any, from this Activity.
4183 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004184 * @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 -08004185 */
4186 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4187 // Refuse possible leaked file descriptors
4188 if (resultData != null && resultData.hasFileDescriptors() == true) {
4189 throw new IllegalArgumentException("File descriptors passed in Intent");
4190 }
4191
4192 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004193 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 // Find the first activity that is not finishing.
4195 HistoryRecord next = topRunningActivityLocked(token, 0);
4196 if (next != null) {
4197 // ask watcher if this is allowed
4198 boolean resumeOK = true;
4199 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004200 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004201 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004202 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004203 }
4204
4205 if (!resumeOK) {
4206 return false;
4207 }
4208 }
4209 }
4210 final long origId = Binder.clearCallingIdentity();
4211 boolean res = requestFinishActivityLocked(token, resultCode,
4212 resultData, "app-request");
4213 Binder.restoreCallingIdentity(origId);
4214 return res;
4215 }
4216 }
4217
4218 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4219 String resultWho, int requestCode, int resultCode, Intent data) {
4220
4221 if (callingUid > 0) {
4222 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4223 data, r);
4224 }
4225
Joe Onorato8a9b2202010-02-26 18:56:32 -08004226 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004227 + " : who=" + resultWho + " req=" + requestCode
4228 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4230 try {
4231 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4232 list.add(new ResultInfo(resultWho, requestCode,
4233 resultCode, data));
4234 r.app.thread.scheduleSendResult(r, list);
4235 return;
4236 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004237 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 }
4239 }
4240
4241 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4242 }
4243
4244 public final void finishSubActivity(IBinder token, String resultWho,
4245 int requestCode) {
4246 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004247 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004248 if (index < 0) {
4249 return;
4250 }
4251 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4252
4253 final long origId = Binder.clearCallingIdentity();
4254
4255 int i;
4256 for (i=mHistory.size()-1; i>=0; i--) {
4257 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4258 if (r.resultTo == self && r.requestCode == requestCode) {
4259 if ((r.resultWho == null && resultWho == null) ||
4260 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4261 finishActivityLocked(r, i,
4262 Activity.RESULT_CANCELED, null, "request-sub");
4263 }
4264 }
4265 }
4266
4267 Binder.restoreCallingIdentity(origId);
4268 }
4269 }
4270
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004271 public boolean willActivityBeVisible(IBinder token) {
4272 synchronized(this) {
4273 int i;
4274 for (i=mHistory.size()-1; i>=0; i--) {
4275 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4276 if (r == token) {
4277 return true;
4278 }
4279 if (r.fullscreen && !r.finishing) {
4280 return false;
4281 }
4282 }
4283 return true;
4284 }
4285 }
4286
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004287 public void overridePendingTransition(IBinder token, String packageName,
4288 int enterAnim, int exitAnim) {
4289 synchronized(this) {
4290 int index = indexOfTokenLocked(token);
4291 if (index < 0) {
4292 return;
4293 }
4294 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4295
4296 final long origId = Binder.clearCallingIdentity();
4297
4298 if (self.state == ActivityState.RESUMED
4299 || self.state == ActivityState.PAUSING) {
4300 mWindowManager.overridePendingAppTransition(packageName,
4301 enterAnim, exitAnim);
4302 }
4303
4304 Binder.restoreCallingIdentity(origId);
4305 }
4306 }
4307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004308 /**
4309 * Perform clean-up of service connections in an activity record.
4310 */
4311 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4312 // Throw away any services that have been bound by this activity.
4313 if (r.connections != null) {
4314 Iterator<ConnectionRecord> it = r.connections.iterator();
4315 while (it.hasNext()) {
4316 ConnectionRecord c = it.next();
4317 removeConnectionLocked(c, null, r);
4318 }
4319 r.connections = null;
4320 }
4321 }
4322
4323 /**
4324 * Perform the common clean-up of an activity record. This is called both
4325 * as part of destroyActivityLocked() (when destroying the client-side
4326 * representation) and cleaning things up as a result of its hosting
4327 * processing going away, in which case there is no remaining client-side
4328 * state to destroy so only the cleanup here is needed.
4329 */
4330 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4331 if (mResumedActivity == r) {
4332 mResumedActivity = null;
4333 }
4334 if (mFocusedActivity == r) {
4335 mFocusedActivity = null;
4336 }
4337
4338 r.configDestroy = false;
4339 r.frozenBeforeDestroy = false;
4340
4341 // Make sure this record is no longer in the pending finishes list.
4342 // This could happen, for example, if we are trimming activities
4343 // down to the max limit while they are still waiting to finish.
4344 mFinishingActivities.remove(r);
4345 mWaitingVisibleActivities.remove(r);
4346
4347 // Remove any pending results.
4348 if (r.finishing && r.pendingResults != null) {
4349 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4350 PendingIntentRecord rec = apr.get();
4351 if (rec != null) {
4352 cancelIntentSenderLocked(rec, false);
4353 }
4354 }
4355 r.pendingResults = null;
4356 }
4357
4358 if (cleanServices) {
4359 cleanUpActivityServicesLocked(r);
4360 }
4361
4362 if (mPendingThumbnails.size() > 0) {
4363 // There are clients waiting to receive thumbnails so, in case
4364 // this is an activity that someone is waiting for, add it
4365 // to the pending list so we can correctly update the clients.
4366 mCancelledThumbnails.add(r);
4367 }
4368
4369 // Get rid of any pending idle timeouts.
4370 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4371 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4372 }
4373
4374 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4375 if (r.state != ActivityState.DESTROYED) {
4376 mHistory.remove(r);
4377 r.inHistory = false;
4378 r.state = ActivityState.DESTROYED;
4379 mWindowManager.removeAppToken(r);
4380 if (VALIDATE_TOKENS) {
4381 mWindowManager.validateAppTokens(mHistory);
4382 }
4383 cleanUpActivityServicesLocked(r);
4384 removeActivityUriPermissionsLocked(r);
4385 }
4386 }
4387
4388 /**
4389 * Destroy the current CLIENT SIDE instance of an activity. This may be
4390 * called both when actually finishing an activity, or when performing
4391 * a configuration switch where we destroy the current client-side object
4392 * but then create a new client-side object for this same HistoryRecord.
4393 */
4394 private final boolean destroyActivityLocked(HistoryRecord r,
4395 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004396 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 TAG, "Removing activity: token=" + r
4398 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004399 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400 System.identityHashCode(r),
4401 r.task.taskId, r.shortComponentName);
4402
4403 boolean removedFromHistory = false;
4404
4405 cleanUpActivityLocked(r, false);
4406
Dianne Hackborn03abb812010-01-04 18:43:19 -08004407 final boolean hadApp = r.app != null;
4408
4409 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 if (removeFromApp) {
4411 int idx = r.app.activities.indexOf(r);
4412 if (idx >= 0) {
4413 r.app.activities.remove(idx);
4414 }
4415 if (r.persistent) {
4416 decPersistentCountLocked(r.app);
4417 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004418 if (r.app.activities.size() == 0) {
4419 // No longer have activities, so update location in
4420 // LRU list.
4421 updateLruProcessLocked(r.app, true, false);
4422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 }
4424
4425 boolean skipDestroy = false;
4426
4427 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004428 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4430 r.configChangeFlags);
4431 } catch (Exception e) {
4432 // We can just ignore exceptions here... if the process
4433 // has crashed, our death notification will clean things
4434 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004435 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 if (r.finishing) {
4437 removeActivityFromHistoryLocked(r);
4438 removedFromHistory = true;
4439 skipDestroy = true;
4440 }
4441 }
4442
4443 r.app = null;
4444 r.nowVisible = false;
4445
4446 if (r.finishing && !skipDestroy) {
4447 r.state = ActivityState.DESTROYING;
4448 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4449 msg.obj = r;
4450 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4451 } else {
4452 r.state = ActivityState.DESTROYED;
4453 }
4454 } else {
4455 // remove this record from the history.
4456 if (r.finishing) {
4457 removeActivityFromHistoryLocked(r);
4458 removedFromHistory = true;
4459 } else {
4460 r.state = ActivityState.DESTROYED;
4461 }
4462 }
4463
4464 r.configChangeFlags = 0;
4465
Dianne Hackborn03abb812010-01-04 18:43:19 -08004466 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004467 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 }
4469
4470 return removedFromHistory;
4471 }
4472
Dianne Hackborn03abb812010-01-04 18:43:19 -08004473 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004474 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004475 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 TAG, "Removing app " + app + " from list " + list
4477 + " with " + i + " entries");
4478 while (i > 0) {
4479 i--;
4480 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004481 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4483 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004484 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 list.remove(i);
4486 }
4487 }
4488 }
4489
4490 /**
4491 * Main function for removing an existing process from the activity manager
4492 * as a result of that process going away. Clears out all connections
4493 * to the process.
4494 */
4495 private final void handleAppDiedLocked(ProcessRecord app,
4496 boolean restarting) {
4497 cleanUpApplicationRecordLocked(app, restarting, -1);
4498 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004499 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 }
4501
4502 // Just in case...
4503 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004504 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 mPausingActivity = null;
4506 }
4507 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4508 mLastPausedActivity = null;
4509 }
4510
4511 // Remove this application's activities from active lists.
4512 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4513 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4514 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4515 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4516
4517 boolean atTop = true;
4518 boolean hasVisibleActivities = false;
4519
4520 // Clean out the history list.
4521 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004522 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004523 TAG, "Removing app " + app + " from history with " + i + " entries");
4524 while (i > 0) {
4525 i--;
4526 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004527 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004528 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4529 if (r.app == app) {
4530 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004531 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004532 TAG, "Removing this entry! frozen=" + r.haveState
4533 + " finishing=" + r.finishing);
4534 mHistory.remove(i);
4535
4536 r.inHistory = false;
4537 mWindowManager.removeAppToken(r);
4538 if (VALIDATE_TOKENS) {
4539 mWindowManager.validateAppTokens(mHistory);
4540 }
4541 removeActivityUriPermissionsLocked(r);
4542
4543 } else {
4544 // We have the current state for this activity, so
4545 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004546 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004547 TAG, "Keeping entry, setting app to null");
4548 if (r.visible) {
4549 hasVisibleActivities = true;
4550 }
4551 r.app = null;
4552 r.nowVisible = false;
4553 if (!r.haveState) {
4554 r.icicle = null;
4555 }
4556 }
4557
4558 cleanUpActivityLocked(r, true);
4559 r.state = ActivityState.STOPPED;
4560 }
4561 atTop = false;
4562 }
4563
4564 app.activities.clear();
4565
4566 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004567 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 + " running instrumentation " + app.instrumentationClass);
4569 Bundle info = new Bundle();
4570 info.putString("shortMsg", "Process crashed.");
4571 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4572 }
4573
4574 if (!restarting) {
4575 if (!resumeTopActivityLocked(null)) {
4576 // If there was nothing to resume, and we are not already
4577 // restarting this process, but there is a visible activity that
4578 // is hosted by the process... then make sure all visible
4579 // activities are running, taking care of restarting this
4580 // process.
4581 if (hasVisibleActivities) {
4582 ensureActivitiesVisibleLocked(null, 0);
4583 }
4584 }
4585 }
4586 }
4587
4588 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4589 IBinder threadBinder = thread.asBinder();
4590
4591 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004592 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4593 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4595 return i;
4596 }
4597 }
4598 return -1;
4599 }
4600
4601 private final ProcessRecord getRecordForAppLocked(
4602 IApplicationThread thread) {
4603 if (thread == null) {
4604 return null;
4605 }
4606
4607 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004608 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 }
4610
4611 private final void appDiedLocked(ProcessRecord app, int pid,
4612 IApplicationThread thread) {
4613
4614 mProcDeaths[0]++;
4615
Magnus Edlund7bb25812010-02-24 15:45:06 +01004616 // Clean up already done if the process has been re-started.
4617 if (app.pid == pid && app.thread != null &&
4618 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004619 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004620 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004621 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004622 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 TAG, "Dying app: " + app + ", pid: " + pid
4624 + ", thread: " + thread.asBinder());
4625 boolean doLowMem = app.instrumentationClass == null;
4626 handleAppDiedLocked(app, false);
4627
4628 if (doLowMem) {
4629 // If there are no longer any background processes running,
4630 // and the app that died was not running instrumentation,
4631 // then tell everyone we are now low on memory.
4632 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004633 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4634 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4636 haveBg = true;
4637 break;
4638 }
4639 }
4640
4641 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004642 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004643 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004644 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004645 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4646 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004647 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004648 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4649 // The low memory report is overriding any current
4650 // state for a GC request. Make sure to do
4651 // visible/foreground processes first.
4652 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4653 rec.lastRequestedGc = 0;
4654 } else {
4655 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004657 rec.reportLowMemory = true;
4658 rec.lastLowMemory = now;
4659 mProcessesToGc.remove(rec);
4660 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004661 }
4662 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004663 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004664 }
4665 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004666 } else if (app.pid != pid) {
4667 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004668 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004669 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004670 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004671 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004672 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004673 + thread.asBinder());
4674 }
4675 }
4676
Dan Egnor42471dd2010-01-07 17:25:22 -08004677 /**
4678 * If a stack trace dump file is configured, dump process stack traces.
4679 * @param pids of dalvik VM processes to dump stack traces for
4680 * @return file containing stack traces, or null if no dump file is configured
4681 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004682 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004683 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4684 if (tracesPath == null || tracesPath.length() == 0) {
4685 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004686 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004687
4688 File tracesFile = new File(tracesPath);
4689 try {
4690 File tracesDir = tracesFile.getParentFile();
4691 if (!tracesDir.exists()) tracesFile.mkdirs();
4692 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4693
4694 if (tracesFile.exists()) tracesFile.delete();
4695 tracesFile.createNewFile();
4696 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4697 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004698 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004699 return null;
4700 }
4701
4702 // Use a FileObserver to detect when traces finish writing.
4703 // The order of traces is considered important to maintain for legibility.
4704 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4705 public synchronized void onEvent(int event, String path) { notify(); }
4706 };
4707
4708 try {
4709 observer.startWatching();
4710 int num = pids.size();
4711 for (int i = 0; i < num; i++) {
4712 synchronized (observer) {
4713 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4714 observer.wait(200); // Wait for write-close, give up after 200msec
4715 }
4716 }
4717 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004718 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004719 } finally {
4720 observer.stopWatching();
4721 }
4722
4723 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 }
4725
Dan Egnor42471dd2010-01-07 17:25:22 -08004726 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4727 HistoryRecord parent, final String annotation) {
Mike Lockwoodb62f9592010-03-12 07:55:23 -05004728 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4729 if (mShuttingDown || app.notResponding || app.crashing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730 return;
4731 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004734 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4735 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004736
Dan Egnor42471dd2010-01-07 17:25:22 -08004737 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4738 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4739 pids.add(app.pid);
4740
4741 int parentPid = app.pid;
4742 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4743 if (parentPid != app.pid) pids.add(parentPid);
4744
4745 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4746
4747 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4748 ProcessRecord r = mLruProcesses.get(i);
4749 if (r != null && r.thread != null) {
4750 int pid = r.pid;
4751 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752 }
4753 }
4754
Dan Egnor42471dd2010-01-07 17:25:22 -08004755 File tracesFile = dumpStackTraces(pids);
4756
4757 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004758 StringBuilder info = mStringBuilder;
4759 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004760 info.append("ANR in ").append(app.processName);
4761 if (activity != null && activity.shortComponentName != null) {
4762 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004763 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004764 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004766 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004768 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004769 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771
Dan Egnor42471dd2010-01-07 17:25:22 -08004772 String cpuInfo = null;
4773 if (MONITOR_CPU_USAGE) {
4774 updateCpuStatsNow();
4775 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4776 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 }
4778
Joe Onorato8a9b2202010-02-26 18:56:32 -08004779 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004780 if (tracesFile == null) {
4781 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4782 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4783 }
4784
4785 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4786
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004787 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004789 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4790 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004792 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4793 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004794 }
4795 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004796 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 }
4798 }
4799
Dan Egnor42471dd2010-01-07 17:25:22 -08004800 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4801 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4802 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4803 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4804 Process.killProcess(app.pid);
4805 return;
4806 }
4807
4808 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 makeAppNotRespondingLocked(app,
4810 activity != null ? activity.shortComponentName : null,
4811 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004812 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004813
4814 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 Message msg = Message.obtain();
4816 HashMap map = new HashMap();
4817 msg.what = SHOW_NOT_RESPONDING_MSG;
4818 msg.obj = map;
4819 map.put("app", app);
4820 if (activity != null) {
4821 map.put("activity", activity);
4822 }
4823
4824 mHandler.sendMessage(msg);
4825 return;
4826 }
4827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828 private final void decPersistentCountLocked(ProcessRecord app)
4829 {
4830 app.persistentActivities--;
4831 if (app.persistentActivities > 0) {
4832 // Still more of 'em...
4833 return;
4834 }
4835 if (app.persistent) {
4836 // Ah, but the application itself is persistent. Whatever!
4837 return;
4838 }
4839
4840 // App is no longer persistent... make sure it and the ones
4841 // following it in the LRU list have the correc oom_adj.
4842 updateOomAdjLocked();
4843 }
4844
4845 public void setPersistent(IBinder token, boolean isPersistent) {
4846 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4847 != PackageManager.PERMISSION_GRANTED) {
4848 String msg = "Permission Denial: setPersistent() from pid="
4849 + Binder.getCallingPid()
4850 + ", uid=" + Binder.getCallingUid()
4851 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004852 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 throw new SecurityException(msg);
4854 }
4855
4856 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004857 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 if (index < 0) {
4859 return;
4860 }
4861 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4862 ProcessRecord app = r.app;
4863
Joe Onorato8a9b2202010-02-26 18:56:32 -08004864 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 TAG, "Setting persistence " + isPersistent + ": " + r);
4866
4867 if (isPersistent) {
4868 if (r.persistent) {
4869 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004870 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004871 return;
4872 }
4873 r.persistent = true;
4874 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004875 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 if (app.persistentActivities > 1) {
4877 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004878 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 return;
4880 }
4881 if (app.persistent) {
4882 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004883 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004884 return;
4885 }
4886
4887 // App is now persistent... make sure it and the ones
4888 // following it now have the correct oom_adj.
4889 final long origId = Binder.clearCallingIdentity();
4890 updateOomAdjLocked();
4891 Binder.restoreCallingIdentity(origId);
4892
4893 } else {
4894 if (!r.persistent) {
4895 // Okay okay, I heard you already!
4896 return;
4897 }
4898 r.persistent = false;
4899 final long origId = Binder.clearCallingIdentity();
4900 decPersistentCountLocked(app);
4901 Binder.restoreCallingIdentity(origId);
4902
4903 }
4904 }
4905 }
4906
4907 public boolean clearApplicationUserData(final String packageName,
4908 final IPackageDataObserver observer) {
4909 int uid = Binder.getCallingUid();
4910 int pid = Binder.getCallingPid();
4911 long callingId = Binder.clearCallingIdentity();
4912 try {
4913 IPackageManager pm = ActivityThread.getPackageManager();
4914 int pkgUid = -1;
4915 synchronized(this) {
4916 try {
4917 pkgUid = pm.getPackageUid(packageName);
4918 } catch (RemoteException e) {
4919 }
4920 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004921 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004922 return false;
4923 }
4924 if (uid == pkgUid || checkComponentPermission(
4925 android.Manifest.permission.CLEAR_APP_USER_DATA,
4926 pid, uid, -1)
4927 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004928 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 } else {
4930 throw new SecurityException(pid+" does not have permission:"+
4931 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4932 "for process:"+packageName);
4933 }
4934 }
4935
4936 try {
4937 //clear application user data
4938 pm.clearApplicationUserData(packageName, observer);
4939 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4940 Uri.fromParts("package", packageName, null));
4941 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06004942 synchronized (this) {
4943 broadcastIntentLocked(null, null, intent,
4944 null, null, 0, null, null, null,
4945 false, false, MY_PID, Process.SYSTEM_UID);
4946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004947 } catch (RemoteException e) {
4948 }
4949 } finally {
4950 Binder.restoreCallingIdentity(callingId);
4951 }
4952 return true;
4953 }
4954
Dianne Hackborn03abb812010-01-04 18:43:19 -08004955 public void killBackgroundProcesses(final String packageName) {
4956 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4957 != PackageManager.PERMISSION_GRANTED &&
4958 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4959 != PackageManager.PERMISSION_GRANTED) {
4960 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 + Binder.getCallingPid()
4962 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004963 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004964 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 throw new SecurityException(msg);
4966 }
4967
4968 long callingId = Binder.clearCallingIdentity();
4969 try {
4970 IPackageManager pm = ActivityThread.getPackageManager();
4971 int pkgUid = -1;
4972 synchronized(this) {
4973 try {
4974 pkgUid = pm.getPackageUid(packageName);
4975 } catch (RemoteException e) {
4976 }
4977 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004978 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 return;
4980 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004981 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004982 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004983 }
4984 } finally {
4985 Binder.restoreCallingIdentity(callingId);
4986 }
4987 }
4988
4989 public void forceStopPackage(final String packageName) {
4990 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4991 != PackageManager.PERMISSION_GRANTED) {
4992 String msg = "Permission Denial: forceStopPackage() from pid="
4993 + Binder.getCallingPid()
4994 + ", uid=" + Binder.getCallingUid()
4995 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004996 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004997 throw new SecurityException(msg);
4998 }
4999
5000 long callingId = Binder.clearCallingIdentity();
5001 try {
5002 IPackageManager pm = ActivityThread.getPackageManager();
5003 int pkgUid = -1;
5004 synchronized(this) {
5005 try {
5006 pkgUid = pm.getPackageUid(packageName);
5007 } catch (RemoteException e) {
5008 }
5009 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005010 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005011 return;
5012 }
5013 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 }
5015 } finally {
5016 Binder.restoreCallingIdentity(callingId);
5017 }
5018 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005019
5020 /*
5021 * The pkg name and uid have to be specified.
5022 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5023 */
5024 public void killApplicationWithUid(String pkg, int uid) {
5025 if (pkg == null) {
5026 return;
5027 }
5028 // Make sure the uid is valid.
5029 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005030 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005031 return;
5032 }
5033 int callerUid = Binder.getCallingUid();
5034 // Only the system server can kill an application
5035 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005036 // Post an aysnc message to kill the application
5037 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5038 msg.arg1 = uid;
5039 msg.arg2 = 0;
5040 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005041 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005042 } else {
5043 throw new SecurityException(callerUid + " cannot kill pkg: " +
5044 pkg);
5045 }
5046 }
5047
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005048 public void closeSystemDialogs(String reason) {
5049 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5050 if (reason != null) {
5051 intent.putExtra("reason", reason);
5052 }
5053
5054 final int uid = Binder.getCallingUid();
5055 final long origId = Binder.clearCallingIdentity();
5056 synchronized (this) {
5057 int i = mWatchers.beginBroadcast();
5058 while (i > 0) {
5059 i--;
5060 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5061 if (w != null) {
5062 try {
5063 w.closingSystemDialogs(reason);
5064 } catch (RemoteException e) {
5065 }
5066 }
5067 }
5068 mWatchers.finishBroadcast();
5069
Dianne Hackbornffa42482009-09-23 22:20:11 -07005070 mWindowManager.closeSystemDialogs(reason);
5071
5072 for (i=mHistory.size()-1; i>=0; i--) {
5073 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5074 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5075 finishActivityLocked(r, i,
5076 Activity.RESULT_CANCELED, null, "close-sys");
5077 }
5078 }
5079
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005080 broadcastIntentLocked(null, null, intent, null,
5081 null, 0, null, null, null, false, false, -1, uid);
5082 }
5083 Binder.restoreCallingIdentity(origId);
5084 }
5085
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005086 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005087 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005088 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5089 for (int i=pids.length-1; i>=0; i--) {
5090 infos[i] = new Debug.MemoryInfo();
5091 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005092 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005093 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005094 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005095
5096 public void killApplicationProcess(String processName, int uid) {
5097 if (processName == null) {
5098 return;
5099 }
5100
5101 int callerUid = Binder.getCallingUid();
5102 // Only the system server can kill an application
5103 if (callerUid == Process.SYSTEM_UID) {
5104 synchronized (this) {
5105 ProcessRecord app = getProcessRecordLocked(processName, uid);
5106 if (app != null) {
5107 try {
5108 app.thread.scheduleSuicide();
5109 } catch (RemoteException e) {
5110 // If the other end already died, then our work here is done.
5111 }
5112 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005113 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005114 + processName + " / " + uid);
5115 }
5116 }
5117 } else {
5118 throw new SecurityException(callerUid + " cannot kill app process: " +
5119 processName);
5120 }
5121 }
5122
Dianne Hackborn03abb812010-01-04 18:43:19 -08005123 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005124 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005125 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5126 Uri.fromParts("package", packageName, null));
5127 intent.putExtra(Intent.EXTRA_UID, uid);
5128 broadcastIntentLocked(null, null, intent,
5129 null, null, 0, null, null, null,
5130 false, false, MY_PID, Process.SYSTEM_UID);
5131 }
5132
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005133 private final boolean killPackageProcessesLocked(String packageName, int uid,
5134 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005135 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005136
Dianne Hackborn03abb812010-01-04 18:43:19 -08005137 // Remove all processes this package may have touched: all with the
5138 // same UID (except for the system or root user), and all whose name
5139 // matches the package name.
5140 final String procNamePrefix = packageName + ":";
5141 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5142 final int NA = apps.size();
5143 for (int ia=0; ia<NA; ia++) {
5144 ProcessRecord app = apps.valueAt(ia);
5145 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005146 if (doit) {
5147 procs.add(app);
5148 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005149 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5150 || app.processName.equals(packageName)
5151 || app.processName.startsWith(procNamePrefix)) {
5152 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005153 if (!doit) {
5154 return true;
5155 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005156 app.removed = true;
5157 procs.add(app);
5158 }
5159 }
5160 }
5161 }
5162
5163 int N = procs.size();
5164 for (int i=0; i<N; i++) {
5165 removeProcessLocked(procs.get(i), callerWillRestart);
5166 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005167 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005168 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005169
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005170 private final boolean forceStopPackageLocked(String name, int uid,
5171 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172 int i, N;
5173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005174 if (uid < 0) {
5175 try {
5176 uid = ActivityThread.getPackageManager().getPackageUid(name);
5177 } catch (RemoteException e) {
5178 }
5179 }
5180
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005181 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005182 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005183
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005184 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5185 while (badApps.hasNext()) {
5186 SparseArray<Long> ba = badApps.next();
5187 if (ba.get(uid) != null) {
5188 badApps.remove();
5189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005190 }
5191 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005192
5193 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5194 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195
5196 for (i=mHistory.size()-1; i>=0; i--) {
5197 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5198 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005199 if (!doit) {
5200 return true;
5201 }
5202 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005203 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 if (r.app != null) {
5205 r.app.removed = true;
5206 }
5207 r.app = null;
5208 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5209 }
5210 }
5211
5212 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5213 for (ServiceRecord service : mServices.values()) {
5214 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005215 if (!doit) {
5216 return true;
5217 }
5218 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005219 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 if (service.app != null) {
5221 service.app.removed = true;
5222 }
5223 service.app = null;
5224 services.add(service);
5225 }
5226 }
5227
5228 N = services.size();
5229 for (i=0; i<N; i++) {
5230 bringDownServiceLocked(services.get(i), true);
5231 }
5232
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005233 if (doit) {
5234 if (purgeCache) {
5235 AttributeCache ac = AttributeCache.instance();
5236 if (ac != null) {
5237 ac.removePackage(name);
5238 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005239 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005240 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005241 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005242
5243 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005244 }
5245
5246 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5247 final String name = app.processName;
5248 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005249 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005250 TAG, "Force removing process " + app + " (" + name
5251 + "/" + uid + ")");
5252
5253 mProcessNames.remove(name, uid);
5254 boolean needRestart = false;
5255 if (app.pid > 0 && app.pid != MY_PID) {
5256 int pid = app.pid;
5257 synchronized (mPidsSelfLocked) {
5258 mPidsSelfLocked.remove(pid);
5259 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5260 }
5261 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005262 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 Process.killProcess(pid);
5264
5265 if (app.persistent) {
5266 if (!callerWillRestart) {
5267 addAppLocked(app.info);
5268 } else {
5269 needRestart = true;
5270 }
5271 }
5272 } else {
5273 mRemovedProcesses.add(app);
5274 }
5275
5276 return needRestart;
5277 }
5278
5279 private final void processStartTimedOutLocked(ProcessRecord app) {
5280 final int pid = app.pid;
5281 boolean gone = false;
5282 synchronized (mPidsSelfLocked) {
5283 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5284 if (knownApp != null && knownApp.thread == null) {
5285 mPidsSelfLocked.remove(pid);
5286 gone = true;
5287 }
5288 }
5289
5290 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005291 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005292 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005293 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005295 // Take care of any launching providers waiting for this process.
5296 checkAppInLaunchingProvidersLocked(app, true);
5297 // Take care of any services that are waiting for the process.
5298 for (int i=0; i<mPendingServices.size(); i++) {
5299 ServiceRecord sr = mPendingServices.get(i);
5300 if (app.info.uid == sr.appInfo.uid
5301 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005302 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005303 mPendingServices.remove(i);
5304 i--;
5305 bringDownServiceLocked(sr, true);
5306 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005308 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005309 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005310 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005311 try {
5312 IBackupManager bm = IBackupManager.Stub.asInterface(
5313 ServiceManager.getService(Context.BACKUP_SERVICE));
5314 bm.agentDisconnected(app.info.packageName);
5315 } catch (RemoteException e) {
5316 // Can't happen; the backup manager is local
5317 }
5318 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005319 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005320 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005321 mPendingBroadcast = null;
5322 scheduleBroadcastsLocked();
5323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005325 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 }
5327 }
5328
5329 private final boolean attachApplicationLocked(IApplicationThread thread,
5330 int pid) {
5331
5332 // Find the application record that is being attached... either via
5333 // the pid if we are running in multiple processes, or just pull the
5334 // next app record if we are emulating process with anonymous threads.
5335 ProcessRecord app;
5336 if (pid != MY_PID && pid >= 0) {
5337 synchronized (mPidsSelfLocked) {
5338 app = mPidsSelfLocked.get(pid);
5339 }
5340 } else if (mStartingProcesses.size() > 0) {
5341 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005342 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 } else {
5344 app = null;
5345 }
5346
5347 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005348 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005350 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005351 if (pid > 0 && pid != MY_PID) {
5352 Process.killProcess(pid);
5353 } else {
5354 try {
5355 thread.scheduleExit();
5356 } catch (Exception e) {
5357 // Ignore exceptions.
5358 }
5359 }
5360 return false;
5361 }
5362
5363 // If this application record is still attached to a previous
5364 // process, clean it up now.
5365 if (app.thread != null) {
5366 handleAppDiedLocked(app, true);
5367 }
5368
5369 // Tell the process all about itself.
5370
Joe Onorato8a9b2202010-02-26 18:56:32 -08005371 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005372 TAG, "Binding process pid " + pid + " to record " + app);
5373
5374 String processName = app.processName;
5375 try {
5376 thread.asBinder().linkToDeath(new AppDeathRecipient(
5377 app, pid, thread), 0);
5378 } catch (RemoteException e) {
5379 app.resetPackageList();
5380 startProcessLocked(app, "link fail", processName);
5381 return false;
5382 }
5383
Doug Zongker2bec3d42009-12-04 12:52:44 -08005384 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385
5386 app.thread = thread;
5387 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005388 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5389 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 app.forcingToForeground = null;
5391 app.foregroundServices = false;
5392 app.debugging = false;
5393
5394 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5395
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005396 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5397 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005398
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005399 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005400 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005401 }
5402
Joe Onorato8a9b2202010-02-26 18:56:32 -08005403 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 TAG, "New app record " + app
5405 + " thread=" + thread.asBinder() + " pid=" + pid);
5406 try {
5407 int testMode = IApplicationThread.DEBUG_OFF;
5408 if (mDebugApp != null && mDebugApp.equals(processName)) {
5409 testMode = mWaitForDebugger
5410 ? IApplicationThread.DEBUG_WAIT
5411 : IApplicationThread.DEBUG_ON;
5412 app.debugging = true;
5413 if (mDebugTransient) {
5414 mDebugApp = mOrigDebugApp;
5415 mWaitForDebugger = mOrigWaitForDebugger;
5416 }
5417 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005418
Christopher Tate181fafa2009-05-14 11:12:14 -07005419 // If the app is being launched for restore or full backup, set it up specially
5420 boolean isRestrictedBackupMode = false;
5421 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5422 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5423 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5424 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005425
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005426 ensurePackageDexOpt(app.instrumentationInfo != null
5427 ? app.instrumentationInfo.packageName
5428 : app.info.packageName);
5429 if (app.instrumentationClass != null) {
5430 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005431 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005432 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005433 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005434 thread.bindApplication(processName, app.instrumentationInfo != null
5435 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 app.instrumentationClass, app.instrumentationProfileFile,
5437 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005438 isRestrictedBackupMode || !normalMode,
5439 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005440 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005441 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442 } catch (Exception e) {
5443 // todo: Yikes! What should we do? For now we will try to
5444 // start another process, but that could easily get us in
5445 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005446 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005447
5448 app.resetPackageList();
5449 startProcessLocked(app, "bind fail", processName);
5450 return false;
5451 }
5452
5453 // Remove this record from the list of starting applications.
5454 mPersistentStartingProcesses.remove(app);
5455 mProcessesOnHold.remove(app);
5456
5457 boolean badApp = false;
5458 boolean didSomething = false;
5459
5460 // See if the top visible activity is waiting to run in this process...
5461 HistoryRecord hr = topRunningActivityLocked(null);
5462 if (hr != null) {
5463 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5464 && processName.equals(hr.processName)) {
5465 try {
5466 if (realStartActivityLocked(hr, app, true, true)) {
5467 didSomething = true;
5468 }
5469 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005470 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005471 + hr.intent.getComponent().flattenToShortString(), e);
5472 badApp = true;
5473 }
5474 } else {
5475 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5476 }
5477 }
5478
5479 // Find any services that should be running in this process...
5480 if (!badApp && mPendingServices.size() > 0) {
5481 ServiceRecord sr = null;
5482 try {
5483 for (int i=0; i<mPendingServices.size(); i++) {
5484 sr = mPendingServices.get(i);
5485 if (app.info.uid != sr.appInfo.uid
5486 || !processName.equals(sr.processName)) {
5487 continue;
5488 }
5489
5490 mPendingServices.remove(i);
5491 i--;
5492 realStartServiceLocked(sr, app);
5493 didSomething = true;
5494 }
5495 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005496 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005497 + sr.shortName, e);
5498 badApp = true;
5499 }
5500 }
5501
5502 // Check if the next broadcast receiver is in this process...
5503 BroadcastRecord br = mPendingBroadcast;
5504 if (!badApp && br != null && br.curApp == app) {
5505 try {
5506 mPendingBroadcast = null;
5507 processCurBroadcastLocked(br, app);
5508 didSomething = true;
5509 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005510 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 + br.curComponent.flattenToShortString(), e);
5512 badApp = true;
5513 logBroadcastReceiverDiscard(br);
5514 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5515 br.resultExtras, br.resultAbort, true);
5516 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005517 // We need to reset the state if we fails to start the receiver.
5518 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 }
5520 }
5521
Christopher Tate181fafa2009-05-14 11:12:14 -07005522 // Check whether the next backup agent is in this process...
5523 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005524 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005525 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005526 try {
5527 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5528 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005529 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005530 e.printStackTrace();
5531 }
5532 }
5533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 if (badApp) {
5535 // todo: Also need to kill application to deal with all
5536 // kinds of exceptions.
5537 handleAppDiedLocked(app, false);
5538 return false;
5539 }
5540
5541 if (!didSomething) {
5542 updateOomAdjLocked();
5543 }
5544
5545 return true;
5546 }
5547
5548 public final void attachApplication(IApplicationThread thread) {
5549 synchronized (this) {
5550 int callingPid = Binder.getCallingPid();
5551 final long origId = Binder.clearCallingIdentity();
5552 attachApplicationLocked(thread, callingPid);
5553 Binder.restoreCallingIdentity(origId);
5554 }
5555 }
5556
Dianne Hackborne88846e2009-09-30 21:34:25 -07005557 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005559 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005560 Binder.restoreCallingIdentity(origId);
5561 }
5562
5563 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5564 boolean remove) {
5565 int N = mStoppingActivities.size();
5566 if (N <= 0) return null;
5567
5568 ArrayList<HistoryRecord> stops = null;
5569
5570 final boolean nowVisible = mResumedActivity != null
5571 && mResumedActivity.nowVisible
5572 && !mResumedActivity.waitingVisible;
5573 for (int i=0; i<N; i++) {
5574 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005575 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 + nowVisible + " waitingVisible=" + s.waitingVisible
5577 + " finishing=" + s.finishing);
5578 if (s.waitingVisible && nowVisible) {
5579 mWaitingVisibleActivities.remove(s);
5580 s.waitingVisible = false;
5581 if (s.finishing) {
5582 // If this activity is finishing, it is sitting on top of
5583 // everyone else but we now know it is no longer needed...
5584 // so get rid of it. Otherwise, we need to go through the
5585 // normal flow and hide it once we determine that it is
5586 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005587 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005588 mWindowManager.setAppVisibility(s, false);
5589 }
5590 }
5591 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005592 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005593 if (stops == null) {
5594 stops = new ArrayList<HistoryRecord>();
5595 }
5596 stops.add(s);
5597 mStoppingActivities.remove(i);
5598 N--;
5599 i--;
5600 }
5601 }
5602
5603 return stops;
5604 }
5605
5606 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005607 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005608 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005609 mWindowManager.enableScreenAfterBoot();
5610 }
5611
Dianne Hackborne88846e2009-09-30 21:34:25 -07005612 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5613 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005614 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615
5616 ArrayList<HistoryRecord> stops = null;
5617 ArrayList<HistoryRecord> finishes = null;
5618 ArrayList<HistoryRecord> thumbnails = null;
5619 int NS = 0;
5620 int NF = 0;
5621 int NT = 0;
5622 IApplicationThread sendThumbnail = null;
5623 boolean booting = false;
5624 boolean enableScreen = false;
5625
5626 synchronized (this) {
5627 if (token != null) {
5628 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5629 }
5630
5631 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005632 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005633 if (index >= 0) {
5634 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5635
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005636 if (fromTimeout) {
5637 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5638 }
5639
Dianne Hackborne88846e2009-09-30 21:34:25 -07005640 // This is a hack to semi-deal with a race condition
5641 // in the client where it can be constructed with a
5642 // newer configuration from when we asked it to launch.
5643 // We'll update with whatever configuration it now says
5644 // it used to launch.
5645 if (config != null) {
5646 r.configuration = config;
5647 }
5648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 // No longer need to keep the device awake.
5650 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5651 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5652 mLaunchingActivity.release();
5653 }
5654
5655 // We are now idle. If someone is waiting for a thumbnail from
5656 // us, we can now deliver.
5657 r.idle = true;
5658 scheduleAppGcsLocked();
5659 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5660 sendThumbnail = r.app.thread;
5661 r.thumbnailNeeded = false;
5662 }
5663
5664 // If this activity is fullscreen, set up to hide those under it.
5665
Joe Onorato8a9b2202010-02-26 18:56:32 -08005666 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667 ensureActivitiesVisibleLocked(null, 0);
5668
Joe Onorato8a9b2202010-02-26 18:56:32 -08005669 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005670 if (!mBooted && !fromTimeout) {
5671 mBooted = true;
5672 enableScreen = true;
5673 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005674
5675 } else if (fromTimeout) {
5676 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005677 }
5678
5679 // Atomically retrieve all of the other things to do.
5680 stops = processStoppingActivitiesLocked(true);
5681 NS = stops != null ? stops.size() : 0;
5682 if ((NF=mFinishingActivities.size()) > 0) {
5683 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5684 mFinishingActivities.clear();
5685 }
5686 if ((NT=mCancelledThumbnails.size()) > 0) {
5687 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5688 mCancelledThumbnails.clear();
5689 }
5690
5691 booting = mBooting;
5692 mBooting = false;
5693 }
5694
5695 int i;
5696
5697 // Send thumbnail if requested.
5698 if (sendThumbnail != null) {
5699 try {
5700 sendThumbnail.requestThumbnail(token);
5701 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005702 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005703 sendPendingThumbnail(null, token, null, null, true);
5704 }
5705 }
5706
5707 // Stop any activities that are scheduled to do so but have been
5708 // waiting for the next one to start.
5709 for (i=0; i<NS; i++) {
5710 HistoryRecord r = (HistoryRecord)stops.get(i);
5711 synchronized (this) {
5712 if (r.finishing) {
5713 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5714 } else {
5715 stopActivityLocked(r);
5716 }
5717 }
5718 }
5719
5720 // Finish any activities that are scheduled to do so but have been
5721 // waiting for the next one to start.
5722 for (i=0; i<NF; i++) {
5723 HistoryRecord r = (HistoryRecord)finishes.get(i);
5724 synchronized (this) {
5725 destroyActivityLocked(r, true);
5726 }
5727 }
5728
5729 // Report back to any thumbnail receivers.
5730 for (i=0; i<NT; i++) {
5731 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5732 sendPendingThumbnail(r, null, null, null, true);
5733 }
5734
5735 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005736 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005737 }
5738
5739 trimApplications();
5740 //dump();
5741 //mWindowManager.dump();
5742
5743 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005744 enableScreenAfterBoot();
5745 }
5746 }
5747
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005748 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005749 IntentFilter pkgFilter = new IntentFilter();
5750 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5751 pkgFilter.addDataScheme("package");
5752 mContext.registerReceiver(new BroadcastReceiver() {
5753 @Override
5754 public void onReceive(Context context, Intent intent) {
5755 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5756 if (pkgs != null) {
5757 for (String pkg : pkgs) {
5758 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5759 setResultCode(Activity.RESULT_OK);
5760 return;
5761 }
5762 }
5763 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005764 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005765 }, pkgFilter);
5766
5767 synchronized (this) {
5768 // Ensure that any processes we had put on hold are now started
5769 // up.
5770 final int NP = mProcessesOnHold.size();
5771 if (NP > 0) {
5772 ArrayList<ProcessRecord> procs =
5773 new ArrayList<ProcessRecord>(mProcessesOnHold);
5774 for (int ip=0; ip<NP; ip++) {
5775 this.startProcessLocked(procs.get(ip), "on-hold", null);
5776 }
5777 }
5778
5779 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5780 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005781 broadcastIntentLocked(null, null,
5782 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5783 null, null, 0, null, null,
5784 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5785 false, false, MY_PID, Process.SYSTEM_UID);
5786 }
5787 }
5788 }
5789
5790 final void ensureBootCompleted() {
5791 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005792 boolean enableScreen;
5793 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005794 booting = mBooting;
5795 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005796 enableScreen = !mBooted;
5797 mBooted = true;
5798 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005799
5800 if (booting) {
5801 finishBooting();
5802 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005803
5804 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005805 enableScreenAfterBoot();
5806 }
5807 }
5808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005809 public final void activityPaused(IBinder token, Bundle icicle) {
5810 // Refuse possible leaked file descriptors
5811 if (icicle != null && icicle.hasFileDescriptors()) {
5812 throw new IllegalArgumentException("File descriptors passed in Bundle");
5813 }
5814
5815 final long origId = Binder.clearCallingIdentity();
5816 activityPaused(token, icicle, false);
5817 Binder.restoreCallingIdentity(origId);
5818 }
5819
5820 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005821 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5823 + ", timeout=" + timeout);
5824
5825 HistoryRecord r = null;
5826
5827 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005828 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005829 if (index >= 0) {
5830 r = (HistoryRecord)mHistory.get(index);
5831 if (!timeout) {
5832 r.icicle = icicle;
5833 r.haveState = true;
5834 }
5835 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5836 if (mPausingActivity == r) {
5837 r.state = ActivityState.PAUSED;
5838 completePauseLocked();
5839 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005840 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005841 System.identityHashCode(r), r.shortComponentName,
5842 mPausingActivity != null
5843 ? mPausingActivity.shortComponentName : "(none)");
5844 }
5845 }
5846 }
5847 }
5848
5849 public final void activityStopped(IBinder token, Bitmap thumbnail,
5850 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005851 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005852 TAG, "Activity stopped: token=" + token);
5853
5854 HistoryRecord r = null;
5855
5856 final long origId = Binder.clearCallingIdentity();
5857
5858 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005859 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 if (index >= 0) {
5861 r = (HistoryRecord)mHistory.get(index);
5862 r.thumbnail = thumbnail;
5863 r.description = description;
5864 r.stopped = true;
5865 r.state = ActivityState.STOPPED;
5866 if (!r.finishing) {
5867 if (r.configDestroy) {
5868 destroyActivityLocked(r, true);
5869 resumeTopActivityLocked(null);
5870 }
5871 }
5872 }
5873 }
5874
5875 if (r != null) {
5876 sendPendingThumbnail(r, null, null, null, false);
5877 }
5878
5879 trimApplications();
5880
5881 Binder.restoreCallingIdentity(origId);
5882 }
5883
5884 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005885 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005886 synchronized (this) {
5887 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5888
Dianne Hackborn75b03852009-06-12 15:43:26 -07005889 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005890 if (index >= 0) {
5891 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5892 if (r.state == ActivityState.DESTROYING) {
5893 final long origId = Binder.clearCallingIdentity();
5894 removeActivityFromHistoryLocked(r);
5895 Binder.restoreCallingIdentity(origId);
5896 }
5897 }
5898 }
5899 }
5900
5901 public String getCallingPackage(IBinder token) {
5902 synchronized (this) {
5903 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005904 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005905 }
5906 }
5907
5908 public ComponentName getCallingActivity(IBinder token) {
5909 synchronized (this) {
5910 HistoryRecord r = getCallingRecordLocked(token);
5911 return r != null ? r.intent.getComponent() : null;
5912 }
5913 }
5914
5915 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005916 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005917 if (index >= 0) {
5918 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5919 if (r != null) {
5920 return r.resultTo;
5921 }
5922 }
5923 return null;
5924 }
5925
5926 public ComponentName getActivityClassForToken(IBinder token) {
5927 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005928 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005929 if (index >= 0) {
5930 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5931 return r.intent.getComponent();
5932 }
5933 return null;
5934 }
5935 }
5936
5937 public String getPackageForToken(IBinder token) {
5938 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005939 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005940 if (index >= 0) {
5941 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5942 return r.packageName;
5943 }
5944 return null;
5945 }
5946 }
5947
5948 public IIntentSender getIntentSender(int type,
5949 String packageName, IBinder token, String resultWho,
5950 int requestCode, Intent intent, String resolvedType, int flags) {
5951 // Refuse possible leaked file descriptors
5952 if (intent != null && intent.hasFileDescriptors() == true) {
5953 throw new IllegalArgumentException("File descriptors passed in Intent");
5954 }
5955
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005956 if (type == INTENT_SENDER_BROADCAST) {
5957 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5958 throw new IllegalArgumentException(
5959 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5960 }
5961 }
5962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005963 synchronized(this) {
5964 int callingUid = Binder.getCallingUid();
5965 try {
5966 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5967 Process.supportsProcesses()) {
5968 int uid = ActivityThread.getPackageManager()
5969 .getPackageUid(packageName);
5970 if (uid != Binder.getCallingUid()) {
5971 String msg = "Permission Denial: getIntentSender() from pid="
5972 + Binder.getCallingPid()
5973 + ", uid=" + Binder.getCallingUid()
5974 + ", (need uid=" + uid + ")"
5975 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005976 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005977 throw new SecurityException(msg);
5978 }
5979 }
5980 } catch (RemoteException e) {
5981 throw new SecurityException(e);
5982 }
5983 HistoryRecord activity = null;
5984 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005985 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005986 if (index < 0) {
5987 return null;
5988 }
5989 activity = (HistoryRecord)mHistory.get(index);
5990 if (activity.finishing) {
5991 return null;
5992 }
5993 }
5994
5995 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5996 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5997 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5998 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5999 |PendingIntent.FLAG_UPDATE_CURRENT);
6000
6001 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6002 type, packageName, activity, resultWho,
6003 requestCode, intent, resolvedType, flags);
6004 WeakReference<PendingIntentRecord> ref;
6005 ref = mIntentSenderRecords.get(key);
6006 PendingIntentRecord rec = ref != null ? ref.get() : null;
6007 if (rec != null) {
6008 if (!cancelCurrent) {
6009 if (updateCurrent) {
6010 rec.key.requestIntent.replaceExtras(intent);
6011 }
6012 return rec;
6013 }
6014 rec.canceled = true;
6015 mIntentSenderRecords.remove(key);
6016 }
6017 if (noCreate) {
6018 return rec;
6019 }
6020 rec = new PendingIntentRecord(this, key, callingUid);
6021 mIntentSenderRecords.put(key, rec.ref);
6022 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6023 if (activity.pendingResults == null) {
6024 activity.pendingResults
6025 = new HashSet<WeakReference<PendingIntentRecord>>();
6026 }
6027 activity.pendingResults.add(rec.ref);
6028 }
6029 return rec;
6030 }
6031 }
6032
6033 public void cancelIntentSender(IIntentSender sender) {
6034 if (!(sender instanceof PendingIntentRecord)) {
6035 return;
6036 }
6037 synchronized(this) {
6038 PendingIntentRecord rec = (PendingIntentRecord)sender;
6039 try {
6040 int uid = ActivityThread.getPackageManager()
6041 .getPackageUid(rec.key.packageName);
6042 if (uid != Binder.getCallingUid()) {
6043 String msg = "Permission Denial: cancelIntentSender() from pid="
6044 + Binder.getCallingPid()
6045 + ", uid=" + Binder.getCallingUid()
6046 + " is not allowed to cancel packges "
6047 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006048 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006049 throw new SecurityException(msg);
6050 }
6051 } catch (RemoteException e) {
6052 throw new SecurityException(e);
6053 }
6054 cancelIntentSenderLocked(rec, true);
6055 }
6056 }
6057
6058 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6059 rec.canceled = true;
6060 mIntentSenderRecords.remove(rec.key);
6061 if (cleanActivity && rec.key.activity != null) {
6062 rec.key.activity.pendingResults.remove(rec.ref);
6063 }
6064 }
6065
6066 public String getPackageForIntentSender(IIntentSender pendingResult) {
6067 if (!(pendingResult instanceof PendingIntentRecord)) {
6068 return null;
6069 }
6070 synchronized(this) {
6071 try {
6072 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6073 return res.key.packageName;
6074 } catch (ClassCastException e) {
6075 }
6076 }
6077 return null;
6078 }
6079
6080 public void setProcessLimit(int max) {
6081 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6082 "setProcessLimit()");
6083 mProcessLimit = max;
6084 }
6085
6086 public int getProcessLimit() {
6087 return mProcessLimit;
6088 }
6089
6090 void foregroundTokenDied(ForegroundToken token) {
6091 synchronized (ActivityManagerService.this) {
6092 synchronized (mPidsSelfLocked) {
6093 ForegroundToken cur
6094 = mForegroundProcesses.get(token.pid);
6095 if (cur != token) {
6096 return;
6097 }
6098 mForegroundProcesses.remove(token.pid);
6099 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6100 if (pr == null) {
6101 return;
6102 }
6103 pr.forcingToForeground = null;
6104 pr.foregroundServices = false;
6105 }
6106 updateOomAdjLocked();
6107 }
6108 }
6109
6110 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6111 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6112 "setProcessForeground()");
6113 synchronized(this) {
6114 boolean changed = false;
6115
6116 synchronized (mPidsSelfLocked) {
6117 ProcessRecord pr = mPidsSelfLocked.get(pid);
6118 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006119 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006120 return;
6121 }
6122 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6123 if (oldToken != null) {
6124 oldToken.token.unlinkToDeath(oldToken, 0);
6125 mForegroundProcesses.remove(pid);
6126 pr.forcingToForeground = null;
6127 changed = true;
6128 }
6129 if (isForeground && token != null) {
6130 ForegroundToken newToken = new ForegroundToken() {
6131 public void binderDied() {
6132 foregroundTokenDied(this);
6133 }
6134 };
6135 newToken.pid = pid;
6136 newToken.token = token;
6137 try {
6138 token.linkToDeath(newToken, 0);
6139 mForegroundProcesses.put(pid, newToken);
6140 pr.forcingToForeground = token;
6141 changed = true;
6142 } catch (RemoteException e) {
6143 // If the process died while doing this, we will later
6144 // do the cleanup with the process death link.
6145 }
6146 }
6147 }
6148
6149 if (changed) {
6150 updateOomAdjLocked();
6151 }
6152 }
6153 }
6154
6155 // =========================================================
6156 // PERMISSIONS
6157 // =========================================================
6158
6159 static class PermissionController extends IPermissionController.Stub {
6160 ActivityManagerService mActivityManagerService;
6161 PermissionController(ActivityManagerService activityManagerService) {
6162 mActivityManagerService = activityManagerService;
6163 }
6164
6165 public boolean checkPermission(String permission, int pid, int uid) {
6166 return mActivityManagerService.checkPermission(permission, pid,
6167 uid) == PackageManager.PERMISSION_GRANTED;
6168 }
6169 }
6170
6171 /**
6172 * This can be called with or without the global lock held.
6173 */
6174 int checkComponentPermission(String permission, int pid, int uid,
6175 int reqUid) {
6176 // We might be performing an operation on behalf of an indirect binder
6177 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6178 // client identity accordingly before proceeding.
6179 Identity tlsIdentity = sCallerIdentity.get();
6180 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006181 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006182 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6183 uid = tlsIdentity.uid;
6184 pid = tlsIdentity.pid;
6185 }
6186
6187 // Root, system server and our own process get to do everything.
6188 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6189 !Process.supportsProcesses()) {
6190 return PackageManager.PERMISSION_GRANTED;
6191 }
6192 // If the target requires a specific UID, always fail for others.
6193 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006194 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006195 return PackageManager.PERMISSION_DENIED;
6196 }
6197 if (permission == null) {
6198 return PackageManager.PERMISSION_GRANTED;
6199 }
6200 try {
6201 return ActivityThread.getPackageManager()
6202 .checkUidPermission(permission, uid);
6203 } catch (RemoteException e) {
6204 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006205 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006206 }
6207 return PackageManager.PERMISSION_DENIED;
6208 }
6209
6210 /**
6211 * As the only public entry point for permissions checking, this method
6212 * can enforce the semantic that requesting a check on a null global
6213 * permission is automatically denied. (Internally a null permission
6214 * string is used when calling {@link #checkComponentPermission} in cases
6215 * when only uid-based security is needed.)
6216 *
6217 * This can be called with or without the global lock held.
6218 */
6219 public int checkPermission(String permission, int pid, int uid) {
6220 if (permission == null) {
6221 return PackageManager.PERMISSION_DENIED;
6222 }
6223 return checkComponentPermission(permission, pid, uid, -1);
6224 }
6225
6226 /**
6227 * Binder IPC calls go through the public entry point.
6228 * This can be called with or without the global lock held.
6229 */
6230 int checkCallingPermission(String permission) {
6231 return checkPermission(permission,
6232 Binder.getCallingPid(),
6233 Binder.getCallingUid());
6234 }
6235
6236 /**
6237 * This can be called with or without the global lock held.
6238 */
6239 void enforceCallingPermission(String permission, String func) {
6240 if (checkCallingPermission(permission)
6241 == PackageManager.PERMISSION_GRANTED) {
6242 return;
6243 }
6244
6245 String msg = "Permission Denial: " + func + " from pid="
6246 + Binder.getCallingPid()
6247 + ", uid=" + Binder.getCallingUid()
6248 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006249 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006250 throw new SecurityException(msg);
6251 }
6252
6253 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6254 ProviderInfo pi, int uid, int modeFlags) {
6255 try {
6256 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6257 if ((pi.readPermission != null) &&
6258 (pm.checkUidPermission(pi.readPermission, uid)
6259 != PackageManager.PERMISSION_GRANTED)) {
6260 return false;
6261 }
6262 }
6263 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6264 if ((pi.writePermission != null) &&
6265 (pm.checkUidPermission(pi.writePermission, uid)
6266 != PackageManager.PERMISSION_GRANTED)) {
6267 return false;
6268 }
6269 }
6270 return true;
6271 } catch (RemoteException e) {
6272 return false;
6273 }
6274 }
6275
6276 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6277 int modeFlags) {
6278 // Root gets to do everything.
6279 if (uid == 0 || !Process.supportsProcesses()) {
6280 return true;
6281 }
6282 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6283 if (perms == null) return false;
6284 UriPermission perm = perms.get(uri);
6285 if (perm == null) return false;
6286 return (modeFlags&perm.modeFlags) == modeFlags;
6287 }
6288
6289 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6290 // Another redirected-binder-call permissions check as in
6291 // {@link checkComponentPermission}.
6292 Identity tlsIdentity = sCallerIdentity.get();
6293 if (tlsIdentity != null) {
6294 uid = tlsIdentity.uid;
6295 pid = tlsIdentity.pid;
6296 }
6297
6298 // Our own process gets to do everything.
6299 if (pid == MY_PID) {
6300 return PackageManager.PERMISSION_GRANTED;
6301 }
6302 synchronized(this) {
6303 return checkUriPermissionLocked(uri, uid, modeFlags)
6304 ? PackageManager.PERMISSION_GRANTED
6305 : PackageManager.PERMISSION_DENIED;
6306 }
6307 }
6308
6309 private void grantUriPermissionLocked(int callingUid,
6310 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6311 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6312 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6313 if (modeFlags == 0) {
6314 return;
6315 }
6316
Joe Onorato8a9b2202010-02-26 18:56:32 -08006317 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006318 "Requested grant " + targetPkg + " permission to " + uri);
6319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006320 final IPackageManager pm = ActivityThread.getPackageManager();
6321
6322 // If this is not a content: uri, we can't do anything with it.
6323 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006324 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006325 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006326 return;
6327 }
6328
6329 String name = uri.getAuthority();
6330 ProviderInfo pi = null;
6331 ContentProviderRecord cpr
6332 = (ContentProviderRecord)mProvidersByName.get(name);
6333 if (cpr != null) {
6334 pi = cpr.info;
6335 } else {
6336 try {
6337 pi = pm.resolveContentProvider(name,
6338 PackageManager.GET_URI_PERMISSION_PATTERNS);
6339 } catch (RemoteException ex) {
6340 }
6341 }
6342 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006343 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006344 return;
6345 }
6346
6347 int targetUid;
6348 try {
6349 targetUid = pm.getPackageUid(targetPkg);
6350 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006351 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006352 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006353 return;
6354 }
6355 } catch (RemoteException ex) {
6356 return;
6357 }
6358
6359 // First... does the target actually need this permission?
6360 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6361 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006362 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006363 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006364 return;
6365 }
6366
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006367 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006368 if (!pi.grantUriPermissions) {
6369 throw new SecurityException("Provider " + pi.packageName
6370 + "/" + pi.name
6371 + " does not allow granting of Uri permissions (uri "
6372 + uri + ")");
6373 }
6374 if (pi.uriPermissionPatterns != null) {
6375 final int N = pi.uriPermissionPatterns.length;
6376 boolean allowed = false;
6377 for (int i=0; i<N; i++) {
6378 if (pi.uriPermissionPatterns[i] != null
6379 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6380 allowed = true;
6381 break;
6382 }
6383 }
6384 if (!allowed) {
6385 throw new SecurityException("Provider " + pi.packageName
6386 + "/" + pi.name
6387 + " does not allow granting of permission to path of Uri "
6388 + uri);
6389 }
6390 }
6391
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006392 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006393 // this uri?
6394 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6395 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6396 throw new SecurityException("Uid " + callingUid
6397 + " does not have permission to uri " + uri);
6398 }
6399 }
6400
6401 // Okay! So here we are: the caller has the assumed permission
6402 // to the uri, and the target doesn't. Let's now give this to
6403 // the target.
6404
Joe Onorato8a9b2202010-02-26 18:56:32 -08006405 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006406 "Granting " + targetPkg + " permission to " + uri);
6407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006408 HashMap<Uri, UriPermission> targetUris
6409 = mGrantedUriPermissions.get(targetUid);
6410 if (targetUris == null) {
6411 targetUris = new HashMap<Uri, UriPermission>();
6412 mGrantedUriPermissions.put(targetUid, targetUris);
6413 }
6414
6415 UriPermission perm = targetUris.get(uri);
6416 if (perm == null) {
6417 perm = new UriPermission(targetUid, uri);
6418 targetUris.put(uri, perm);
6419
6420 }
6421 perm.modeFlags |= modeFlags;
6422 if (activity == null) {
6423 perm.globalModeFlags |= modeFlags;
6424 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6425 perm.readActivities.add(activity);
6426 if (activity.readUriPermissions == null) {
6427 activity.readUriPermissions = new HashSet<UriPermission>();
6428 }
6429 activity.readUriPermissions.add(perm);
6430 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6431 perm.writeActivities.add(activity);
6432 if (activity.writeUriPermissions == null) {
6433 activity.writeUriPermissions = new HashSet<UriPermission>();
6434 }
6435 activity.writeUriPermissions.add(perm);
6436 }
6437 }
6438
6439 private void grantUriPermissionFromIntentLocked(int callingUid,
6440 String targetPkg, Intent intent, HistoryRecord activity) {
6441 if (intent == null) {
6442 return;
6443 }
6444 Uri data = intent.getData();
6445 if (data == null) {
6446 return;
6447 }
6448 grantUriPermissionLocked(callingUid, targetPkg, data,
6449 intent.getFlags(), activity);
6450 }
6451
6452 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6453 Uri uri, int modeFlags) {
6454 synchronized(this) {
6455 final ProcessRecord r = getRecordForAppLocked(caller);
6456 if (r == null) {
6457 throw new SecurityException("Unable to find app for caller "
6458 + caller
6459 + " when granting permission to uri " + uri);
6460 }
6461 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006462 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006463 return;
6464 }
6465 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006466 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 return;
6468 }
6469
6470 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6471 null);
6472 }
6473 }
6474
6475 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6476 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6477 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6478 HashMap<Uri, UriPermission> perms
6479 = mGrantedUriPermissions.get(perm.uid);
6480 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006481 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006482 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006483 perms.remove(perm.uri);
6484 if (perms.size() == 0) {
6485 mGrantedUriPermissions.remove(perm.uid);
6486 }
6487 }
6488 }
6489 }
6490
6491 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6492 if (activity.readUriPermissions != null) {
6493 for (UriPermission perm : activity.readUriPermissions) {
6494 perm.readActivities.remove(activity);
6495 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6496 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6497 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6498 removeUriPermissionIfNeededLocked(perm);
6499 }
6500 }
6501 }
6502 if (activity.writeUriPermissions != null) {
6503 for (UriPermission perm : activity.writeUriPermissions) {
6504 perm.writeActivities.remove(activity);
6505 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6506 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6507 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6508 removeUriPermissionIfNeededLocked(perm);
6509 }
6510 }
6511 }
6512 }
6513
6514 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6515 int modeFlags) {
6516 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6517 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6518 if (modeFlags == 0) {
6519 return;
6520 }
6521
Joe Onorato8a9b2202010-02-26 18:56:32 -08006522 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006523 "Revoking all granted permissions to " + uri);
6524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006525 final IPackageManager pm = ActivityThread.getPackageManager();
6526
6527 final String authority = uri.getAuthority();
6528 ProviderInfo pi = null;
6529 ContentProviderRecord cpr
6530 = (ContentProviderRecord)mProvidersByName.get(authority);
6531 if (cpr != null) {
6532 pi = cpr.info;
6533 } else {
6534 try {
6535 pi = pm.resolveContentProvider(authority,
6536 PackageManager.GET_URI_PERMISSION_PATTERNS);
6537 } catch (RemoteException ex) {
6538 }
6539 }
6540 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006541 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006542 return;
6543 }
6544
6545 // Does the caller have this permission on the URI?
6546 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6547 // Right now, if you are not the original owner of the permission,
6548 // you are not allowed to revoke it.
6549 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6550 throw new SecurityException("Uid " + callingUid
6551 + " does not have permission to uri " + uri);
6552 //}
6553 }
6554
6555 // Go through all of the permissions and remove any that match.
6556 final List<String> SEGMENTS = uri.getPathSegments();
6557 if (SEGMENTS != null) {
6558 final int NS = SEGMENTS.size();
6559 int N = mGrantedUriPermissions.size();
6560 for (int i=0; i<N; i++) {
6561 HashMap<Uri, UriPermission> perms
6562 = mGrantedUriPermissions.valueAt(i);
6563 Iterator<UriPermission> it = perms.values().iterator();
6564 toploop:
6565 while (it.hasNext()) {
6566 UriPermission perm = it.next();
6567 Uri targetUri = perm.uri;
6568 if (!authority.equals(targetUri.getAuthority())) {
6569 continue;
6570 }
6571 List<String> targetSegments = targetUri.getPathSegments();
6572 if (targetSegments == null) {
6573 continue;
6574 }
6575 if (targetSegments.size() < NS) {
6576 continue;
6577 }
6578 for (int j=0; j<NS; j++) {
6579 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6580 continue toploop;
6581 }
6582 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006583 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006584 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006585 perm.clearModes(modeFlags);
6586 if (perm.modeFlags == 0) {
6587 it.remove();
6588 }
6589 }
6590 if (perms.size() == 0) {
6591 mGrantedUriPermissions.remove(
6592 mGrantedUriPermissions.keyAt(i));
6593 N--;
6594 i--;
6595 }
6596 }
6597 }
6598 }
6599
6600 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6601 int modeFlags) {
6602 synchronized(this) {
6603 final ProcessRecord r = getRecordForAppLocked(caller);
6604 if (r == null) {
6605 throw new SecurityException("Unable to find app for caller "
6606 + caller
6607 + " when revoking permission to uri " + uri);
6608 }
6609 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006610 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006611 return;
6612 }
6613
6614 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6615 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6616 if (modeFlags == 0) {
6617 return;
6618 }
6619
6620 final IPackageManager pm = ActivityThread.getPackageManager();
6621
6622 final String authority = uri.getAuthority();
6623 ProviderInfo pi = null;
6624 ContentProviderRecord cpr
6625 = (ContentProviderRecord)mProvidersByName.get(authority);
6626 if (cpr != null) {
6627 pi = cpr.info;
6628 } else {
6629 try {
6630 pi = pm.resolveContentProvider(authority,
6631 PackageManager.GET_URI_PERMISSION_PATTERNS);
6632 } catch (RemoteException ex) {
6633 }
6634 }
6635 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006636 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006637 return;
6638 }
6639
6640 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6641 }
6642 }
6643
6644 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6645 synchronized (this) {
6646 ProcessRecord app =
6647 who != null ? getRecordForAppLocked(who) : null;
6648 if (app == null) return;
6649
6650 Message msg = Message.obtain();
6651 msg.what = WAIT_FOR_DEBUGGER_MSG;
6652 msg.obj = app;
6653 msg.arg1 = waiting ? 1 : 0;
6654 mHandler.sendMessage(msg);
6655 }
6656 }
6657
6658 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6659 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006660 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006661 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006662 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 }
6664
6665 // =========================================================
6666 // TASK MANAGEMENT
6667 // =========================================================
6668
6669 public List getTasks(int maxNum, int flags,
6670 IThumbnailReceiver receiver) {
6671 ArrayList list = new ArrayList();
6672
6673 PendingThumbnailsRecord pending = null;
6674 IApplicationThread topThumbnail = null;
6675 HistoryRecord topRecord = null;
6676
6677 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006678 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006679 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6680 + ", receiver=" + receiver);
6681
6682 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6683 != PackageManager.PERMISSION_GRANTED) {
6684 if (receiver != null) {
6685 // If the caller wants to wait for pending thumbnails,
6686 // it ain't gonna get them.
6687 try {
6688 receiver.finished();
6689 } catch (RemoteException ex) {
6690 }
6691 }
6692 String msg = "Permission Denial: getTasks() from pid="
6693 + Binder.getCallingPid()
6694 + ", uid=" + Binder.getCallingUid()
6695 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006696 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006697 throw new SecurityException(msg);
6698 }
6699
6700 int pos = mHistory.size()-1;
6701 HistoryRecord next =
6702 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6703 HistoryRecord top = null;
6704 CharSequence topDescription = null;
6705 TaskRecord curTask = null;
6706 int numActivities = 0;
6707 int numRunning = 0;
6708 while (pos >= 0 && maxNum > 0) {
6709 final HistoryRecord r = next;
6710 pos--;
6711 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6712
6713 // Initialize state for next task if needed.
6714 if (top == null ||
6715 (top.state == ActivityState.INITIALIZING
6716 && top.task == r.task)) {
6717 top = r;
6718 topDescription = r.description;
6719 curTask = r.task;
6720 numActivities = numRunning = 0;
6721 }
6722
6723 // Add 'r' into the current task.
6724 numActivities++;
6725 if (r.app != null && r.app.thread != null) {
6726 numRunning++;
6727 }
6728 if (topDescription == null) {
6729 topDescription = r.description;
6730 }
6731
Joe Onorato8a9b2202010-02-26 18:56:32 -08006732 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006733 TAG, r.intent.getComponent().flattenToShortString()
6734 + ": task=" + r.task);
6735
6736 // If the next one is a different task, generate a new
6737 // TaskInfo entry for what we have.
6738 if (next == null || next.task != curTask) {
6739 ActivityManager.RunningTaskInfo ci
6740 = new ActivityManager.RunningTaskInfo();
6741 ci.id = curTask.taskId;
6742 ci.baseActivity = r.intent.getComponent();
6743 ci.topActivity = top.intent.getComponent();
6744 ci.thumbnail = top.thumbnail;
6745 ci.description = topDescription;
6746 ci.numActivities = numActivities;
6747 ci.numRunning = numRunning;
6748 //System.out.println(
6749 // "#" + maxNum + ": " + " descr=" + ci.description);
6750 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006751 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006752 TAG, "State=" + top.state + "Idle=" + top.idle
6753 + " app=" + top.app
6754 + " thr=" + (top.app != null ? top.app.thread : null));
6755 if (top.state == ActivityState.RESUMED
6756 || top.state == ActivityState.PAUSING) {
6757 if (top.idle && top.app != null
6758 && top.app.thread != null) {
6759 topRecord = top;
6760 topThumbnail = top.app.thread;
6761 } else {
6762 top.thumbnailNeeded = true;
6763 }
6764 }
6765 if (pending == null) {
6766 pending = new PendingThumbnailsRecord(receiver);
6767 }
6768 pending.pendingRecords.add(top);
6769 }
6770 list.add(ci);
6771 maxNum--;
6772 top = null;
6773 }
6774 }
6775
6776 if (pending != null) {
6777 mPendingThumbnails.add(pending);
6778 }
6779 }
6780
Joe Onorato8a9b2202010-02-26 18:56:32 -08006781 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006782
6783 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006784 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006785 try {
6786 topThumbnail.requestThumbnail(topRecord);
6787 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006788 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006789 sendPendingThumbnail(null, topRecord, null, null, true);
6790 }
6791 }
6792
6793 if (pending == null && receiver != null) {
6794 // In this case all thumbnails were available and the client
6795 // is being asked to be told when the remaining ones come in...
6796 // which is unusually, since the top-most currently running
6797 // activity should never have a canned thumbnail! Oh well.
6798 try {
6799 receiver.finished();
6800 } catch (RemoteException ex) {
6801 }
6802 }
6803
6804 return list;
6805 }
6806
6807 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6808 int flags) {
6809 synchronized (this) {
6810 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6811 "getRecentTasks()");
6812
6813 final int N = mRecentTasks.size();
6814 ArrayList<ActivityManager.RecentTaskInfo> res
6815 = new ArrayList<ActivityManager.RecentTaskInfo>(
6816 maxNum < N ? maxNum : N);
6817 for (int i=0; i<N && maxNum > 0; i++) {
6818 TaskRecord tr = mRecentTasks.get(i);
6819 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6820 || (tr.intent == null)
6821 || ((tr.intent.getFlags()
6822 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6823 ActivityManager.RecentTaskInfo rti
6824 = new ActivityManager.RecentTaskInfo();
6825 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6826 rti.baseIntent = new Intent(
6827 tr.intent != null ? tr.intent : tr.affinityIntent);
6828 rti.origActivity = tr.origActivity;
6829 res.add(rti);
6830 maxNum--;
6831 }
6832 }
6833 return res;
6834 }
6835 }
6836
6837 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6838 int j;
6839 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6840 TaskRecord jt = startTask;
6841
6842 // First look backwards
6843 for (j=startIndex-1; j>=0; j--) {
6844 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6845 if (r.task != jt) {
6846 jt = r.task;
6847 if (affinity.equals(jt.affinity)) {
6848 return j;
6849 }
6850 }
6851 }
6852
6853 // Now look forwards
6854 final int N = mHistory.size();
6855 jt = startTask;
6856 for (j=startIndex+1; j<N; j++) {
6857 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6858 if (r.task != jt) {
6859 if (affinity.equals(jt.affinity)) {
6860 return j;
6861 }
6862 jt = r.task;
6863 }
6864 }
6865
6866 // Might it be at the top?
6867 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6868 return N-1;
6869 }
6870
6871 return -1;
6872 }
6873
6874 /**
6875 * Perform a reset of the given task, if needed as part of launching it.
6876 * Returns the new HistoryRecord at the top of the task.
6877 */
6878 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6879 HistoryRecord newActivity) {
6880 boolean forceReset = (newActivity.info.flags
6881 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6882 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6883 if ((newActivity.info.flags
6884 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6885 forceReset = true;
6886 }
6887 }
6888
6889 final TaskRecord task = taskTop.task;
6890
6891 // We are going to move through the history list so that we can look
6892 // at each activity 'target' with 'below' either the interesting
6893 // activity immediately below it in the stack or null.
6894 HistoryRecord target = null;
6895 int targetI = 0;
6896 int taskTopI = -1;
6897 int replyChainEnd = -1;
6898 int lastReparentPos = -1;
6899 for (int i=mHistory.size()-1; i>=-1; i--) {
6900 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6901
6902 if (below != null && below.finishing) {
6903 continue;
6904 }
6905 if (target == null) {
6906 target = below;
6907 targetI = i;
6908 // If we were in the middle of a reply chain before this
6909 // task, it doesn't appear like the root of the chain wants
6910 // anything interesting, so drop it.
6911 replyChainEnd = -1;
6912 continue;
6913 }
6914
6915 final int flags = target.info.flags;
6916
6917 final boolean finishOnTaskLaunch =
6918 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6919 final boolean allowTaskReparenting =
6920 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6921
6922 if (target.task == task) {
6923 // We are inside of the task being reset... we'll either
6924 // finish this activity, push it out for another task,
6925 // or leave it as-is. We only do this
6926 // for activities that are not the root of the task (since
6927 // if we finish the root, we may no longer have the task!).
6928 if (taskTopI < 0) {
6929 taskTopI = targetI;
6930 }
6931 if (below != null && below.task == task) {
6932 final boolean clearWhenTaskReset =
6933 (target.intent.getFlags()
6934 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006935 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006936 // If this activity is sending a reply to a previous
6937 // activity, we can't do anything with it now until
6938 // we reach the start of the reply chain.
6939 // XXX note that we are assuming the result is always
6940 // to the previous activity, which is almost always
6941 // the case but we really shouldn't count on.
6942 if (replyChainEnd < 0) {
6943 replyChainEnd = targetI;
6944 }
Ed Heyl73798232009-03-24 21:32:21 -07006945 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006946 && target.taskAffinity != null
6947 && !target.taskAffinity.equals(task.affinity)) {
6948 // If this activity has an affinity for another
6949 // task, then we need to move it out of here. We will
6950 // move it as far out of the way as possible, to the
6951 // bottom of the activity stack. This also keeps it
6952 // correctly ordered with any activities we previously
6953 // moved.
6954 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6955 if (target.taskAffinity != null
6956 && target.taskAffinity.equals(p.task.affinity)) {
6957 // If the activity currently at the bottom has the
6958 // same task affinity as the one we are moving,
6959 // then merge it into the same task.
6960 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006961 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006962 + " out to bottom task " + p.task);
6963 } else {
6964 mCurTask++;
6965 if (mCurTask <= 0) {
6966 mCurTask = 1;
6967 }
6968 target.task = new TaskRecord(mCurTask, target.info, null,
6969 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6970 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006971 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006972 + " out to new task " + target.task);
6973 }
6974 mWindowManager.setAppGroupId(target, task.taskId);
6975 if (replyChainEnd < 0) {
6976 replyChainEnd = targetI;
6977 }
6978 int dstPos = 0;
6979 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6980 p = (HistoryRecord)mHistory.get(srcPos);
6981 if (p.finishing) {
6982 continue;
6983 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006984 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006985 + " out to target's task " + target.task);
6986 task.numActivities--;
6987 p.task = target.task;
6988 target.task.numActivities++;
6989 mHistory.remove(srcPos);
6990 mHistory.add(dstPos, p);
6991 mWindowManager.moveAppToken(dstPos, p);
6992 mWindowManager.setAppGroupId(p, p.task.taskId);
6993 dstPos++;
6994 if (VALIDATE_TOKENS) {
6995 mWindowManager.validateAppTokens(mHistory);
6996 }
6997 i++;
6998 }
6999 if (taskTop == p) {
7000 taskTop = below;
7001 }
7002 if (taskTopI == replyChainEnd) {
7003 taskTopI = -1;
7004 }
7005 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007006 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007007 } else if (forceReset || finishOnTaskLaunch
7008 || clearWhenTaskReset) {
7009 // If the activity should just be removed -- either
7010 // because it asks for it, or the task should be
7011 // cleared -- then finish it and anything that is
7012 // part of its reply chain.
7013 if (clearWhenTaskReset) {
7014 // In this case, we want to finish this activity
7015 // and everything above it, so be sneaky and pretend
7016 // like these are all in the reply chain.
7017 replyChainEnd = targetI+1;
7018 while (replyChainEnd < mHistory.size() &&
7019 ((HistoryRecord)mHistory.get(
7020 replyChainEnd)).task == task) {
7021 replyChainEnd++;
7022 }
7023 replyChainEnd--;
7024 } else if (replyChainEnd < 0) {
7025 replyChainEnd = targetI;
7026 }
7027 HistoryRecord p = null;
7028 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7029 p = (HistoryRecord)mHistory.get(srcPos);
7030 if (p.finishing) {
7031 continue;
7032 }
7033 if (finishActivityLocked(p, srcPos,
7034 Activity.RESULT_CANCELED, null, "reset")) {
7035 replyChainEnd--;
7036 srcPos--;
7037 }
7038 }
7039 if (taskTop == p) {
7040 taskTop = below;
7041 }
7042 if (taskTopI == replyChainEnd) {
7043 taskTopI = -1;
7044 }
7045 replyChainEnd = -1;
7046 } else {
7047 // If we were in the middle of a chain, well the
7048 // activity that started it all doesn't want anything
7049 // special, so leave it all as-is.
7050 replyChainEnd = -1;
7051 }
7052 } else {
7053 // Reached the bottom of the task -- any reply chain
7054 // should be left as-is.
7055 replyChainEnd = -1;
7056 }
7057
7058 } else if (target.resultTo != null) {
7059 // If this activity is sending a reply to a previous
7060 // activity, we can't do anything with it now until
7061 // we reach the start of the reply chain.
7062 // XXX note that we are assuming the result is always
7063 // to the previous activity, which is almost always
7064 // the case but we really shouldn't count on.
7065 if (replyChainEnd < 0) {
7066 replyChainEnd = targetI;
7067 }
7068
7069 } else if (taskTopI >= 0 && allowTaskReparenting
7070 && task.affinity != null
7071 && task.affinity.equals(target.taskAffinity)) {
7072 // We are inside of another task... if this activity has
7073 // an affinity for our task, then either remove it if we are
7074 // clearing or move it over to our task. Note that
7075 // we currently punt on the case where we are resetting a
7076 // task that is not at the top but who has activities above
7077 // with an affinity to it... this is really not a normal
7078 // case, and we will need to later pull that task to the front
7079 // and usually at that point we will do the reset and pick
7080 // up those remaining activities. (This only happens if
7081 // someone starts an activity in a new task from an activity
7082 // in a task that is not currently on top.)
7083 if (forceReset || finishOnTaskLaunch) {
7084 if (replyChainEnd < 0) {
7085 replyChainEnd = targetI;
7086 }
7087 HistoryRecord p = null;
7088 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7089 p = (HistoryRecord)mHistory.get(srcPos);
7090 if (p.finishing) {
7091 continue;
7092 }
7093 if (finishActivityLocked(p, srcPos,
7094 Activity.RESULT_CANCELED, null, "reset")) {
7095 taskTopI--;
7096 lastReparentPos--;
7097 replyChainEnd--;
7098 srcPos--;
7099 }
7100 }
7101 replyChainEnd = -1;
7102 } else {
7103 if (replyChainEnd < 0) {
7104 replyChainEnd = targetI;
7105 }
7106 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7107 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7108 if (p.finishing) {
7109 continue;
7110 }
7111 if (lastReparentPos < 0) {
7112 lastReparentPos = taskTopI;
7113 taskTop = p;
7114 } else {
7115 lastReparentPos--;
7116 }
7117 mHistory.remove(srcPos);
7118 p.task.numActivities--;
7119 p.task = task;
7120 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007121 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007122 + " in to resetting task " + task);
7123 task.numActivities++;
7124 mWindowManager.moveAppToken(lastReparentPos, p);
7125 mWindowManager.setAppGroupId(p, p.task.taskId);
7126 if (VALIDATE_TOKENS) {
7127 mWindowManager.validateAppTokens(mHistory);
7128 }
7129 }
7130 replyChainEnd = -1;
7131
7132 // Now we've moved it in to place... but what if this is
7133 // a singleTop activity and we have put it on top of another
7134 // instance of the same activity? Then we drop the instance
7135 // below so it remains singleTop.
7136 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7137 for (int j=lastReparentPos-1; j>=0; j--) {
7138 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7139 if (p.finishing) {
7140 continue;
7141 }
7142 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7143 if (finishActivityLocked(p, j,
7144 Activity.RESULT_CANCELED, null, "replace")) {
7145 taskTopI--;
7146 lastReparentPos--;
7147 }
7148 }
7149 }
7150 }
7151 }
7152 }
7153
7154 target = below;
7155 targetI = i;
7156 }
7157
7158 return taskTop;
7159 }
7160
7161 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007162 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007163 */
7164 public void moveTaskToFront(int task) {
7165 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7166 "moveTaskToFront()");
7167
7168 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007169 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7170 Binder.getCallingUid(), "Task to front")) {
7171 return;
7172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007173 final long origId = Binder.clearCallingIdentity();
7174 try {
7175 int N = mRecentTasks.size();
7176 for (int i=0; i<N; i++) {
7177 TaskRecord tr = mRecentTasks.get(i);
7178 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007179 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180 return;
7181 }
7182 }
7183 for (int i=mHistory.size()-1; i>=0; i--) {
7184 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7185 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007186 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007187 return;
7188 }
7189 }
7190 } finally {
7191 Binder.restoreCallingIdentity(origId);
7192 }
7193 }
7194 }
7195
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007196 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007197 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007198
7199 final int task = tr.taskId;
7200 int top = mHistory.size()-1;
7201
7202 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7203 // nothing to do!
7204 return;
7205 }
7206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 ArrayList moved = new ArrayList();
7208
7209 // Applying the affinities may have removed entries from the history,
7210 // so get the size again.
7211 top = mHistory.size()-1;
7212 int pos = top;
7213
7214 // Shift all activities with this task up to the top
7215 // of the stack, keeping them in the same internal order.
7216 while (pos >= 0) {
7217 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007218 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007219 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7220 boolean first = true;
7221 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007222 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007223 mHistory.remove(pos);
7224 mHistory.add(top, r);
7225 moved.add(0, r);
7226 top--;
7227 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007228 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007229 first = false;
7230 }
7231 }
7232 pos--;
7233 }
7234
Joe Onorato8a9b2202010-02-26 18:56:32 -08007235 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007236 "Prepare to front transition: task=" + tr);
7237 if (reason != null &&
7238 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7239 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7240 HistoryRecord r = topRunningActivityLocked(null);
7241 if (r != null) {
7242 mNoAnimActivities.add(r);
7243 }
7244 } else {
7245 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7246 }
7247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007248 mWindowManager.moveAppTokensToTop(moved);
7249 if (VALIDATE_TOKENS) {
7250 mWindowManager.validateAppTokens(mHistory);
7251 }
7252
Josh Bartel7f208742010-02-25 11:01:44 -06007253 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007254 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007255 }
7256
Josh Bartel7f208742010-02-25 11:01:44 -06007257 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007258 resumeTopActivityLocked(null);
7259 }
7260
7261 public void moveTaskToBack(int task) {
7262 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7263 "moveTaskToBack()");
7264
7265 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007266 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7267 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7268 Binder.getCallingUid(), "Task to back")) {
7269 return;
7270 }
7271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007273 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007274 Binder.restoreCallingIdentity(origId);
7275 }
7276 }
7277
7278 /**
7279 * Moves an activity, and all of the other activities within the same task, to the bottom
7280 * of the history stack. The activity's order within the task is unchanged.
7281 *
7282 * @param token A reference to the activity we wish to move
7283 * @param nonRoot If false then this only works if the activity is the root
7284 * of a task; if true it will work for any activity in a task.
7285 * @return Returns true if the move completed, false if not.
7286 */
7287 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7288 synchronized(this) {
7289 final long origId = Binder.clearCallingIdentity();
7290 int taskId = getTaskForActivityLocked(token, !nonRoot);
7291 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007292 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007293 }
7294 Binder.restoreCallingIdentity(origId);
7295 }
7296 return false;
7297 }
7298
7299 /**
7300 * Worker method for rearranging history stack. Implements the function of moving all
7301 * activities for a specific task (gathering them if disjoint) into a single group at the
7302 * bottom of the stack.
7303 *
7304 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7305 * to premeptively cancel the move.
7306 *
7307 * @param task The taskId to collect and move to the bottom.
7308 * @return Returns true if the move completed, false if not.
7309 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007310 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007311 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007312
7313 // If we have a watcher, preflight the move before committing to it. First check
7314 // for *other* available tasks, but if none are available, then try again allowing the
7315 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007316 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007317 HistoryRecord next = topRunningActivityLocked(null, task);
7318 if (next == null) {
7319 next = topRunningActivityLocked(null, 0);
7320 }
7321 if (next != null) {
7322 // ask watcher if this is allowed
7323 boolean moveOK = true;
7324 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007325 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007327 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007328 }
7329 if (!moveOK) {
7330 return false;
7331 }
7332 }
7333 }
7334
7335 ArrayList moved = new ArrayList();
7336
Joe Onorato8a9b2202010-02-26 18:56:32 -08007337 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007338 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007339
7340 final int N = mHistory.size();
7341 int bottom = 0;
7342 int pos = 0;
7343
7344 // Shift all activities with this task down to the bottom
7345 // of the stack, keeping them in the same internal order.
7346 while (pos < N) {
7347 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007348 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007349 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7350 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007351 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352 mHistory.remove(pos);
7353 mHistory.add(bottom, r);
7354 moved.add(r);
7355 bottom++;
7356 }
7357 pos++;
7358 }
7359
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007360 if (reason != null &&
7361 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7362 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7363 HistoryRecord r = topRunningActivityLocked(null);
7364 if (r != null) {
7365 mNoAnimActivities.add(r);
7366 }
7367 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007368 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007370 mWindowManager.moveAppTokensToBottom(moved);
7371 if (VALIDATE_TOKENS) {
7372 mWindowManager.validateAppTokens(mHistory);
7373 }
7374
Josh Bartel7f208742010-02-25 11:01:44 -06007375 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 return true;
7377 }
7378
7379 public void moveTaskBackwards(int task) {
7380 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7381 "moveTaskBackwards()");
7382
7383 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007384 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7385 Binder.getCallingUid(), "Task backwards")) {
7386 return;
7387 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 final long origId = Binder.clearCallingIdentity();
7389 moveTaskBackwardsLocked(task);
7390 Binder.restoreCallingIdentity(origId);
7391 }
7392 }
7393
7394 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007395 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007396 }
7397
7398 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7399 synchronized(this) {
7400 return getTaskForActivityLocked(token, onlyRoot);
7401 }
7402 }
7403
7404 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7405 final int N = mHistory.size();
7406 TaskRecord lastTask = null;
7407 for (int i=0; i<N; i++) {
7408 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7409 if (r == token) {
7410 if (!onlyRoot || lastTask != r.task) {
7411 return r.task.taskId;
7412 }
7413 return -1;
7414 }
7415 lastTask = r.task;
7416 }
7417
7418 return -1;
7419 }
7420
7421 /**
7422 * Returns the top activity in any existing task matching the given
7423 * Intent. Returns null if no such task is found.
7424 */
7425 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7426 ComponentName cls = intent.getComponent();
7427 if (info.targetActivity != null) {
7428 cls = new ComponentName(info.packageName, info.targetActivity);
7429 }
7430
7431 TaskRecord cp = null;
7432
7433 final int N = mHistory.size();
7434 for (int i=(N-1); i>=0; i--) {
7435 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7436 if (!r.finishing && r.task != cp
7437 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7438 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007439 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 // + "/aff=" + r.task.affinity + " to new cls="
7441 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7442 if (r.task.affinity != null) {
7443 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007444 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007445 return r;
7446 }
7447 } else if (r.task.intent != null
7448 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007449 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007450 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007451 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007452 return r;
7453 } else if (r.task.affinityIntent != null
7454 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007455 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007456 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007457 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458 return r;
7459 }
7460 }
7461 }
7462
7463 return null;
7464 }
7465
7466 /**
7467 * Returns the first activity (starting from the top of the stack) that
7468 * is the same as the given activity. Returns null if no such activity
7469 * is found.
7470 */
7471 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7472 ComponentName cls = intent.getComponent();
7473 if (info.targetActivity != null) {
7474 cls = new ComponentName(info.packageName, info.targetActivity);
7475 }
7476
7477 final int N = mHistory.size();
7478 for (int i=(N-1); i>=0; i--) {
7479 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7480 if (!r.finishing) {
7481 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007482 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007483 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007484 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007485 return r;
7486 }
7487 }
7488 }
7489
7490 return null;
7491 }
7492
7493 public void finishOtherInstances(IBinder token, ComponentName className) {
7494 synchronized(this) {
7495 final long origId = Binder.clearCallingIdentity();
7496
7497 int N = mHistory.size();
7498 TaskRecord lastTask = null;
7499 for (int i=0; i<N; i++) {
7500 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7501 if (r.realActivity.equals(className)
7502 && r != token && lastTask != r.task) {
7503 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7504 null, "others")) {
7505 i--;
7506 N--;
7507 }
7508 }
7509 lastTask = r.task;
7510 }
7511
7512 Binder.restoreCallingIdentity(origId);
7513 }
7514 }
7515
7516 // =========================================================
7517 // THUMBNAILS
7518 // =========================================================
7519
7520 public void reportThumbnail(IBinder token,
7521 Bitmap thumbnail, CharSequence description) {
7522 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7523 final long origId = Binder.clearCallingIdentity();
7524 sendPendingThumbnail(null, token, thumbnail, description, true);
7525 Binder.restoreCallingIdentity(origId);
7526 }
7527
7528 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7529 Bitmap thumbnail, CharSequence description, boolean always) {
7530 TaskRecord task = null;
7531 ArrayList receivers = null;
7532
7533 //System.out.println("Send pending thumbnail: " + r);
7534
7535 synchronized(this) {
7536 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007537 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007538 if (index < 0) {
7539 return;
7540 }
7541 r = (HistoryRecord)mHistory.get(index);
7542 }
7543 if (thumbnail == null) {
7544 thumbnail = r.thumbnail;
7545 description = r.description;
7546 }
7547 if (thumbnail == null && !always) {
7548 // If there is no thumbnail, and this entry is not actually
7549 // going away, then abort for now and pick up the next
7550 // thumbnail we get.
7551 return;
7552 }
7553 task = r.task;
7554
7555 int N = mPendingThumbnails.size();
7556 int i=0;
7557 while (i<N) {
7558 PendingThumbnailsRecord pr =
7559 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7560 //System.out.println("Looking in " + pr.pendingRecords);
7561 if (pr.pendingRecords.remove(r)) {
7562 if (receivers == null) {
7563 receivers = new ArrayList();
7564 }
7565 receivers.add(pr);
7566 if (pr.pendingRecords.size() == 0) {
7567 pr.finished = true;
7568 mPendingThumbnails.remove(i);
7569 N--;
7570 continue;
7571 }
7572 }
7573 i++;
7574 }
7575 }
7576
7577 if (receivers != null) {
7578 final int N = receivers.size();
7579 for (int i=0; i<N; i++) {
7580 try {
7581 PendingThumbnailsRecord pr =
7582 (PendingThumbnailsRecord)receivers.get(i);
7583 pr.receiver.newThumbnail(
7584 task != null ? task.taskId : -1, thumbnail, description);
7585 if (pr.finished) {
7586 pr.receiver.finished();
7587 }
7588 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007589 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 }
7591 }
7592 }
7593 }
7594
7595 // =========================================================
7596 // CONTENT PROVIDERS
7597 // =========================================================
7598
7599 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7600 List providers = null;
7601 try {
7602 providers = ActivityThread.getPackageManager().
7603 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007604 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007605 } catch (RemoteException ex) {
7606 }
7607 if (providers != null) {
7608 final int N = providers.size();
7609 for (int i=0; i<N; i++) {
7610 ProviderInfo cpi =
7611 (ProviderInfo)providers.get(i);
7612 ContentProviderRecord cpr =
7613 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7614 if (cpr == null) {
7615 cpr = new ContentProviderRecord(cpi, app.info);
7616 mProvidersByClass.put(cpi.name, cpr);
7617 }
7618 app.pubProviders.put(cpi.name, cpr);
7619 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007620 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007621 }
7622 }
7623 return providers;
7624 }
7625
7626 private final String checkContentProviderPermissionLocked(
7627 ProviderInfo cpi, ProcessRecord r, int mode) {
7628 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7629 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7630 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7631 cpi.exported ? -1 : cpi.applicationInfo.uid)
7632 == PackageManager.PERMISSION_GRANTED
7633 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7634 return null;
7635 }
7636 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7637 cpi.exported ? -1 : cpi.applicationInfo.uid)
7638 == PackageManager.PERMISSION_GRANTED) {
7639 return null;
7640 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007641
7642 PathPermission[] pps = cpi.pathPermissions;
7643 if (pps != null) {
7644 int i = pps.length;
7645 while (i > 0) {
7646 i--;
7647 PathPermission pp = pps[i];
7648 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7649 cpi.exported ? -1 : cpi.applicationInfo.uid)
7650 == PackageManager.PERMISSION_GRANTED
7651 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7652 return null;
7653 }
7654 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7655 cpi.exported ? -1 : cpi.applicationInfo.uid)
7656 == PackageManager.PERMISSION_GRANTED) {
7657 return null;
7658 }
7659 }
7660 }
7661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007662 String msg = "Permission Denial: opening provider " + cpi.name
7663 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7664 + ", uid=" + callingUid + ") requires "
7665 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007666 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007667 return msg;
7668 }
7669
7670 private final ContentProviderHolder getContentProviderImpl(
7671 IApplicationThread caller, String name) {
7672 ContentProviderRecord cpr;
7673 ProviderInfo cpi = null;
7674
7675 synchronized(this) {
7676 ProcessRecord r = null;
7677 if (caller != null) {
7678 r = getRecordForAppLocked(caller);
7679 if (r == null) {
7680 throw new SecurityException(
7681 "Unable to find app for caller " + caller
7682 + " (pid=" + Binder.getCallingPid()
7683 + ") when getting content provider " + name);
7684 }
7685 }
7686
7687 // First check if this content provider has been published...
7688 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7689 if (cpr != null) {
7690 cpi = cpr.info;
7691 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7692 return new ContentProviderHolder(cpi,
7693 cpi.readPermission != null
7694 ? cpi.readPermission : cpi.writePermission);
7695 }
7696
7697 if (r != null && cpr.canRunHere(r)) {
7698 // This provider has been published or is in the process
7699 // of being published... but it is also allowed to run
7700 // in the caller's process, so don't make a connection
7701 // and just let the caller instantiate its own instance.
7702 if (cpr.provider != null) {
7703 // don't give caller the provider object, it needs
7704 // to make its own.
7705 cpr = new ContentProviderRecord(cpr);
7706 }
7707 return cpr;
7708 }
7709
7710 final long origId = Binder.clearCallingIdentity();
7711
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007712 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713 // return it right away.
7714 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007715 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007716 "Adding provider requested by "
7717 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007718 + cpr.info.processName);
7719 Integer cnt = r.conProviders.get(cpr);
7720 if (cnt == null) {
7721 r.conProviders.put(cpr, new Integer(1));
7722 } else {
7723 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007725 cpr.clients.add(r);
7726 } else {
7727 cpr.externals++;
7728 }
7729
7730 if (cpr.app != null) {
7731 updateOomAdjLocked(cpr.app);
7732 }
7733
7734 Binder.restoreCallingIdentity(origId);
7735
7736 } else {
7737 try {
7738 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007739 resolveContentProvider(name,
7740 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007741 } catch (RemoteException ex) {
7742 }
7743 if (cpi == null) {
7744 return null;
7745 }
7746
7747 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7748 return new ContentProviderHolder(cpi,
7749 cpi.readPermission != null
7750 ? cpi.readPermission : cpi.writePermission);
7751 }
7752
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007753 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7754 && !cpi.processName.equals("system")) {
7755 // If this content provider does not run in the system
7756 // process, and the system is not yet ready to run other
7757 // processes, then fail fast instead of hanging.
7758 throw new IllegalArgumentException(
7759 "Attempt to launch content provider before system ready");
7760 }
7761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7763 final boolean firstClass = cpr == null;
7764 if (firstClass) {
7765 try {
7766 ApplicationInfo ai =
7767 ActivityThread.getPackageManager().
7768 getApplicationInfo(
7769 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007770 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007772 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007773 + cpi.name);
7774 return null;
7775 }
7776 cpr = new ContentProviderRecord(cpi, ai);
7777 } catch (RemoteException ex) {
7778 // pm is in same process, this will never happen.
7779 }
7780 }
7781
7782 if (r != null && cpr.canRunHere(r)) {
7783 // If this is a multiprocess provider, then just return its
7784 // info and allow the caller to instantiate it. Only do
7785 // this if the provider is the same user as the caller's
7786 // process, or can run as root (so can be in any process).
7787 return cpr;
7788 }
7789
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007790 if (DEBUG_PROVIDER) {
7791 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007792 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007793 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 }
7795
7796 // This is single process, and our app is now connecting to it.
7797 // See if we are already in the process of launching this
7798 // provider.
7799 final int N = mLaunchingProviders.size();
7800 int i;
7801 for (i=0; i<N; i++) {
7802 if (mLaunchingProviders.get(i) == cpr) {
7803 break;
7804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007805 }
7806
7807 // If the provider is not already being launched, then get it
7808 // started.
7809 if (i >= N) {
7810 final long origId = Binder.clearCallingIdentity();
7811 ProcessRecord proc = startProcessLocked(cpi.processName,
7812 cpr.appInfo, false, 0, "content provider",
7813 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007814 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007815 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007816 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007817 + cpi.applicationInfo.packageName + "/"
7818 + cpi.applicationInfo.uid + " for provider "
7819 + name + ": process is bad");
7820 return null;
7821 }
7822 cpr.launchingApp = proc;
7823 mLaunchingProviders.add(cpr);
7824 Binder.restoreCallingIdentity(origId);
7825 }
7826
7827 // Make sure the provider is published (the same provider class
7828 // may be published under multiple names).
7829 if (firstClass) {
7830 mProvidersByClass.put(cpi.name, cpr);
7831 }
7832 mProvidersByName.put(name, cpr);
7833
7834 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007835 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007836 "Adding provider requested by "
7837 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007838 + cpr.info.processName);
7839 Integer cnt = r.conProviders.get(cpr);
7840 if (cnt == null) {
7841 r.conProviders.put(cpr, new Integer(1));
7842 } else {
7843 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007845 cpr.clients.add(r);
7846 } else {
7847 cpr.externals++;
7848 }
7849 }
7850 }
7851
7852 // Wait for the provider to be published...
7853 synchronized (cpr) {
7854 while (cpr.provider == null) {
7855 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007856 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007857 + cpi.applicationInfo.packageName + "/"
7858 + cpi.applicationInfo.uid + " for provider "
7859 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007860 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007861 cpi.applicationInfo.packageName,
7862 cpi.applicationInfo.uid, name);
7863 return null;
7864 }
7865 try {
7866 cpr.wait();
7867 } catch (InterruptedException ex) {
7868 }
7869 }
7870 }
7871 return cpr;
7872 }
7873
7874 public final ContentProviderHolder getContentProvider(
7875 IApplicationThread caller, String name) {
7876 if (caller == null) {
7877 String msg = "null IApplicationThread when getting content provider "
7878 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007879 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 throw new SecurityException(msg);
7881 }
7882
7883 return getContentProviderImpl(caller, name);
7884 }
7885
7886 private ContentProviderHolder getContentProviderExternal(String name) {
7887 return getContentProviderImpl(null, name);
7888 }
7889
7890 /**
7891 * Drop a content provider from a ProcessRecord's bookkeeping
7892 * @param cpr
7893 */
7894 public void removeContentProvider(IApplicationThread caller, String name) {
7895 synchronized (this) {
7896 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7897 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007898 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007899 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007900 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 return;
7902 }
7903 final ProcessRecord r = getRecordForAppLocked(caller);
7904 if (r == null) {
7905 throw new SecurityException(
7906 "Unable to find app for caller " + caller +
7907 " when removing content provider " + name);
7908 }
7909 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007910 ContentProviderRecord localCpr = (ContentProviderRecord)
7911 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007912 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007913 + r.info.processName + " from process "
7914 + localCpr.appInfo.processName);
7915 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007916 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007917 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007918 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007919 return;
7920 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007921 Integer cnt = r.conProviders.get(localCpr);
7922 if (cnt == null || cnt.intValue() <= 1) {
7923 localCpr.clients.remove(r);
7924 r.conProviders.remove(localCpr);
7925 } else {
7926 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007928 }
7929 updateOomAdjLocked();
7930 }
7931 }
7932
7933 private void removeContentProviderExternal(String name) {
7934 synchronized (this) {
7935 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7936 if(cpr == null) {
7937 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007938 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007939 return;
7940 }
7941
7942 //update content provider record entry info
7943 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7944 localCpr.externals--;
7945 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007946 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007947 }
7948 updateOomAdjLocked();
7949 }
7950 }
7951
7952 public final void publishContentProviders(IApplicationThread caller,
7953 List<ContentProviderHolder> providers) {
7954 if (providers == null) {
7955 return;
7956 }
7957
7958 synchronized(this) {
7959 final ProcessRecord r = getRecordForAppLocked(caller);
7960 if (r == null) {
7961 throw new SecurityException(
7962 "Unable to find app for caller " + caller
7963 + " (pid=" + Binder.getCallingPid()
7964 + ") when publishing content providers");
7965 }
7966
7967 final long origId = Binder.clearCallingIdentity();
7968
7969 final int N = providers.size();
7970 for (int i=0; i<N; i++) {
7971 ContentProviderHolder src = providers.get(i);
7972 if (src == null || src.info == null || src.provider == null) {
7973 continue;
7974 }
7975 ContentProviderRecord dst =
7976 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7977 if (dst != null) {
7978 mProvidersByClass.put(dst.info.name, dst);
7979 String names[] = dst.info.authority.split(";");
7980 for (int j = 0; j < names.length; j++) {
7981 mProvidersByName.put(names[j], dst);
7982 }
7983
7984 int NL = mLaunchingProviders.size();
7985 int j;
7986 for (j=0; j<NL; j++) {
7987 if (mLaunchingProviders.get(j) == dst) {
7988 mLaunchingProviders.remove(j);
7989 j--;
7990 NL--;
7991 }
7992 }
7993 synchronized (dst) {
7994 dst.provider = src.provider;
7995 dst.app = r;
7996 dst.notifyAll();
7997 }
7998 updateOomAdjLocked(r);
7999 }
8000 }
8001
8002 Binder.restoreCallingIdentity(origId);
8003 }
8004 }
8005
8006 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008007 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008008 synchronized (mSelf) {
8009 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8010 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008011 if (providers != null) {
8012 for (int i=providers.size()-1; i>=0; i--) {
8013 ProviderInfo pi = (ProviderInfo)providers.get(i);
8014 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8015 Slog.w(TAG, "Not installing system proc provider " + pi.name
8016 + ": not system .apk");
8017 providers.remove(i);
8018 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008019 }
8020 }
8021 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008022 if (providers != null) {
8023 mSystemThread.installSystemProviders(providers);
8024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008025 }
8026
8027 // =========================================================
8028 // GLOBAL MANAGEMENT
8029 // =========================================================
8030
8031 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8032 ApplicationInfo info, String customProcess) {
8033 String proc = customProcess != null ? customProcess : info.processName;
8034 BatteryStatsImpl.Uid.Proc ps = null;
8035 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8036 synchronized (stats) {
8037 ps = stats.getProcessStatsLocked(info.uid, proc);
8038 }
8039 return new ProcessRecord(ps, thread, info, proc);
8040 }
8041
8042 final ProcessRecord addAppLocked(ApplicationInfo info) {
8043 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8044
8045 if (app == null) {
8046 app = newProcessRecordLocked(null, info, null);
8047 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008048 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008049 }
8050
8051 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8052 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8053 app.persistent = true;
8054 app.maxAdj = CORE_SERVER_ADJ;
8055 }
8056 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8057 mPersistentStartingProcesses.add(app);
8058 startProcessLocked(app, "added application", app.processName);
8059 }
8060
8061 return app;
8062 }
8063
8064 public void unhandledBack() {
8065 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8066 "unhandledBack()");
8067
8068 synchronized(this) {
8069 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008070 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008071 TAG, "Performing unhandledBack(): stack size = " + count);
8072 if (count > 1) {
8073 final long origId = Binder.clearCallingIdentity();
8074 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8075 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8076 Binder.restoreCallingIdentity(origId);
8077 }
8078 }
8079 }
8080
8081 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8082 String name = uri.getAuthority();
8083 ContentProviderHolder cph = getContentProviderExternal(name);
8084 ParcelFileDescriptor pfd = null;
8085 if (cph != null) {
8086 // We record the binder invoker's uid in thread-local storage before
8087 // going to the content provider to open the file. Later, in the code
8088 // that handles all permissions checks, we look for this uid and use
8089 // that rather than the Activity Manager's own uid. The effect is that
8090 // we do the check against the caller's permissions even though it looks
8091 // to the content provider like the Activity Manager itself is making
8092 // the request.
8093 sCallerIdentity.set(new Identity(
8094 Binder.getCallingPid(), Binder.getCallingUid()));
8095 try {
8096 pfd = cph.provider.openFile(uri, "r");
8097 } catch (FileNotFoundException e) {
8098 // do nothing; pfd will be returned null
8099 } finally {
8100 // Ensure that whatever happens, we clean up the identity state
8101 sCallerIdentity.remove();
8102 }
8103
8104 // We've got the fd now, so we're done with the provider.
8105 removeContentProviderExternal(name);
8106 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008107 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008108 }
8109 return pfd;
8110 }
8111
8112 public void goingToSleep() {
8113 synchronized(this) {
8114 mSleeping = true;
8115 mWindowManager.setEventDispatching(false);
8116
8117 if (mResumedActivity != null) {
8118 pauseIfSleepingLocked();
8119 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008120 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121 }
8122 }
8123 }
8124
Dianne Hackborn55280a92009-05-07 15:53:46 -07008125 public boolean shutdown(int timeout) {
8126 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8127 != PackageManager.PERMISSION_GRANTED) {
8128 throw new SecurityException("Requires permission "
8129 + android.Manifest.permission.SHUTDOWN);
8130 }
8131
8132 boolean timedout = false;
8133
8134 synchronized(this) {
8135 mShuttingDown = true;
8136 mWindowManager.setEventDispatching(false);
8137
8138 if (mResumedActivity != null) {
8139 pauseIfSleepingLocked();
8140 final long endTime = System.currentTimeMillis() + timeout;
8141 while (mResumedActivity != null || mPausingActivity != null) {
8142 long delay = endTime - System.currentTimeMillis();
8143 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008144 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008145 timedout = true;
8146 break;
8147 }
8148 try {
8149 this.wait();
8150 } catch (InterruptedException e) {
8151 }
8152 }
8153 }
8154 }
8155
8156 mUsageStatsService.shutdown();
8157 mBatteryStatsService.shutdown();
8158
8159 return timedout;
8160 }
8161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008163 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008164 if (!mGoingToSleep.isHeld()) {
8165 mGoingToSleep.acquire();
8166 if (mLaunchingActivity.isHeld()) {
8167 mLaunchingActivity.release();
8168 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8169 }
8170 }
8171
8172 // If we are not currently pausing an activity, get the current
8173 // one to pause. If we are pausing one, we will just let that stuff
8174 // run and release the wake lock when all done.
8175 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008176 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8177 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 startPausingLocked(false, true);
8179 }
8180 }
8181 }
8182
8183 public void wakingUp() {
8184 synchronized(this) {
8185 if (mGoingToSleep.isHeld()) {
8186 mGoingToSleep.release();
8187 }
8188 mWindowManager.setEventDispatching(true);
8189 mSleeping = false;
8190 resumeTopActivityLocked(null);
8191 }
8192 }
8193
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008194 public void stopAppSwitches() {
8195 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8196 != PackageManager.PERMISSION_GRANTED) {
8197 throw new SecurityException("Requires permission "
8198 + android.Manifest.permission.STOP_APP_SWITCHES);
8199 }
8200
8201 synchronized(this) {
8202 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8203 + APP_SWITCH_DELAY_TIME;
8204 mDidAppSwitch = false;
8205 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8206 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8207 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8208 }
8209 }
8210
8211 public void resumeAppSwitches() {
8212 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8213 != PackageManager.PERMISSION_GRANTED) {
8214 throw new SecurityException("Requires permission "
8215 + android.Manifest.permission.STOP_APP_SWITCHES);
8216 }
8217
8218 synchronized(this) {
8219 // Note that we don't execute any pending app switches... we will
8220 // let those wait until either the timeout, or the next start
8221 // activity request.
8222 mAppSwitchesAllowedTime = 0;
8223 }
8224 }
8225
8226 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8227 String name) {
8228 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8229 return true;
8230 }
8231
8232 final int perm = checkComponentPermission(
8233 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8234 callingUid, -1);
8235 if (perm == PackageManager.PERMISSION_GRANTED) {
8236 return true;
8237 }
8238
Joe Onorato8a9b2202010-02-26 18:56:32 -08008239 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008240 return false;
8241 }
8242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008243 public void setDebugApp(String packageName, boolean waitForDebugger,
8244 boolean persistent) {
8245 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8246 "setDebugApp()");
8247
8248 // Note that this is not really thread safe if there are multiple
8249 // callers into it at the same time, but that's not a situation we
8250 // care about.
8251 if (persistent) {
8252 final ContentResolver resolver = mContext.getContentResolver();
8253 Settings.System.putString(
8254 resolver, Settings.System.DEBUG_APP,
8255 packageName);
8256 Settings.System.putInt(
8257 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8258 waitForDebugger ? 1 : 0);
8259 }
8260
8261 synchronized (this) {
8262 if (!persistent) {
8263 mOrigDebugApp = mDebugApp;
8264 mOrigWaitForDebugger = mWaitForDebugger;
8265 }
8266 mDebugApp = packageName;
8267 mWaitForDebugger = waitForDebugger;
8268 mDebugTransient = !persistent;
8269 if (packageName != null) {
8270 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008271 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008272 Binder.restoreCallingIdentity(origId);
8273 }
8274 }
8275 }
8276
8277 public void setAlwaysFinish(boolean enabled) {
8278 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8279 "setAlwaysFinish()");
8280
8281 Settings.System.putInt(
8282 mContext.getContentResolver(),
8283 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8284
8285 synchronized (this) {
8286 mAlwaysFinishActivities = enabled;
8287 }
8288 }
8289
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008290 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008291 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008292 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008293 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008294 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008295 }
8296 }
8297
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008298 public boolean isUserAMonkey() {
8299 // For now the fact that there is a controller implies
8300 // we have a monkey.
8301 synchronized (this) {
8302 return mController != null;
8303 }
8304 }
8305
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008306 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008307 synchronized (this) {
8308 mWatchers.register(watcher);
8309 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008310 }
8311
8312 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008313 synchronized (this) {
8314 mWatchers.unregister(watcher);
8315 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008316 }
8317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008318 public final void enterSafeMode() {
8319 synchronized(this) {
8320 // It only makes sense to do this before the system is ready
8321 // and started launching other packages.
8322 if (!mSystemReady) {
8323 try {
8324 ActivityThread.getPackageManager().enterSafeMode();
8325 } catch (RemoteException e) {
8326 }
8327
8328 View v = LayoutInflater.from(mContext).inflate(
8329 com.android.internal.R.layout.safe_mode, null);
8330 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8331 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8332 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8333 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8334 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8335 lp.format = v.getBackground().getOpacity();
8336 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8337 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8338 ((WindowManager)mContext.getSystemService(
8339 Context.WINDOW_SERVICE)).addView(v, lp);
8340 }
8341 }
8342 }
8343
8344 public void noteWakeupAlarm(IIntentSender sender) {
8345 if (!(sender instanceof PendingIntentRecord)) {
8346 return;
8347 }
8348 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8349 synchronized (stats) {
8350 if (mBatteryStatsService.isOnBattery()) {
8351 mBatteryStatsService.enforceCallingPermission();
8352 PendingIntentRecord rec = (PendingIntentRecord)sender;
8353 int MY_UID = Binder.getCallingUid();
8354 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8355 BatteryStatsImpl.Uid.Pkg pkg =
8356 stats.getPackageStatsLocked(uid, rec.key.packageName);
8357 pkg.incWakeupsLocked();
8358 }
8359 }
8360 }
8361
8362 public boolean killPidsForMemory(int[] pids) {
8363 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8364 throw new SecurityException("killPidsForMemory only available to the system");
8365 }
8366
8367 // XXX Note: don't acquire main activity lock here, because the window
8368 // manager calls in with its locks held.
8369
8370 boolean killed = false;
8371 synchronized (mPidsSelfLocked) {
8372 int[] types = new int[pids.length];
8373 int worstType = 0;
8374 for (int i=0; i<pids.length; i++) {
8375 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8376 if (proc != null) {
8377 int type = proc.setAdj;
8378 types[i] = type;
8379 if (type > worstType) {
8380 worstType = type;
8381 }
8382 }
8383 }
8384
8385 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8386 // then constrain it so we will kill all hidden procs.
8387 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8388 worstType = HIDDEN_APP_MIN_ADJ;
8389 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008390 Slog.w(TAG, "Killing processes for memory at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008391 for (int i=0; i<pids.length; i++) {
8392 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8393 if (proc == null) {
8394 continue;
8395 }
8396 int adj = proc.setAdj;
8397 if (adj >= worstType) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008398 Slog.w(TAG, "Killing for memory: " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008399 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008400 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008401 proc.processName, adj);
8402 killed = true;
8403 Process.killProcess(pids[i]);
8404 }
8405 }
8406 }
8407 return killed;
8408 }
8409
8410 public void reportPss(IApplicationThread caller, int pss) {
8411 Watchdog.PssRequestor req;
8412 String name;
8413 ProcessRecord callerApp;
8414 synchronized (this) {
8415 if (caller == null) {
8416 return;
8417 }
8418 callerApp = getRecordForAppLocked(caller);
8419 if (callerApp == null) {
8420 return;
8421 }
8422 callerApp.lastPss = pss;
8423 req = callerApp;
8424 name = callerApp.processName;
8425 }
8426 Watchdog.getInstance().reportPss(req, name, pss);
8427 if (!callerApp.persistent) {
8428 removeRequestedPss(callerApp);
8429 }
8430 }
8431
8432 public void requestPss(Runnable completeCallback) {
8433 ArrayList<ProcessRecord> procs;
8434 synchronized (this) {
8435 mRequestPssCallback = completeCallback;
8436 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008437 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8438 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008439 if (!proc.persistent) {
8440 mRequestPssList.add(proc);
8441 }
8442 }
8443 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8444 }
8445
8446 int oldPri = Process.getThreadPriority(Process.myTid());
8447 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8448 for (int i=procs.size()-1; i>=0; i--) {
8449 ProcessRecord proc = procs.get(i);
8450 proc.lastPss = 0;
8451 proc.requestPss();
8452 }
8453 Process.setThreadPriority(oldPri);
8454 }
8455
8456 void removeRequestedPss(ProcessRecord proc) {
8457 Runnable callback = null;
8458 synchronized (this) {
8459 if (mRequestPssList.remove(proc)) {
8460 if (mRequestPssList.size() == 0) {
8461 callback = mRequestPssCallback;
8462 mRequestPssCallback = null;
8463 }
8464 }
8465 }
8466
8467 if (callback != null) {
8468 callback.run();
8469 }
8470 }
8471
8472 public void collectPss(Watchdog.PssStats stats) {
8473 stats.mEmptyPss = 0;
8474 stats.mEmptyCount = 0;
8475 stats.mBackgroundPss = 0;
8476 stats.mBackgroundCount = 0;
8477 stats.mServicePss = 0;
8478 stats.mServiceCount = 0;
8479 stats.mVisiblePss = 0;
8480 stats.mVisibleCount = 0;
8481 stats.mForegroundPss = 0;
8482 stats.mForegroundCount = 0;
8483 stats.mNoPssCount = 0;
8484 synchronized (this) {
8485 int i;
8486 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8487 ? mProcDeaths.length : stats.mProcDeaths.length;
8488 int aggr = 0;
8489 for (i=0; i<NPD; i++) {
8490 aggr += mProcDeaths[i];
8491 stats.mProcDeaths[i] = aggr;
8492 }
8493 while (i<stats.mProcDeaths.length) {
8494 stats.mProcDeaths[i] = 0;
8495 i++;
8496 }
8497
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008498 for (i=mLruProcesses.size()-1; i>=0; i--) {
8499 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008500 if (proc.persistent) {
8501 continue;
8502 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008503 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008504 if (proc.lastPss == 0) {
8505 stats.mNoPssCount++;
8506 continue;
8507 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008508 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8509 if (proc.empty) {
8510 stats.mEmptyPss += proc.lastPss;
8511 stats.mEmptyCount++;
8512 } else {
8513 stats.mBackgroundPss += proc.lastPss;
8514 stats.mBackgroundCount++;
8515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8517 stats.mVisiblePss += proc.lastPss;
8518 stats.mVisibleCount++;
8519 } else {
8520 stats.mForegroundPss += proc.lastPss;
8521 stats.mForegroundCount++;
8522 }
8523 }
8524 }
8525 }
8526
8527 public final void startRunning(String pkg, String cls, String action,
8528 String data) {
8529 synchronized(this) {
8530 if (mStartRunning) {
8531 return;
8532 }
8533 mStartRunning = true;
8534 mTopComponent = pkg != null && cls != null
8535 ? new ComponentName(pkg, cls) : null;
8536 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8537 mTopData = data;
8538 if (!mSystemReady) {
8539 return;
8540 }
8541 }
8542
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008543 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008544 }
8545
8546 private void retrieveSettings() {
8547 final ContentResolver resolver = mContext.getContentResolver();
8548 String debugApp = Settings.System.getString(
8549 resolver, Settings.System.DEBUG_APP);
8550 boolean waitForDebugger = Settings.System.getInt(
8551 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8552 boolean alwaysFinishActivities = Settings.System.getInt(
8553 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8554
8555 Configuration configuration = new Configuration();
8556 Settings.System.getConfiguration(resolver, configuration);
8557
8558 synchronized (this) {
8559 mDebugApp = mOrigDebugApp = debugApp;
8560 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8561 mAlwaysFinishActivities = alwaysFinishActivities;
8562 // This happens before any activities are started, so we can
8563 // change mConfiguration in-place.
8564 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008565 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008566 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008567 }
8568 }
8569
8570 public boolean testIsSystemReady() {
8571 // no need to synchronize(this) just to read & return the value
8572 return mSystemReady;
8573 }
8574
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008575 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008576 // In the simulator, startRunning will never have been called, which
8577 // normally sets a few crucial variables. Do it here instead.
8578 if (!Process.supportsProcesses()) {
8579 mStartRunning = true;
8580 mTopAction = Intent.ACTION_MAIN;
8581 }
8582
8583 synchronized(this) {
8584 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008585 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008586 return;
8587 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008588
8589 // Check to see if there are any update receivers to run.
8590 if (!mDidUpdate) {
8591 if (mWaitingUpdate) {
8592 return;
8593 }
8594 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8595 List<ResolveInfo> ris = null;
8596 try {
8597 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8598 intent, null, 0);
8599 } catch (RemoteException e) {
8600 }
8601 if (ris != null) {
8602 for (int i=ris.size()-1; i>=0; i--) {
8603 if ((ris.get(i).activityInfo.applicationInfo.flags
8604 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8605 ris.remove(i);
8606 }
8607 }
8608 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8609 for (int i=0; i<ris.size(); i++) {
8610 ActivityInfo ai = ris.get(i).activityInfo;
8611 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8612 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008613 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008614 finisher = new IIntentReceiver.Stub() {
8615 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008616 String data, Bundle extras, boolean ordered,
8617 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008618 throws RemoteException {
8619 synchronized (ActivityManagerService.this) {
8620 mDidUpdate = true;
8621 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008622 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008623 }
8624 };
8625 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008626 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008627 broadcastIntentLocked(null, null, intent, null, finisher,
8628 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008629 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008630 mWaitingUpdate = true;
8631 }
8632 }
8633 }
8634 if (mWaitingUpdate) {
8635 return;
8636 }
8637 mDidUpdate = true;
8638 }
8639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008640 mSystemReady = true;
8641 if (!mStartRunning) {
8642 return;
8643 }
8644 }
8645
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008646 ArrayList<ProcessRecord> procsToKill = null;
8647 synchronized(mPidsSelfLocked) {
8648 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8649 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8650 if (!isAllowedWhileBooting(proc.info)){
8651 if (procsToKill == null) {
8652 procsToKill = new ArrayList<ProcessRecord>();
8653 }
8654 procsToKill.add(proc);
8655 }
8656 }
8657 }
8658
8659 if (procsToKill != null) {
8660 synchronized(this) {
8661 for (int i=procsToKill.size()-1; i>=0; i--) {
8662 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008663 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008664 removeProcessLocked(proc, true);
8665 }
8666 }
8667 }
8668
Joe Onorato8a9b2202010-02-26 18:56:32 -08008669 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008670 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008671 SystemClock.uptimeMillis());
8672
8673 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008674 // Make sure we have no pre-ready processes sitting around.
8675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008676 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8677 ResolveInfo ri = mContext.getPackageManager()
8678 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008679 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008680 CharSequence errorMsg = null;
8681 if (ri != null) {
8682 ActivityInfo ai = ri.activityInfo;
8683 ApplicationInfo app = ai.applicationInfo;
8684 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8685 mTopAction = Intent.ACTION_FACTORY_TEST;
8686 mTopData = null;
8687 mTopComponent = new ComponentName(app.packageName,
8688 ai.name);
8689 } else {
8690 errorMsg = mContext.getResources().getText(
8691 com.android.internal.R.string.factorytest_not_system);
8692 }
8693 } else {
8694 errorMsg = mContext.getResources().getText(
8695 com.android.internal.R.string.factorytest_no_action);
8696 }
8697 if (errorMsg != null) {
8698 mTopAction = null;
8699 mTopData = null;
8700 mTopComponent = null;
8701 Message msg = Message.obtain();
8702 msg.what = SHOW_FACTORY_ERROR_MSG;
8703 msg.getData().putCharSequence("msg", errorMsg);
8704 mHandler.sendMessage(msg);
8705 }
8706 }
8707 }
8708
8709 retrieveSettings();
8710
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008711 if (goingCallback != null) goingCallback.run();
8712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008713 synchronized (this) {
8714 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8715 try {
8716 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008717 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 if (apps != null) {
8719 int N = apps.size();
8720 int i;
8721 for (i=0; i<N; i++) {
8722 ApplicationInfo info
8723 = (ApplicationInfo)apps.get(i);
8724 if (info != null &&
8725 !info.packageName.equals("android")) {
8726 addAppLocked(info);
8727 }
8728 }
8729 }
8730 } catch (RemoteException ex) {
8731 // pm is in same process, this will never happen.
8732 }
8733 }
8734
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008735 // Start up initial activity.
8736 mBooting = true;
8737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 try {
8739 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8740 Message msg = Message.obtain();
8741 msg.what = SHOW_UID_ERROR_MSG;
8742 mHandler.sendMessage(msg);
8743 }
8744 } catch (RemoteException e) {
8745 }
8746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008747 resumeTopActivityLocked(null);
8748 }
8749 }
8750
Dan Egnorb7f03672009-12-09 16:22:32 -08008751 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008752 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008753 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008754 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008755 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008756 startAppProblemLocked(app);
8757 app.stopFreezingAllLocked();
8758 return handleAppCrashLocked(app);
8759 }
8760
Dan Egnorb7f03672009-12-09 16:22:32 -08008761 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008762 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008763 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008764 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008765 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8766 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008767 startAppProblemLocked(app);
8768 app.stopFreezingAllLocked();
8769 }
8770
8771 /**
8772 * Generate a process error record, suitable for attachment to a ProcessRecord.
8773 *
8774 * @param app The ProcessRecord in which the error occurred.
8775 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8776 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008777 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008778 * @param shortMsg Short message describing the crash.
8779 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008780 * @param stackTrace Full crash stack trace, may be null.
8781 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 * @return Returns a fully-formed AppErrorStateInfo record.
8783 */
8784 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008785 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008786 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 report.condition = condition;
8789 report.processName = app.processName;
8790 report.pid = app.pid;
8791 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008792 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008793 report.shortMsg = shortMsg;
8794 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008795 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008796
8797 return report;
8798 }
8799
Dan Egnor42471dd2010-01-07 17:25:22 -08008800 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 synchronized (this) {
8802 app.crashing = false;
8803 app.crashingReport = null;
8804 app.notResponding = false;
8805 app.notRespondingReport = null;
8806 if (app.anrDialog == fromDialog) {
8807 app.anrDialog = null;
8808 }
8809 if (app.waitDialog == fromDialog) {
8810 app.waitDialog = null;
8811 }
8812 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008813 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008814 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008815 + app.processName
8816 + " (pid=" + app.pid + ") at user's request");
8817 Process.killProcess(app.pid);
8818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 }
8820 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008821
Dan Egnorb7f03672009-12-09 16:22:32 -08008822 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008823 long now = SystemClock.uptimeMillis();
8824
8825 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8826 app.info.uid);
8827 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8828 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008829 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008830 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008831 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008832 app.info.processName, app.info.uid);
8833 killServicesLocked(app, false);
8834 for (int i=mHistory.size()-1; i>=0; i--) {
8835 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8836 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008837 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 + r.intent.getComponent().flattenToShortString());
8839 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8840 }
8841 }
8842 if (!app.persistent) {
8843 // We don't want to start this process again until the user
8844 // explicitly does so... but for persistent process, we really
8845 // need to keep it running. If a persistent process is actually
8846 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008847 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008848 app.info.processName);
8849 mBadProcesses.put(app.info.processName, app.info.uid, now);
8850 app.bad = true;
8851 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8852 app.removed = true;
8853 removeProcessLocked(app, false);
8854 return false;
8855 }
8856 }
8857
8858 // Bump up the crash count of any services currently running in the proc.
8859 if (app.services.size() != 0) {
8860 // Any services running in the application need to be placed
8861 // back in the pending list.
8862 Iterator it = app.services.iterator();
8863 while (it.hasNext()) {
8864 ServiceRecord sr = (ServiceRecord)it.next();
8865 sr.crashCount++;
8866 }
8867 }
8868
8869 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8870 return true;
8871 }
8872
8873 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008874 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8875 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008876 skipCurrentReceiverLocked(app);
8877 }
8878
8879 void skipCurrentReceiverLocked(ProcessRecord app) {
8880 boolean reschedule = false;
8881 BroadcastRecord r = app.curReceiver;
8882 if (r != null) {
8883 // The current broadcast is waiting for this app's receiver
8884 // to be finished. Looks like that's not going to happen, so
8885 // let the broadcast continue.
8886 logBroadcastReceiverDiscard(r);
8887 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8888 r.resultExtras, r.resultAbort, true);
8889 reschedule = true;
8890 }
8891 r = mPendingBroadcast;
8892 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008893 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008894 "skip & discard pending app " + r);
8895 logBroadcastReceiverDiscard(r);
8896 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8897 r.resultExtras, r.resultAbort, true);
8898 reschedule = true;
8899 }
8900 if (reschedule) {
8901 scheduleBroadcastsLocked();
8902 }
8903 }
8904
Dan Egnor60d87622009-12-16 16:32:58 -08008905 /**
8906 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8907 * The application process will exit immediately after this call returns.
8908 * @param app object of the crashing app, null for the system server
8909 * @param crashInfo describing the exception
8910 */
8911 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8912 ProcessRecord r = findAppProcess(app);
8913
8914 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8915 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008916 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008917 crashInfo.exceptionClassName,
8918 crashInfo.exceptionMessage,
8919 crashInfo.throwFileName,
8920 crashInfo.throwLineNumber);
8921
Dan Egnor42471dd2010-01-07 17:25:22 -08008922 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008923
8924 crashApplication(r, crashInfo);
8925 }
8926
8927 /**
8928 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8929 * @param app object of the crashing app, null for the system server
8930 * @param tag reported by the caller
8931 * @param crashInfo describing the context of the error
8932 * @return true if the process should exit immediately (WTF is fatal)
8933 */
8934 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008935 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008936 ProcessRecord r = findAppProcess(app);
8937
8938 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8939 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008940 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008941 tag, crashInfo.exceptionMessage);
8942
Dan Egnor42471dd2010-01-07 17:25:22 -08008943 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008944
Doug Zongker43866e02010-01-07 12:09:54 -08008945 if (Settings.Secure.getInt(mContext.getContentResolver(),
8946 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008947 crashApplication(r, crashInfo);
8948 return true;
8949 } else {
8950 return false;
8951 }
8952 }
8953
8954 /**
8955 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8956 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8957 */
8958 private ProcessRecord findAppProcess(IBinder app) {
8959 if (app == null) {
8960 return null;
8961 }
8962
8963 synchronized (this) {
8964 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8965 final int NA = apps.size();
8966 for (int ia=0; ia<NA; ia++) {
8967 ProcessRecord p = apps.valueAt(ia);
8968 if (p.thread != null && p.thread.asBinder() == app) {
8969 return p;
8970 }
8971 }
8972 }
8973
Joe Onorato8a9b2202010-02-26 18:56:32 -08008974 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008975 return null;
8976 }
8977 }
8978
8979 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008980 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008981 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008982 * @param process which caused the error, null means the system server
8983 * @param activity which triggered the error, null if unknown
8984 * @param parent activity related to the error, null if unknown
8985 * @param subject line related to the error, null if absent
8986 * @param report in long form describing the error, null if absent
8987 * @param logFile to include in the report, null if none
8988 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008989 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08008990 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08008991 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
8992 final String report, final File logFile,
8993 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08008994 // NOTE -- this must never acquire the ActivityManagerService lock,
8995 // otherwise the watchdog may be prevented from resetting the system.
8996
Dan Egnora455d192010-03-12 08:52:28 -08008997 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08008998 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08008999 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009000 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009001 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009002 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009003 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009004 }
9005
Dan Egnora455d192010-03-12 08:52:28 -08009006 final String dropboxTag = prefix + eventType;
9007 final DropBoxManager dbox = (DropBoxManager)
9008 mContext.getSystemService(Context.DROPBOX_SERVICE);
9009
9010 // Exit early if the dropbox isn't configured to accept this report type.
9011 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9012
9013 final StringBuilder sb = new StringBuilder(1024);
9014 if (process == null || process.pid == MY_PID) {
9015 sb.append("Process: system_server\n");
9016 } else {
9017 sb.append("Process: ").append(process.processName).append("\n");
9018 }
9019 if (process != null) {
9020 int flags = process.info.flags;
9021 IPackageManager pm = ActivityThread.getPackageManager();
9022 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9023 for (String pkg : process.pkgList) {
9024 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009025 try {
Dan Egnora455d192010-03-12 08:52:28 -08009026 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9027 if (pi != null) {
9028 sb.append(" v").append(pi.versionCode);
9029 if (pi.versionName != null) {
9030 sb.append(" (").append(pi.versionName).append(")");
9031 }
9032 }
9033 } catch (RemoteException e) {
9034 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009035 }
Dan Egnora455d192010-03-12 08:52:28 -08009036 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009037 }
Dan Egnora455d192010-03-12 08:52:28 -08009038 }
9039 if (activity != null) {
9040 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9041 }
9042 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9043 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9044 }
9045 if (parent != null && parent != activity) {
9046 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9047 }
9048 if (subject != null) {
9049 sb.append("Subject: ").append(subject).append("\n");
9050 }
9051 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9052 sb.append("\n");
9053
9054 // Do the rest in a worker thread to avoid blocking the caller on I/O
9055 // (After this point, we shouldn't access AMS internal data structures.)
9056 Thread worker = new Thread("Error dump: " + dropboxTag) {
9057 @Override
9058 public void run() {
9059 if (report != null) {
9060 sb.append(report);
9061 }
9062 if (logFile != null) {
9063 try {
9064 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9065 } catch (IOException e) {
9066 Slog.e(TAG, "Error reading " + logFile, e);
9067 }
9068 }
9069 if (crashInfo != null && crashInfo.stackTrace != null) {
9070 sb.append(crashInfo.stackTrace);
9071 }
9072
9073 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9074 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9075 if (lines > 0) {
9076 sb.append("\n");
9077
9078 // Merge several logcat streams, and take the last N lines
9079 InputStreamReader input = null;
9080 try {
9081 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9082 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9083 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9084
9085 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9086 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9087 input = new InputStreamReader(logcat.getInputStream());
9088
9089 int num;
9090 char[] buf = new char[8192];
9091 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9092 } catch (IOException e) {
9093 Slog.e(TAG, "Error running logcat", e);
9094 } finally {
9095 if (input != null) try { input.close(); } catch (IOException e) {}
9096 }
9097 }
9098
9099 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009100 }
Dan Egnora455d192010-03-12 08:52:28 -08009101 };
9102
9103 if (process == null || process.pid == MY_PID) {
9104 worker.run(); // We may be about to die -- need to run this synchronously
9105 } else {
9106 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009107 }
9108 }
9109
9110 /**
9111 * Bring up the "unexpected error" dialog box for a crashing app.
9112 * Deal with edge cases (intercepts from instrumented applications,
9113 * ActivityController, error intent receivers, that sort of thing).
9114 * @param r the application crashing
9115 * @param crashInfo describing the failure
9116 */
9117 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009118 long timeMillis = System.currentTimeMillis();
9119 String shortMsg = crashInfo.exceptionClassName;
9120 String longMsg = crashInfo.exceptionMessage;
9121 String stackTrace = crashInfo.stackTrace;
9122 if (shortMsg != null && longMsg != null) {
9123 longMsg = shortMsg + ": " + longMsg;
9124 } else if (shortMsg != null) {
9125 longMsg = shortMsg;
9126 }
9127
Dan Egnor60d87622009-12-16 16:32:58 -08009128 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009129 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009130 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009131 try {
9132 String name = r != null ? r.processName : null;
9133 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009134 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009135 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009136 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009137 + " at watcher's request");
9138 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009139 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009140 }
9141 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009142 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009143 }
9144 }
9145
9146 final long origId = Binder.clearCallingIdentity();
9147
9148 // If this process is running instrumentation, finish it.
9149 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009150 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009151 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009152 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9153 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009154 Bundle info = new Bundle();
9155 info.putString("shortMsg", shortMsg);
9156 info.putString("longMsg", longMsg);
9157 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9158 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009159 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009160 }
9161
Dan Egnor60d87622009-12-16 16:32:58 -08009162 // If we can't identify the process or it's already exceeded its crash quota,
9163 // quit right away without showing a crash dialog.
9164 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009165 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009166 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009167 }
9168
9169 Message msg = Message.obtain();
9170 msg.what = SHOW_ERROR_MSG;
9171 HashMap data = new HashMap();
9172 data.put("result", result);
9173 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009174 msg.obj = data;
9175 mHandler.sendMessage(msg);
9176
9177 Binder.restoreCallingIdentity(origId);
9178 }
9179
9180 int res = result.get();
9181
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009182 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 synchronized (this) {
9184 if (r != null) {
9185 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9186 SystemClock.uptimeMillis());
9187 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009188 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009189 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009190 }
9191 }
9192
9193 if (appErrorIntent != null) {
9194 try {
9195 mContext.startActivity(appErrorIntent);
9196 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009197 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009200 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009201
9202 Intent createAppErrorIntentLocked(ProcessRecord r,
9203 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9204 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009205 if (report == null) {
9206 return null;
9207 }
9208 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9209 result.setComponent(r.errorReportReceiver);
9210 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9211 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9212 return result;
9213 }
9214
Dan Egnorb7f03672009-12-09 16:22:32 -08009215 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9216 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009217 if (r.errorReportReceiver == null) {
9218 return null;
9219 }
9220
9221 if (!r.crashing && !r.notResponding) {
9222 return null;
9223 }
9224
Dan Egnorb7f03672009-12-09 16:22:32 -08009225 ApplicationErrorReport report = new ApplicationErrorReport();
9226 report.packageName = r.info.packageName;
9227 report.installerPackageName = r.errorReportReceiver.getPackageName();
9228 report.processName = r.processName;
9229 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009230 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009231
Dan Egnorb7f03672009-12-09 16:22:32 -08009232 if (r.crashing) {
9233 report.type = ApplicationErrorReport.TYPE_CRASH;
9234 report.crashInfo = crashInfo;
9235 } else if (r.notResponding) {
9236 report.type = ApplicationErrorReport.TYPE_ANR;
9237 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009238
Dan Egnorb7f03672009-12-09 16:22:32 -08009239 report.anrInfo.activity = r.notRespondingReport.tag;
9240 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9241 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009242 }
9243
Dan Egnorb7f03672009-12-09 16:22:32 -08009244 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009245 }
9246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009247 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9248 // assume our apps are happy - lazy create the list
9249 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9250
9251 synchronized (this) {
9252
9253 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009254 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9255 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009256 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9257 // This one's in trouble, so we'll generate a report for it
9258 // crashes are higher priority (in case there's a crash *and* an anr)
9259 ActivityManager.ProcessErrorStateInfo report = null;
9260 if (app.crashing) {
9261 report = app.crashingReport;
9262 } else if (app.notResponding) {
9263 report = app.notRespondingReport;
9264 }
9265
9266 if (report != null) {
9267 if (errList == null) {
9268 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9269 }
9270 errList.add(report);
9271 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009272 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 " crashing = " + app.crashing +
9274 " notResponding = " + app.notResponding);
9275 }
9276 }
9277 }
9278 }
9279
9280 return errList;
9281 }
9282
9283 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9284 // Lazy instantiation of list
9285 List<ActivityManager.RunningAppProcessInfo> runList = null;
9286 synchronized (this) {
9287 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009288 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9289 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9291 // Generate process state info for running application
9292 ActivityManager.RunningAppProcessInfo currApp =
9293 new ActivityManager.RunningAppProcessInfo(app.processName,
9294 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009295 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009296 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009297 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009298 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9299 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9300 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009301 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9302 } else if (adj >= HOME_APP_ADJ) {
9303 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9304 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009305 } else if (adj >= SECONDARY_SERVER_ADJ) {
9306 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9307 } else if (adj >= VISIBLE_APP_ADJ) {
9308 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9309 } else {
9310 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9311 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009312 currApp.importanceReasonCode = app.adjTypeCode;
9313 if (app.adjSource instanceof ProcessRecord) {
9314 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9315 } else if (app.adjSource instanceof HistoryRecord) {
9316 HistoryRecord r = (HistoryRecord)app.adjSource;
9317 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9318 }
9319 if (app.adjTarget instanceof ComponentName) {
9320 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9321 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009322 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009323 // + " lru=" + currApp.lru);
9324 if (runList == null) {
9325 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9326 }
9327 runList.add(currApp);
9328 }
9329 }
9330 }
9331 return runList;
9332 }
9333
9334 @Override
9335 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009336 if (checkCallingPermission(android.Manifest.permission.DUMP)
9337 != PackageManager.PERMISSION_GRANTED) {
9338 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9339 + Binder.getCallingPid()
9340 + ", uid=" + Binder.getCallingUid()
9341 + " without permission "
9342 + android.Manifest.permission.DUMP);
9343 return;
9344 }
9345
9346 boolean dumpAll = false;
9347
9348 int opti = 0;
9349 while (opti < args.length) {
9350 String opt = args[opti];
9351 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9352 break;
9353 }
9354 opti++;
9355 if ("-a".equals(opt)) {
9356 dumpAll = true;
9357 } else if ("-h".equals(opt)) {
9358 pw.println("Activity manager dump options:");
9359 pw.println(" [-a] [h- [cmd] ...");
9360 pw.println(" cmd may be one of:");
9361 pw.println(" activities: activity stack state");
9362 pw.println(" broadcasts: broadcast state");
9363 pw.println(" intents: pending intent state");
9364 pw.println(" processes: process state");
9365 pw.println(" providers: content provider state");
9366 pw.println(" services: service state");
9367 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009368 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009369 } else {
9370 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009371 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009372 }
9373
9374 // Is the caller requesting to dump a particular piece of data?
9375 if (opti < args.length) {
9376 String cmd = args[opti];
9377 opti++;
9378 if ("activities".equals(cmd) || "a".equals(cmd)) {
9379 synchronized (this) {
9380 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009381 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009382 return;
9383 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9384 synchronized (this) {
9385 dumpBroadcastsLocked(fd, pw, args, opti, true);
9386 }
9387 return;
9388 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9389 synchronized (this) {
9390 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9391 }
9392 return;
9393 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9394 synchronized (this) {
9395 dumpProcessesLocked(fd, pw, args, opti, true);
9396 }
9397 return;
9398 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9399 synchronized (this) {
9400 dumpProvidersLocked(fd, pw, args, opti, true);
9401 }
9402 return;
9403 } else if ("service".equals(cmd)) {
9404 dumpService(fd, pw, args, opti, true);
9405 return;
9406 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9407 synchronized (this) {
9408 dumpServicesLocked(fd, pw, args, opti, true);
9409 }
9410 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009411 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009412 }
9413
9414 // No piece of data specified, dump everything.
9415 synchronized (this) {
9416 boolean needSep;
9417 if (dumpAll) {
9418 pw.println("Providers in Current Activity Manager State:");
9419 }
9420 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9421 if (needSep) {
9422 pw.println(" ");
9423 }
9424 if (dumpAll) {
9425 pw.println("-------------------------------------------------------------------------------");
9426 pw.println("Broadcasts in Current Activity Manager State:");
9427 }
9428 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9429 if (needSep) {
9430 pw.println(" ");
9431 }
9432 if (dumpAll) {
9433 pw.println("-------------------------------------------------------------------------------");
9434 pw.println("Services in Current Activity Manager State:");
9435 }
9436 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9437 if (needSep) {
9438 pw.println(" ");
9439 }
9440 if (dumpAll) {
9441 pw.println("-------------------------------------------------------------------------------");
9442 pw.println("PendingIntents in Current Activity Manager State:");
9443 }
9444 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9445 if (needSep) {
9446 pw.println(" ");
9447 }
9448 if (dumpAll) {
9449 pw.println("-------------------------------------------------------------------------------");
9450 pw.println("Activities in Current Activity Manager State:");
9451 }
9452 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9453 if (needSep) {
9454 pw.println(" ");
9455 }
9456 if (dumpAll) {
9457 pw.println("-------------------------------------------------------------------------------");
9458 pw.println("Processes in Current Activity Manager State:");
9459 }
9460 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9461 }
9462 }
9463
9464 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9465 int opti, boolean dumpAll, boolean needHeader) {
9466 if (needHeader) {
9467 pw.println(" Activity stack:");
9468 }
9469 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9470 pw.println(" ");
9471 pw.println(" Running activities (most recent first):");
9472 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9473 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009474 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009475 pw.println(" Activities waiting for another to become visible:");
9476 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9477 }
9478 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009480 pw.println(" Activities waiting to stop:");
9481 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9482 }
9483 if (mFinishingActivities.size() > 0) {
9484 pw.println(" ");
9485 pw.println(" Activities waiting to finish:");
9486 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009488
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009489 pw.println(" ");
9490 pw.println(" mPausingActivity: " + mPausingActivity);
9491 pw.println(" mResumedActivity: " + mResumedActivity);
9492 pw.println(" mFocusedActivity: " + mFocusedActivity);
9493 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009494
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009495 if (dumpAll && mRecentTasks.size() > 0) {
9496 pw.println(" ");
9497 pw.println("Recent tasks in Current Activity Manager State:");
9498
9499 final int N = mRecentTasks.size();
9500 for (int i=0; i<N; i++) {
9501 TaskRecord tr = mRecentTasks.get(i);
9502 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9503 pw.println(tr);
9504 mRecentTasks.get(i).dump(pw, " ");
9505 }
9506 }
9507
9508 pw.println(" ");
9509 pw.println(" mCurTask: " + mCurTask);
9510
9511 return true;
9512 }
9513
9514 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9515 int opti, boolean dumpAll) {
9516 boolean needSep = false;
9517 int numPers = 0;
9518
9519 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009520 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9521 final int NA = procs.size();
9522 for (int ia=0; ia<NA; ia++) {
9523 if (!needSep) {
9524 pw.println(" All known processes:");
9525 needSep = true;
9526 }
9527 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009528 pw.print(r.persistent ? " *PERS*" : " *APP*");
9529 pw.print(" UID "); pw.print(procs.keyAt(ia));
9530 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009531 r.dump(pw, " ");
9532 if (r.persistent) {
9533 numPers++;
9534 }
9535 }
9536 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009537 }
9538
9539 if (mLruProcesses.size() > 0) {
9540 if (needSep) pw.println(" ");
9541 needSep = true;
9542 pw.println(" Running processes (most recent first):");
9543 dumpProcessList(pw, this, mLruProcesses, " ",
9544 "App ", "PERS", true);
9545 needSep = true;
9546 }
9547
9548 synchronized (mPidsSelfLocked) {
9549 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 if (needSep) pw.println(" ");
9551 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009552 pw.println(" PID mappings:");
9553 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9554 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9555 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009556 }
9557 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009558 }
9559
9560 if (mForegroundProcesses.size() > 0) {
9561 if (needSep) pw.println(" ");
9562 needSep = true;
9563 pw.println(" Foreground Processes:");
9564 for (int i=0; i<mForegroundProcesses.size(); i++) {
9565 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9566 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009567 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009568 }
9569
9570 if (mPersistentStartingProcesses.size() > 0) {
9571 if (needSep) pw.println(" ");
9572 needSep = true;
9573 pw.println(" Persisent processes that are starting:");
9574 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9575 "Starting Norm", "Restarting PERS", false);
9576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009578 if (mStartingProcesses.size() > 0) {
9579 if (needSep) pw.println(" ");
9580 needSep = true;
9581 pw.println(" Processes that are starting:");
9582 dumpProcessList(pw, this, mStartingProcesses, " ",
9583 "Starting Norm", "Starting PERS", false);
9584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009585
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009586 if (mRemovedProcesses.size() > 0) {
9587 if (needSep) pw.println(" ");
9588 needSep = true;
9589 pw.println(" Processes that are being removed:");
9590 dumpProcessList(pw, this, mRemovedProcesses, " ",
9591 "Removed Norm", "Removed PERS", false);
9592 }
9593
9594 if (mProcessesOnHold.size() > 0) {
9595 if (needSep) pw.println(" ");
9596 needSep = true;
9597 pw.println(" Processes that are on old until the system is ready:");
9598 dumpProcessList(pw, this, mProcessesOnHold, " ",
9599 "OnHold Norm", "OnHold PERS", false);
9600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009601
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009602 if (mProcessesToGc.size() > 0) {
9603 if (needSep) pw.println(" ");
9604 needSep = true;
9605 pw.println(" Processes that are waiting to GC:");
9606 long now = SystemClock.uptimeMillis();
9607 for (int i=0; i<mProcessesToGc.size(); i++) {
9608 ProcessRecord proc = mProcessesToGc.get(i);
9609 pw.print(" Process "); pw.println(proc);
9610 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9611 pw.print(", last gced=");
9612 pw.print(now-proc.lastRequestedGc);
9613 pw.print(" ms ago, last lowMem=");
9614 pw.print(now-proc.lastLowMemory);
9615 pw.println(" ms ago");
9616
9617 }
9618 }
9619
9620 if (mProcessCrashTimes.getMap().size() > 0) {
9621 if (needSep) pw.println(" ");
9622 needSep = true;
9623 pw.println(" Time since processes crashed:");
9624 long now = SystemClock.uptimeMillis();
9625 for (Map.Entry<String, SparseArray<Long>> procs
9626 : mProcessCrashTimes.getMap().entrySet()) {
9627 SparseArray<Long> uids = procs.getValue();
9628 final int N = uids.size();
9629 for (int i=0; i<N; i++) {
9630 pw.print(" Process "); pw.print(procs.getKey());
9631 pw.print(" uid "); pw.print(uids.keyAt(i));
9632 pw.print(": last crashed ");
9633 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009634 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009635 }
9636 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009637 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009638
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009639 if (mBadProcesses.getMap().size() > 0) {
9640 if (needSep) pw.println(" ");
9641 needSep = true;
9642 pw.println(" Bad processes:");
9643 for (Map.Entry<String, SparseArray<Long>> procs
9644 : mBadProcesses.getMap().entrySet()) {
9645 SparseArray<Long> uids = procs.getValue();
9646 final int N = uids.size();
9647 for (int i=0; i<N; i++) {
9648 pw.print(" Bad process "); pw.print(procs.getKey());
9649 pw.print(" uid "); pw.print(uids.keyAt(i));
9650 pw.print(": crashed at time ");
9651 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 }
9653 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009654 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009655
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009656 pw.println(" ");
9657 pw.println(" mHomeProcess: " + mHomeProcess);
9658 pw.println(" mConfiguration: " + mConfiguration);
9659 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9660 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9661 || mOrigWaitForDebugger) {
9662 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9663 + " mDebugTransient=" + mDebugTransient
9664 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9665 }
9666 if (mAlwaysFinishActivities || mController != null) {
9667 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9668 + " mController=" + mController);
9669 }
9670 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009671 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009672 pw.println(" mStartRunning=" + mStartRunning
9673 + " mSystemReady=" + mSystemReady
9674 + " mBooting=" + mBooting
9675 + " mBooted=" + mBooted
9676 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009677 pw.println(" mGoingToSleep=" + mGoingToSleep);
9678 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009679 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009680
9681 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009682 }
9683
9684 /**
9685 * There are three ways to call this:
9686 * - no service specified: dump all the services
9687 * - a flattened component name that matched an existing service was specified as the
9688 * first arg: dump that one service
9689 * - the first arg isn't the flattened component name of an existing service:
9690 * dump all services whose component contains the first arg as a substring
9691 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009692 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9693 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009694 String[] newArgs;
9695 String componentNameString;
9696 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009697 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698 componentNameString = null;
9699 newArgs = EMPTY_STRING_ARRAY;
9700 r = null;
9701 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009702 componentNameString = args[opti];
9703 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9705 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009706 newArgs = new String[args.length - opti];
9707 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009708 }
9709
9710 if (r != null) {
9711 dumpService(fd, pw, r, newArgs);
9712 } else {
9713 for (ServiceRecord r1 : mServices.values()) {
9714 if (componentNameString == null
9715 || r1.name.flattenToString().contains(componentNameString)) {
9716 dumpService(fd, pw, r1, newArgs);
9717 }
9718 }
9719 }
9720 }
9721
9722 /**
9723 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9724 * there is a thread associated with the service.
9725 */
9726 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9727 pw.println(" Service " + r.name.flattenToString());
9728 if (r.app != null && r.app.thread != null) {
9729 try {
9730 // flush anything that is already in the PrintWriter since the thread is going
9731 // to write to the file descriptor directly
9732 pw.flush();
9733 r.app.thread.dumpService(fd, r, args);
9734 pw.print("\n");
9735 } catch (RemoteException e) {
9736 pw.println("got a RemoteException while dumping the service");
9737 }
9738 }
9739 }
9740
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009741 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9742 int opti, boolean dumpAll) {
9743 boolean needSep = false;
9744
9745 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009746 if (mRegisteredReceivers.size() > 0) {
9747 pw.println(" ");
9748 pw.println(" Registered Receivers:");
9749 Iterator it = mRegisteredReceivers.values().iterator();
9750 while (it.hasNext()) {
9751 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009752 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009753 r.dump(pw, " ");
9754 }
9755 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 pw.println(" ");
9758 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009759 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009760 needSep = true;
9761 }
9762
9763 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9764 || mPendingBroadcast != null) {
9765 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009766 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009767 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009768 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009769 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9770 pw.println(" Broadcast #" + i + ":");
9771 mParallelBroadcasts.get(i).dump(pw, " ");
9772 }
9773 if (mOrderedBroadcasts.size() > 0) {
9774 pw.println(" ");
9775 pw.println(" Active serialized broadcasts:");
9776 }
9777 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9778 pw.println(" Serialized Broadcast #" + i + ":");
9779 mOrderedBroadcasts.get(i).dump(pw, " ");
9780 }
9781 pw.println(" ");
9782 pw.println(" Pending broadcast:");
9783 if (mPendingBroadcast != null) {
9784 mPendingBroadcast.dump(pw, " ");
9785 } else {
9786 pw.println(" (null)");
9787 }
9788 needSep = true;
9789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009790
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009791 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009792 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009793 pw.println(" Historical broadcasts:");
9794 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9795 BroadcastRecord r = mBroadcastHistory[i];
9796 if (r == null) {
9797 break;
9798 }
9799 pw.println(" Historical Broadcast #" + i + ":");
9800 r.dump(pw, " ");
9801 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009802 needSep = true;
9803 }
9804
9805 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009806 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009807 pw.println(" Sticky broadcasts:");
9808 StringBuilder sb = new StringBuilder(128);
9809 for (Map.Entry<String, ArrayList<Intent>> ent
9810 : mStickyBroadcasts.entrySet()) {
9811 pw.print(" * Sticky action "); pw.print(ent.getKey());
9812 pw.println(":");
9813 ArrayList<Intent> intents = ent.getValue();
9814 final int N = intents.size();
9815 for (int i=0; i<N; i++) {
9816 sb.setLength(0);
9817 sb.append(" Intent: ");
9818 intents.get(i).toShortString(sb, true, false);
9819 pw.println(sb.toString());
9820 Bundle bundle = intents.get(i).getExtras();
9821 if (bundle != null) {
9822 pw.print(" ");
9823 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 }
9825 }
9826 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009827 needSep = true;
9828 }
9829
9830 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009831 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009832 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833 pw.println(" mHandler:");
9834 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009835 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009836 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009837
9838 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 }
9840
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009841 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9842 int opti, boolean dumpAll) {
9843 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009844
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009845 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009846 if (mServices.size() > 0) {
9847 pw.println(" Active services:");
9848 Iterator<ServiceRecord> it = mServices.values().iterator();
9849 while (it.hasNext()) {
9850 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009851 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009852 r.dump(pw, " ");
9853 }
9854 needSep = true;
9855 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009857
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009858 if (mPendingServices.size() > 0) {
9859 if (needSep) pw.println(" ");
9860 pw.println(" Pending services:");
9861 for (int i=0; i<mPendingServices.size(); i++) {
9862 ServiceRecord r = mPendingServices.get(i);
9863 pw.print(" * Pending "); pw.println(r);
9864 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009866 needSep = true;
9867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009869 if (mRestartingServices.size() > 0) {
9870 if (needSep) pw.println(" ");
9871 pw.println(" Restarting services:");
9872 for (int i=0; i<mRestartingServices.size(); i++) {
9873 ServiceRecord r = mRestartingServices.get(i);
9874 pw.print(" * Restarting "); pw.println(r);
9875 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009876 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009877 needSep = true;
9878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009879
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009880 if (mStoppingServices.size() > 0) {
9881 if (needSep) pw.println(" ");
9882 pw.println(" Stopping services:");
9883 for (int i=0; i<mStoppingServices.size(); i++) {
9884 ServiceRecord r = mStoppingServices.get(i);
9885 pw.print(" * Stopping "); pw.println(r);
9886 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009887 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009888 needSep = true;
9889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009890
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009891 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 if (mServiceConnections.size() > 0) {
9893 if (needSep) pw.println(" ");
9894 pw.println(" Connection bindings to services:");
9895 Iterator<ConnectionRecord> it
9896 = mServiceConnections.values().iterator();
9897 while (it.hasNext()) {
9898 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009899 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009900 r.dump(pw, " ");
9901 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009902 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903 }
9904 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009905
9906 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009907 }
9908
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009909 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9910 int opti, boolean dumpAll) {
9911 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009912
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009913 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009914 if (mProvidersByClass.size() > 0) {
9915 if (needSep) pw.println(" ");
9916 pw.println(" Published content providers (by class):");
9917 Iterator it = mProvidersByClass.entrySet().iterator();
9918 while (it.hasNext()) {
9919 Map.Entry e = (Map.Entry)it.next();
9920 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009921 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 r.dump(pw, " ");
9923 }
9924 needSep = true;
9925 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009926
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009927 if (mProvidersByName.size() > 0) {
9928 pw.println(" ");
9929 pw.println(" Authority to provider mappings:");
9930 Iterator it = mProvidersByName.entrySet().iterator();
9931 while (it.hasNext()) {
9932 Map.Entry e = (Map.Entry)it.next();
9933 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9934 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9935 pw.println(r);
9936 }
9937 needSep = true;
9938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009939 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009940
9941 if (mLaunchingProviders.size() > 0) {
9942 if (needSep) pw.println(" ");
9943 pw.println(" Launching content providers:");
9944 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9945 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9946 pw.println(mLaunchingProviders.get(i));
9947 }
9948 needSep = true;
9949 }
9950
9951 if (mGrantedUriPermissions.size() > 0) {
9952 pw.println();
9953 pw.println("Granted Uri Permissions:");
9954 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9955 int uid = mGrantedUriPermissions.keyAt(i);
9956 HashMap<Uri, UriPermission> perms
9957 = mGrantedUriPermissions.valueAt(i);
9958 pw.print(" * UID "); pw.print(uid);
9959 pw.println(" holds:");
9960 for (UriPermission perm : perms.values()) {
9961 pw.print(" "); pw.println(perm);
9962 perm.dump(pw, " ");
9963 }
9964 }
9965 needSep = true;
9966 }
9967
9968 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009969 }
9970
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009971 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9972 int opti, boolean dumpAll) {
9973 boolean needSep = false;
9974
9975 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 if (this.mIntentSenderRecords.size() > 0) {
9977 Iterator<WeakReference<PendingIntentRecord>> it
9978 = mIntentSenderRecords.values().iterator();
9979 while (it.hasNext()) {
9980 WeakReference<PendingIntentRecord> ref = it.next();
9981 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009982 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009983 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009984 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009985 rec.dump(pw, " ");
9986 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009987 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009988 }
9989 }
9990 }
9991 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009992
9993 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009994 }
9995
9996 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009997 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009998 TaskRecord lastTask = null;
9999 for (int i=list.size()-1; i>=0; i--) {
10000 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010001 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 if (lastTask != r.task) {
10003 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010004 pw.print(prefix);
10005 pw.print(full ? "* " : " ");
10006 pw.println(lastTask);
10007 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010008 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010010 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010011 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10012 pw.print(" #"); pw.print(i); pw.print(": ");
10013 pw.println(r);
10014 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010015 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010017 }
10018 }
10019
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010020 private static String buildOomTag(String prefix, String space, int val, int base) {
10021 if (val == base) {
10022 if (space == null) return prefix;
10023 return prefix + " ";
10024 }
10025 return prefix + "+" + Integer.toString(val-base);
10026 }
10027
10028 private static final int dumpProcessList(PrintWriter pw,
10029 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 String prefix, String normalLabel, String persistentLabel,
10031 boolean inclOomAdj) {
10032 int numPers = 0;
10033 for (int i=list.size()-1; i>=0; i--) {
10034 ProcessRecord r = (ProcessRecord)list.get(i);
10035 if (false) {
10036 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10037 + " #" + i + ":");
10038 r.dump(pw, prefix + " ");
10039 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010040 String oomAdj;
10041 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010042 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010043 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010044 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10045 } else if (r.setAdj >= HOME_APP_ADJ) {
10046 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10047 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10048 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10049 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10050 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10051 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10052 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10053 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10054 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010055 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010056 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010057 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010058 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010059 } else {
10060 oomAdj = Integer.toString(r.setAdj);
10061 }
10062 String schedGroup;
10063 switch (r.setSchedGroup) {
10064 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10065 schedGroup = "B";
10066 break;
10067 case Process.THREAD_GROUP_DEFAULT:
10068 schedGroup = "F";
10069 break;
10070 default:
10071 schedGroup = Integer.toString(r.setSchedGroup);
10072 break;
10073 }
10074 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010076 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010077 if (r.adjSource != null || r.adjTarget != null) {
10078 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010079 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010081 } else {
10082 pw.println(String.format("%s%s #%2d: %s",
10083 prefix, (r.persistent ? persistentLabel : normalLabel),
10084 i, r.toString()));
10085 }
10086 if (r.persistent) {
10087 numPers++;
10088 }
10089 }
10090 return numPers;
10091 }
10092
10093 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
10094 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010095 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010096 long uptime = SystemClock.uptimeMillis();
10097 long realtime = SystemClock.elapsedRealtime();
10098
10099 if (isCheckinRequest) {
10100 // short checkin version
10101 pw.println(uptime + "," + realtime);
10102 pw.flush();
10103 } else {
10104 pw.println("Applications Memory Usage (kB):");
10105 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10106 }
10107 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10108 ProcessRecord r = (ProcessRecord)list.get(i);
10109 if (r.thread != null) {
10110 if (!isCheckinRequest) {
10111 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10112 pw.flush();
10113 }
10114 try {
10115 r.thread.asBinder().dump(fd, args);
10116 } catch (RemoteException e) {
10117 if (!isCheckinRequest) {
10118 pw.println("Got RemoteException!");
10119 pw.flush();
10120 }
10121 }
10122 }
10123 }
10124 }
10125
10126 /**
10127 * Searches array of arguments for the specified string
10128 * @param args array of argument strings
10129 * @param value value to search for
10130 * @return true if the value is contained in the array
10131 */
10132 private static boolean scanArgs(String[] args, String value) {
10133 if (args != null) {
10134 for (String arg : args) {
10135 if (value.equals(arg)) {
10136 return true;
10137 }
10138 }
10139 }
10140 return false;
10141 }
10142
Dianne Hackborn75b03852009-06-12 15:43:26 -070010143 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010144 int count = mHistory.size();
10145
10146 // convert the token to an entry in the history.
10147 HistoryRecord r = null;
10148 int index = -1;
10149 for (int i=count-1; i>=0; i--) {
10150 Object o = mHistory.get(i);
10151 if (o == token) {
10152 r = (HistoryRecord)o;
10153 index = i;
10154 break;
10155 }
10156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010157
10158 return index;
10159 }
10160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010161 private final void killServicesLocked(ProcessRecord app,
10162 boolean allowRestart) {
10163 // Report disconnected services.
10164 if (false) {
10165 // XXX we are letting the client link to the service for
10166 // death notifications.
10167 if (app.services.size() > 0) {
10168 Iterator it = app.services.iterator();
10169 while (it.hasNext()) {
10170 ServiceRecord r = (ServiceRecord)it.next();
10171 if (r.connections.size() > 0) {
10172 Iterator<ConnectionRecord> jt
10173 = r.connections.values().iterator();
10174 while (jt.hasNext()) {
10175 ConnectionRecord c = jt.next();
10176 if (c.binding.client != app) {
10177 try {
10178 //c.conn.connected(r.className, null);
10179 } catch (Exception e) {
10180 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010181 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 + r.shortName
10183 + " from app " + app.processName, e);
10184 }
10185 }
10186 }
10187 }
10188 }
10189 }
10190 }
10191
10192 // Clean up any connections this application has to other services.
10193 if (app.connections.size() > 0) {
10194 Iterator<ConnectionRecord> it = app.connections.iterator();
10195 while (it.hasNext()) {
10196 ConnectionRecord r = it.next();
10197 removeConnectionLocked(r, app, null);
10198 }
10199 }
10200 app.connections.clear();
10201
10202 if (app.services.size() != 0) {
10203 // Any services running in the application need to be placed
10204 // back in the pending list.
10205 Iterator it = app.services.iterator();
10206 while (it.hasNext()) {
10207 ServiceRecord sr = (ServiceRecord)it.next();
10208 synchronized (sr.stats.getBatteryStats()) {
10209 sr.stats.stopLaunchedLocked();
10210 }
10211 sr.app = null;
10212 sr.executeNesting = 0;
10213 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010214
10215 boolean hasClients = sr.bindings.size() > 0;
10216 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010217 Iterator<IntentBindRecord> bindings
10218 = sr.bindings.values().iterator();
10219 while (bindings.hasNext()) {
10220 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010221 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010222 + ": shouldUnbind=" + b.hasBound);
10223 b.binder = null;
10224 b.requested = b.received = b.hasBound = false;
10225 }
10226 }
10227
10228 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010229 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010231 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010232 sr.crashCount, sr.shortName, app.pid);
10233 bringDownServiceLocked(sr, true);
10234 } else if (!allowRestart) {
10235 bringDownServiceLocked(sr, true);
10236 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010237 boolean canceled = scheduleServiceRestartLocked(sr, true);
10238
10239 // Should the service remain running? Note that in the
10240 // extreme case of so many attempts to deliver a command
10241 // that it failed, that we also will stop it here.
10242 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10243 if (sr.pendingStarts.size() == 0) {
10244 sr.startRequested = false;
10245 if (!hasClients) {
10246 // Whoops, no reason to restart!
10247 bringDownServiceLocked(sr, true);
10248 }
10249 }
10250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 }
10252 }
10253
10254 if (!allowRestart) {
10255 app.services.clear();
10256 }
10257 }
10258
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010259 // Make sure we have no more records on the stopping list.
10260 int i = mStoppingServices.size();
10261 while (i > 0) {
10262 i--;
10263 ServiceRecord sr = mStoppingServices.get(i);
10264 if (sr.app == app) {
10265 mStoppingServices.remove(i);
10266 }
10267 }
10268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010269 app.executingServices.clear();
10270 }
10271
10272 private final void removeDyingProviderLocked(ProcessRecord proc,
10273 ContentProviderRecord cpr) {
10274 synchronized (cpr) {
10275 cpr.launchingApp = null;
10276 cpr.notifyAll();
10277 }
10278
10279 mProvidersByClass.remove(cpr.info.name);
10280 String names[] = cpr.info.authority.split(";");
10281 for (int j = 0; j < names.length; j++) {
10282 mProvidersByName.remove(names[j]);
10283 }
10284
10285 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10286 while (cit.hasNext()) {
10287 ProcessRecord capp = cit.next();
10288 if (!capp.persistent && capp.thread != null
10289 && capp.pid != 0
10290 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010291 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292 + " (pid " + capp.pid
10293 + ") because provider " + cpr.info.name
10294 + " is in dying process " + proc.processName);
10295 Process.killProcess(capp.pid);
10296 }
10297 }
10298
10299 mLaunchingProviders.remove(cpr);
10300 }
10301
10302 /**
10303 * Main code for cleaning up a process when it has gone away. This is
10304 * called both as a result of the process dying, or directly when stopping
10305 * a process when running in single process mode.
10306 */
10307 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10308 boolean restarting, int index) {
10309 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010310 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010311 }
10312
Dianne Hackborn36124872009-10-08 16:22:03 -070010313 mProcessesToGc.remove(app);
10314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 // Dismiss any open dialogs.
10316 if (app.crashDialog != null) {
10317 app.crashDialog.dismiss();
10318 app.crashDialog = null;
10319 }
10320 if (app.anrDialog != null) {
10321 app.anrDialog.dismiss();
10322 app.anrDialog = null;
10323 }
10324 if (app.waitDialog != null) {
10325 app.waitDialog.dismiss();
10326 app.waitDialog = null;
10327 }
10328
10329 app.crashing = false;
10330 app.notResponding = false;
10331
10332 app.resetPackageList();
10333 app.thread = null;
10334 app.forcingToForeground = null;
10335 app.foregroundServices = false;
10336
10337 killServicesLocked(app, true);
10338
10339 boolean restart = false;
10340
10341 int NL = mLaunchingProviders.size();
10342
10343 // Remove published content providers.
10344 if (!app.pubProviders.isEmpty()) {
10345 Iterator it = app.pubProviders.values().iterator();
10346 while (it.hasNext()) {
10347 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10348 cpr.provider = null;
10349 cpr.app = null;
10350
10351 // See if someone is waiting for this provider... in which
10352 // case we don't remove it, but just let it restart.
10353 int i = 0;
10354 if (!app.bad) {
10355 for (; i<NL; i++) {
10356 if (mLaunchingProviders.get(i) == cpr) {
10357 restart = true;
10358 break;
10359 }
10360 }
10361 } else {
10362 i = NL;
10363 }
10364
10365 if (i >= NL) {
10366 removeDyingProviderLocked(app, cpr);
10367 NL = mLaunchingProviders.size();
10368 }
10369 }
10370 app.pubProviders.clear();
10371 }
10372
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010373 // Take care of any launching providers waiting for this process.
10374 if (checkAppInLaunchingProvidersLocked(app, false)) {
10375 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010376 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378 // Unregister from connected content providers.
10379 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010380 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010381 while (it.hasNext()) {
10382 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10383 cpr.clients.remove(app);
10384 }
10385 app.conProviders.clear();
10386 }
10387
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010388 // At this point there may be remaining entries in mLaunchingProviders
10389 // where we were the only one waiting, so they are no longer of use.
10390 // Look for these and clean up if found.
10391 // XXX Commented out for now. Trying to figure out a way to reproduce
10392 // the actual situation to identify what is actually going on.
10393 if (false) {
10394 for (int i=0; i<NL; i++) {
10395 ContentProviderRecord cpr = (ContentProviderRecord)
10396 mLaunchingProviders.get(i);
10397 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10398 synchronized (cpr) {
10399 cpr.launchingApp = null;
10400 cpr.notifyAll();
10401 }
10402 }
10403 }
10404 }
10405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010406 skipCurrentReceiverLocked(app);
10407
10408 // Unregister any receivers.
10409 if (app.receivers.size() > 0) {
10410 Iterator<ReceiverList> it = app.receivers.iterator();
10411 while (it.hasNext()) {
10412 removeReceiverLocked(it.next());
10413 }
10414 app.receivers.clear();
10415 }
10416
Christopher Tate181fafa2009-05-14 11:12:14 -070010417 // If the app is undergoing backup, tell the backup manager about it
10418 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010419 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010420 try {
10421 IBackupManager bm = IBackupManager.Stub.asInterface(
10422 ServiceManager.getService(Context.BACKUP_SERVICE));
10423 bm.agentDisconnected(app.info.packageName);
10424 } catch (RemoteException e) {
10425 // can't happen; backup manager is local
10426 }
10427 }
10428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010429 // If the caller is restarting this app, then leave it in its
10430 // current lists and let the caller take care of it.
10431 if (restarting) {
10432 return;
10433 }
10434
10435 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010436 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010437 "Removing non-persistent process during cleanup: " + app);
10438 mProcessNames.remove(app.processName, app.info.uid);
10439 } else if (!app.removed) {
10440 // This app is persistent, so we need to keep its record around.
10441 // If it is not already on the pending app list, add it there
10442 // and start a new process for it.
10443 app.thread = null;
10444 app.forcingToForeground = null;
10445 app.foregroundServices = false;
10446 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10447 mPersistentStartingProcesses.add(app);
10448 restart = true;
10449 }
10450 }
10451 mProcessesOnHold.remove(app);
10452
The Android Open Source Project4df24232009-03-05 14:34:35 -080010453 if (app == mHomeProcess) {
10454 mHomeProcess = null;
10455 }
10456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010457 if (restart) {
10458 // We have components that still need to be running in the
10459 // process, so re-launch it.
10460 mProcessNames.put(app.processName, app.info.uid, app);
10461 startProcessLocked(app, "restart", app.processName);
10462 } else if (app.pid > 0 && app.pid != MY_PID) {
10463 // Goodbye!
10464 synchronized (mPidsSelfLocked) {
10465 mPidsSelfLocked.remove(app.pid);
10466 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10467 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010468 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010469 }
10470 }
10471
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010472 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10473 // Look through the content providers we are waiting to have launched,
10474 // and if any run in this process then either schedule a restart of
10475 // the process or kill the client waiting for it if this process has
10476 // gone bad.
10477 int NL = mLaunchingProviders.size();
10478 boolean restart = false;
10479 for (int i=0; i<NL; i++) {
10480 ContentProviderRecord cpr = (ContentProviderRecord)
10481 mLaunchingProviders.get(i);
10482 if (cpr.launchingApp == app) {
10483 if (!alwaysBad && !app.bad) {
10484 restart = true;
10485 } else {
10486 removeDyingProviderLocked(app, cpr);
10487 NL = mLaunchingProviders.size();
10488 }
10489 }
10490 }
10491 return restart;
10492 }
10493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010494 // =========================================================
10495 // SERVICES
10496 // =========================================================
10497
10498 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10499 ActivityManager.RunningServiceInfo info =
10500 new ActivityManager.RunningServiceInfo();
10501 info.service = r.name;
10502 if (r.app != null) {
10503 info.pid = r.app.pid;
10504 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010505 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010506 info.process = r.processName;
10507 info.foreground = r.isForeground;
10508 info.activeSince = r.createTime;
10509 info.started = r.startRequested;
10510 info.clientCount = r.connections.size();
10511 info.crashCount = r.crashCount;
10512 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010513 if (r.isForeground) {
10514 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10515 }
10516 if (r.startRequested) {
10517 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10518 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010519 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010520 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10521 }
10522 if (r.app != null && r.app.persistent) {
10523 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10524 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010525 for (ConnectionRecord conn : r.connections.values()) {
10526 if (conn.clientLabel != 0) {
10527 info.clientPackage = conn.binding.client.info.packageName;
10528 info.clientLabel = conn.clientLabel;
10529 break;
10530 }
10531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010532 return info;
10533 }
10534
10535 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10536 int flags) {
10537 synchronized (this) {
10538 ArrayList<ActivityManager.RunningServiceInfo> res
10539 = new ArrayList<ActivityManager.RunningServiceInfo>();
10540
10541 if (mServices.size() > 0) {
10542 Iterator<ServiceRecord> it = mServices.values().iterator();
10543 while (it.hasNext() && res.size() < maxNum) {
10544 res.add(makeRunningServiceInfoLocked(it.next()));
10545 }
10546 }
10547
10548 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10549 ServiceRecord r = mRestartingServices.get(i);
10550 ActivityManager.RunningServiceInfo info =
10551 makeRunningServiceInfoLocked(r);
10552 info.restarting = r.nextRestartTime;
10553 res.add(info);
10554 }
10555
10556 return res;
10557 }
10558 }
10559
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010560 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10561 synchronized (this) {
10562 ServiceRecord r = mServices.get(name);
10563 if (r != null) {
10564 for (ConnectionRecord conn : r.connections.values()) {
10565 if (conn.clientIntent != null) {
10566 return conn.clientIntent;
10567 }
10568 }
10569 }
10570 }
10571 return null;
10572 }
10573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010574 private final ServiceRecord findServiceLocked(ComponentName name,
10575 IBinder token) {
10576 ServiceRecord r = mServices.get(name);
10577 return r == token ? r : null;
10578 }
10579
10580 private final class ServiceLookupResult {
10581 final ServiceRecord record;
10582 final String permission;
10583
10584 ServiceLookupResult(ServiceRecord _record, String _permission) {
10585 record = _record;
10586 permission = _permission;
10587 }
10588 };
10589
10590 private ServiceLookupResult findServiceLocked(Intent service,
10591 String resolvedType) {
10592 ServiceRecord r = null;
10593 if (service.getComponent() != null) {
10594 r = mServices.get(service.getComponent());
10595 }
10596 if (r == null) {
10597 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10598 r = mServicesByIntent.get(filter);
10599 }
10600
10601 if (r == null) {
10602 try {
10603 ResolveInfo rInfo =
10604 ActivityThread.getPackageManager().resolveService(
10605 service, resolvedType, 0);
10606 ServiceInfo sInfo =
10607 rInfo != null ? rInfo.serviceInfo : null;
10608 if (sInfo == null) {
10609 return null;
10610 }
10611
10612 ComponentName name = new ComponentName(
10613 sInfo.applicationInfo.packageName, sInfo.name);
10614 r = mServices.get(name);
10615 } catch (RemoteException ex) {
10616 // pm is in same process, this will never happen.
10617 }
10618 }
10619 if (r != null) {
10620 int callingPid = Binder.getCallingPid();
10621 int callingUid = Binder.getCallingUid();
10622 if (checkComponentPermission(r.permission,
10623 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10624 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010625 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010626 + " from pid=" + callingPid
10627 + ", uid=" + callingUid
10628 + " requires " + r.permission);
10629 return new ServiceLookupResult(null, r.permission);
10630 }
10631 return new ServiceLookupResult(r, null);
10632 }
10633 return null;
10634 }
10635
10636 private class ServiceRestarter implements Runnable {
10637 private ServiceRecord mService;
10638
10639 void setService(ServiceRecord service) {
10640 mService = service;
10641 }
10642
10643 public void run() {
10644 synchronized(ActivityManagerService.this) {
10645 performServiceRestartLocked(mService);
10646 }
10647 }
10648 }
10649
10650 private ServiceLookupResult retrieveServiceLocked(Intent service,
10651 String resolvedType, int callingPid, int callingUid) {
10652 ServiceRecord r = null;
10653 if (service.getComponent() != null) {
10654 r = mServices.get(service.getComponent());
10655 }
10656 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10657 r = mServicesByIntent.get(filter);
10658 if (r == null) {
10659 try {
10660 ResolveInfo rInfo =
10661 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010662 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010663 ServiceInfo sInfo =
10664 rInfo != null ? rInfo.serviceInfo : null;
10665 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010666 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 ": not found");
10668 return null;
10669 }
10670
10671 ComponentName name = new ComponentName(
10672 sInfo.applicationInfo.packageName, sInfo.name);
10673 r = mServices.get(name);
10674 if (r == null) {
10675 filter = new Intent.FilterComparison(service.cloneFilter());
10676 ServiceRestarter res = new ServiceRestarter();
10677 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10678 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10679 synchronized (stats) {
10680 ss = stats.getServiceStatsLocked(
10681 sInfo.applicationInfo.uid, sInfo.packageName,
10682 sInfo.name);
10683 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010684 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010685 res.setService(r);
10686 mServices.put(name, r);
10687 mServicesByIntent.put(filter, r);
10688
10689 // Make sure this component isn't in the pending list.
10690 int N = mPendingServices.size();
10691 for (int i=0; i<N; i++) {
10692 ServiceRecord pr = mPendingServices.get(i);
10693 if (pr.name.equals(name)) {
10694 mPendingServices.remove(i);
10695 i--;
10696 N--;
10697 }
10698 }
10699 }
10700 } catch (RemoteException ex) {
10701 // pm is in same process, this will never happen.
10702 }
10703 }
10704 if (r != null) {
10705 if (checkComponentPermission(r.permission,
10706 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10707 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010708 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010709 + " from pid=" + Binder.getCallingPid()
10710 + ", uid=" + Binder.getCallingUid()
10711 + " requires " + r.permission);
10712 return new ServiceLookupResult(null, r.permission);
10713 }
10714 return new ServiceLookupResult(r, null);
10715 }
10716 return null;
10717 }
10718
10719 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10720 long now = SystemClock.uptimeMillis();
10721 if (r.executeNesting == 0 && r.app != null) {
10722 if (r.app.executingServices.size() == 0) {
10723 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10724 msg.obj = r.app;
10725 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10726 }
10727 r.app.executingServices.add(r);
10728 }
10729 r.executeNesting++;
10730 r.executingStart = now;
10731 }
10732
10733 private final void sendServiceArgsLocked(ServiceRecord r,
10734 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010735 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010736 if (N == 0) {
10737 return;
10738 }
10739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010740 int i = 0;
10741 while (i < N) {
10742 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010743 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010744 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010745 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010746 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010747 // If somehow we got a dummy start at the front, then
10748 // just drop it here.
10749 i++;
10750 continue;
10751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010752 bumpServiceExecutingLocked(r);
10753 if (!oomAdjusted) {
10754 oomAdjusted = true;
10755 updateOomAdjLocked(r.app);
10756 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010757 int flags = 0;
10758 if (si.deliveryCount > 0) {
10759 flags |= Service.START_FLAG_RETRY;
10760 }
10761 if (si.doneExecutingCount > 0) {
10762 flags |= Service.START_FLAG_REDELIVERY;
10763 }
10764 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10765 si.deliveredTime = SystemClock.uptimeMillis();
10766 r.deliveredStarts.add(si);
10767 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010768 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010769 } catch (RemoteException e) {
10770 // Remote process gone... we'll let the normal cleanup take
10771 // care of this.
10772 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010773 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010774 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010775 break;
10776 }
10777 }
10778 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010779 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010780 } else {
10781 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010783 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010784 }
10785 }
10786 }
10787
10788 private final boolean requestServiceBindingLocked(ServiceRecord r,
10789 IntentBindRecord i, boolean rebind) {
10790 if (r.app == null || r.app.thread == null) {
10791 // If service is not currently running, can't yet bind.
10792 return false;
10793 }
10794 if ((!i.requested || rebind) && i.apps.size() > 0) {
10795 try {
10796 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010797 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010798 + ": shouldUnbind=" + i.hasBound);
10799 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10800 if (!rebind) {
10801 i.requested = true;
10802 }
10803 i.hasBound = true;
10804 i.doRebind = false;
10805 } catch (RemoteException e) {
10806 return false;
10807 }
10808 }
10809 return true;
10810 }
10811
10812 private final void requestServiceBindingsLocked(ServiceRecord r) {
10813 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10814 while (bindings.hasNext()) {
10815 IntentBindRecord i = bindings.next();
10816 if (!requestServiceBindingLocked(r, i, false)) {
10817 break;
10818 }
10819 }
10820 }
10821
10822 private final void realStartServiceLocked(ServiceRecord r,
10823 ProcessRecord app) throws RemoteException {
10824 if (app.thread == null) {
10825 throw new RemoteException();
10826 }
10827
10828 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010829 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830
10831 app.services.add(r);
10832 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010833 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010834
10835 boolean created = false;
10836 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010837 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010838 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010839 mStringBuilder.setLength(0);
10840 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010841 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010842 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010843 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010844 synchronized (r.stats.getBatteryStats()) {
10845 r.stats.startLaunchedLocked();
10846 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010847 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010848 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010849 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010850 created = true;
10851 } finally {
10852 if (!created) {
10853 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010854 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010855 }
10856 }
10857
10858 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010859
10860 // If the service is in the started state, and there are no
10861 // pending arguments, then fake up one so its onStartCommand() will
10862 // be called.
10863 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10864 r.lastStartId++;
10865 if (r.lastStartId < 1) {
10866 r.lastStartId = 1;
10867 }
10868 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10869 }
10870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010871 sendServiceArgsLocked(r, true);
10872 }
10873
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010874 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10875 boolean allowCancel) {
10876 boolean canceled = false;
10877
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010878 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010879 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010880 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010881
10882 // Any delivered but not yet finished starts should be put back
10883 // on the pending list.
10884 final int N = r.deliveredStarts.size();
10885 if (N > 0) {
10886 for (int i=N-1; i>=0; i--) {
10887 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10888 if (si.intent == null) {
10889 // We'll generate this again if needed.
10890 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10891 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10892 r.pendingStarts.add(0, si);
10893 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10894 dur *= 2;
10895 if (minDuration < dur) minDuration = dur;
10896 if (resetTime < dur) resetTime = dur;
10897 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010898 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010899 + r.name);
10900 canceled = true;
10901 }
10902 }
10903 r.deliveredStarts.clear();
10904 }
10905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 r.totalRestartCount++;
10907 if (r.restartDelay == 0) {
10908 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010909 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010910 } else {
10911 // If it has been a "reasonably long time" since the service
10912 // was started, then reset our restart duration back to
10913 // the beginning, so we don't infinitely increase the duration
10914 // on a service that just occasionally gets killed (which is
10915 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010916 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010918 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010919 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010920 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010921 if (r.restartDelay < minDuration) {
10922 r.restartDelay = minDuration;
10923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010924 }
10925 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010926
10927 r.nextRestartTime = now + r.restartDelay;
10928
10929 // Make sure that we don't end up restarting a bunch of services
10930 // all at the same time.
10931 boolean repeat;
10932 do {
10933 repeat = false;
10934 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10935 ServiceRecord r2 = mRestartingServices.get(i);
10936 if (r2 != r && r.nextRestartTime
10937 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10938 && r.nextRestartTime
10939 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10940 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10941 r.restartDelay = r.nextRestartTime - now;
10942 repeat = true;
10943 break;
10944 }
10945 }
10946 } while (repeat);
10947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 if (!mRestartingServices.contains(r)) {
10949 mRestartingServices.add(r);
10950 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010951
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010952 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010955 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010956 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010957 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010958 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010959 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 r.shortName, r.restartDelay);
10961
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010962 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 }
10964
10965 final void performServiceRestartLocked(ServiceRecord r) {
10966 if (!mRestartingServices.contains(r)) {
10967 return;
10968 }
10969 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10970 }
10971
10972 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10973 if (r.restartDelay == 0) {
10974 return false;
10975 }
10976 r.resetRestartCounter();
10977 mRestartingServices.remove(r);
10978 mHandler.removeCallbacks(r.restarter);
10979 return true;
10980 }
10981
10982 private final boolean bringUpServiceLocked(ServiceRecord r,
10983 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010984 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 //r.dump(" ");
10986
Dianne Hackborn36124872009-10-08 16:22:03 -070010987 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010988 sendServiceArgsLocked(r, false);
10989 return true;
10990 }
10991
10992 if (!whileRestarting && r.restartDelay > 0) {
10993 // If waiting for a restart, then do nothing.
10994 return true;
10995 }
10996
Joe Onorato8a9b2202010-02-26 18:56:32 -080010997 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998 + " " + r.intent);
10999
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011000 // We are now bringing the service up, so no longer in the
11001 // restarting state.
11002 mRestartingServices.remove(r);
11003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011004 final String appName = r.processName;
11005 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11006 if (app != null && app.thread != null) {
11007 try {
11008 realStartServiceLocked(r, app);
11009 return true;
11010 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011011 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011012 }
11013
11014 // If a dead object exception was thrown -- fall through to
11015 // restart the application.
11016 }
11017
Dianne Hackborn36124872009-10-08 16:22:03 -070011018 // Not running -- get it started, and enqueue this service record
11019 // to be executed when the app comes up.
11020 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11021 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011022 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011023 + r.appInfo.packageName + "/"
11024 + r.appInfo.uid + " for service "
11025 + r.intent.getIntent() + ": process is bad");
11026 bringDownServiceLocked(r, true);
11027 return false;
11028 }
11029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011030 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011031 mPendingServices.add(r);
11032 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011034 return true;
11035 }
11036
11037 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011038 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011039 //r.dump(" ");
11040
11041 // Does it still need to run?
11042 if (!force && r.startRequested) {
11043 return;
11044 }
11045 if (r.connections.size() > 0) {
11046 if (!force) {
11047 // XXX should probably keep a count of the number of auto-create
11048 // connections directly in the service.
11049 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11050 while (it.hasNext()) {
11051 ConnectionRecord cr = it.next();
11052 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11053 return;
11054 }
11055 }
11056 }
11057
11058 // Report to all of the connections that the service is no longer
11059 // available.
11060 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11061 while (it.hasNext()) {
11062 ConnectionRecord c = it.next();
11063 try {
11064 // todo: shouldn't be a synchronous call!
11065 c.conn.connected(r.name, null);
11066 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011067 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011068 " to connection " + c.conn.asBinder() +
11069 " (in " + c.binding.client.processName + ")", e);
11070 }
11071 }
11072 }
11073
11074 // Tell the service that it has been unbound.
11075 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11076 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11077 while (it.hasNext()) {
11078 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011079 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080 + ": hasBound=" + ibr.hasBound);
11081 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11082 try {
11083 bumpServiceExecutingLocked(r);
11084 updateOomAdjLocked(r.app);
11085 ibr.hasBound = false;
11086 r.app.thread.scheduleUnbindService(r,
11087 ibr.intent.getIntent());
11088 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011089 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011090 + r.shortName, e);
11091 serviceDoneExecutingLocked(r, true);
11092 }
11093 }
11094 }
11095 }
11096
Joe Onorato8a9b2202010-02-26 18:56:32 -080011097 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011098 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011099 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011100 System.identityHashCode(r), r.shortName,
11101 (r.app != null) ? r.app.pid : -1);
11102
11103 mServices.remove(r.name);
11104 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011105 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 r.totalRestartCount = 0;
11107 unscheduleServiceRestartLocked(r);
11108
11109 // Also make sure it is not on the pending list.
11110 int N = mPendingServices.size();
11111 for (int i=0; i<N; i++) {
11112 if (mPendingServices.get(i) == r) {
11113 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011114 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011115 TAG, "Removed pending service: " + r.shortName);
11116 i--;
11117 N--;
11118 }
11119 }
11120
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011121 r.cancelNotification();
11122 r.isForeground = false;
11123 r.foregroundId = 0;
11124 r.foregroundNoti = null;
11125
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011126 // Clear start entries.
11127 r.deliveredStarts.clear();
11128 r.pendingStarts.clear();
11129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011130 if (r.app != null) {
11131 synchronized (r.stats.getBatteryStats()) {
11132 r.stats.stopLaunchedLocked();
11133 }
11134 r.app.services.remove(r);
11135 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011136 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011137 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011138 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011139 bumpServiceExecutingLocked(r);
11140 mStoppingServices.add(r);
11141 updateOomAdjLocked(r.app);
11142 r.app.thread.scheduleStopService(r);
11143 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011144 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 + r.shortName, e);
11146 serviceDoneExecutingLocked(r, true);
11147 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011148 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011150 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 TAG, "Removed service that has no process: " + r.shortName);
11152 }
11153 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011154 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011155 TAG, "Removed service that is not running: " + r.shortName);
11156 }
11157 }
11158
11159 ComponentName startServiceLocked(IApplicationThread caller,
11160 Intent service, String resolvedType,
11161 int callingPid, int callingUid) {
11162 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011163 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 + " type=" + resolvedType + " args=" + service.getExtras());
11165
11166 if (caller != null) {
11167 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11168 if (callerApp == null) {
11169 throw new SecurityException(
11170 "Unable to find app for caller " + caller
11171 + " (pid=" + Binder.getCallingPid()
11172 + ") when starting service " + service);
11173 }
11174 }
11175
11176 ServiceLookupResult res =
11177 retrieveServiceLocked(service, resolvedType,
11178 callingPid, callingUid);
11179 if (res == null) {
11180 return null;
11181 }
11182 if (res.record == null) {
11183 return new ComponentName("!", res.permission != null
11184 ? res.permission : "private to package");
11185 }
11186 ServiceRecord r = res.record;
11187 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011188 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189 + r.shortName);
11190 }
11191 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011192 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011193 r.lastStartId++;
11194 if (r.lastStartId < 1) {
11195 r.lastStartId = 1;
11196 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011197 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 r.lastActivity = SystemClock.uptimeMillis();
11199 synchronized (r.stats.getBatteryStats()) {
11200 r.stats.startRunningLocked();
11201 }
11202 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11203 return new ComponentName("!", "Service process is bad");
11204 }
11205 return r.name;
11206 }
11207 }
11208
11209 public ComponentName startService(IApplicationThread caller, Intent service,
11210 String resolvedType) {
11211 // Refuse possible leaked file descriptors
11212 if (service != null && service.hasFileDescriptors() == true) {
11213 throw new IllegalArgumentException("File descriptors passed in Intent");
11214 }
11215
11216 synchronized(this) {
11217 final int callingPid = Binder.getCallingPid();
11218 final int callingUid = Binder.getCallingUid();
11219 final long origId = Binder.clearCallingIdentity();
11220 ComponentName res = startServiceLocked(caller, service,
11221 resolvedType, callingPid, callingUid);
11222 Binder.restoreCallingIdentity(origId);
11223 return res;
11224 }
11225 }
11226
11227 ComponentName startServiceInPackage(int uid,
11228 Intent service, String resolvedType) {
11229 synchronized(this) {
11230 final long origId = Binder.clearCallingIdentity();
11231 ComponentName res = startServiceLocked(null, service,
11232 resolvedType, -1, uid);
11233 Binder.restoreCallingIdentity(origId);
11234 return res;
11235 }
11236 }
11237
11238 public int stopService(IApplicationThread caller, Intent service,
11239 String resolvedType) {
11240 // Refuse possible leaked file descriptors
11241 if (service != null && service.hasFileDescriptors() == true) {
11242 throw new IllegalArgumentException("File descriptors passed in Intent");
11243 }
11244
11245 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011246 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011247 + " type=" + resolvedType);
11248
11249 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11250 if (caller != null && callerApp == null) {
11251 throw new SecurityException(
11252 "Unable to find app for caller " + caller
11253 + " (pid=" + Binder.getCallingPid()
11254 + ") when stopping service " + service);
11255 }
11256
11257 // If this service is active, make sure it is stopped.
11258 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11259 if (r != null) {
11260 if (r.record != null) {
11261 synchronized (r.record.stats.getBatteryStats()) {
11262 r.record.stats.stopRunningLocked();
11263 }
11264 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011265 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 final long origId = Binder.clearCallingIdentity();
11267 bringDownServiceLocked(r.record, false);
11268 Binder.restoreCallingIdentity(origId);
11269 return 1;
11270 }
11271 return -1;
11272 }
11273 }
11274
11275 return 0;
11276 }
11277
11278 public IBinder peekService(Intent service, String resolvedType) {
11279 // Refuse possible leaked file descriptors
11280 if (service != null && service.hasFileDescriptors() == true) {
11281 throw new IllegalArgumentException("File descriptors passed in Intent");
11282 }
11283
11284 IBinder ret = null;
11285
11286 synchronized(this) {
11287 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11288
11289 if (r != null) {
11290 // r.record is null if findServiceLocked() failed the caller permission check
11291 if (r.record == null) {
11292 throw new SecurityException(
11293 "Permission Denial: Accessing service " + r.record.name
11294 + " from pid=" + Binder.getCallingPid()
11295 + ", uid=" + Binder.getCallingUid()
11296 + " requires " + r.permission);
11297 }
11298 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11299 if (ib != null) {
11300 ret = ib.binder;
11301 }
11302 }
11303 }
11304
11305 return ret;
11306 }
11307
11308 public boolean stopServiceToken(ComponentName className, IBinder token,
11309 int startId) {
11310 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011311 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 + " " + token + " startId=" + startId);
11313 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011314 if (r != null) {
11315 if (startId >= 0) {
11316 // Asked to only stop if done with all work. Note that
11317 // to avoid leaks, we will take this as dropping all
11318 // start items up to and including this one.
11319 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11320 if (si != null) {
11321 while (r.deliveredStarts.size() > 0) {
11322 if (r.deliveredStarts.remove(0) == si) {
11323 break;
11324 }
11325 }
11326 }
11327
11328 if (r.lastStartId != startId) {
11329 return false;
11330 }
11331
11332 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011333 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011334 + " is last, but have " + r.deliveredStarts.size()
11335 + " remaining args");
11336 }
11337 }
11338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 synchronized (r.stats.getBatteryStats()) {
11340 r.stats.stopRunningLocked();
11341 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011342 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011343 }
11344 final long origId = Binder.clearCallingIdentity();
11345 bringDownServiceLocked(r, false);
11346 Binder.restoreCallingIdentity(origId);
11347 return true;
11348 }
11349 }
11350 return false;
11351 }
11352
11353 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011354 int id, Notification notification, boolean removeNotification) {
11355 final long origId = Binder.clearCallingIdentity();
11356 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 synchronized(this) {
11358 ServiceRecord r = findServiceLocked(className, token);
11359 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011360 if (id != 0) {
11361 if (notification == null) {
11362 throw new IllegalArgumentException("null notification");
11363 }
11364 if (r.foregroundId != id) {
11365 r.cancelNotification();
11366 r.foregroundId = id;
11367 }
11368 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11369 r.foregroundNoti = notification;
11370 r.isForeground = true;
11371 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011372 if (r.app != null) {
11373 updateServiceForegroundLocked(r.app, true);
11374 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011375 } else {
11376 if (r.isForeground) {
11377 r.isForeground = false;
11378 if (r.app != null) {
11379 updateServiceForegroundLocked(r.app, true);
11380 }
11381 }
11382 if (removeNotification) {
11383 r.cancelNotification();
11384 r.foregroundId = 0;
11385 r.foregroundNoti = null;
11386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387 }
11388 }
11389 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011390 } finally {
11391 Binder.restoreCallingIdentity(origId);
11392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011393 }
11394
11395 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11396 boolean anyForeground = false;
11397 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11398 if (sr.isForeground) {
11399 anyForeground = true;
11400 break;
11401 }
11402 }
11403 if (anyForeground != proc.foregroundServices) {
11404 proc.foregroundServices = anyForeground;
11405 if (oomAdj) {
11406 updateOomAdjLocked();
11407 }
11408 }
11409 }
11410
11411 public int bindService(IApplicationThread caller, IBinder token,
11412 Intent service, String resolvedType,
11413 IServiceConnection connection, int flags) {
11414 // Refuse possible leaked file descriptors
11415 if (service != null && service.hasFileDescriptors() == true) {
11416 throw new IllegalArgumentException("File descriptors passed in Intent");
11417 }
11418
11419 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011420 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011421 + " type=" + resolvedType + " conn=" + connection.asBinder()
11422 + " flags=0x" + Integer.toHexString(flags));
11423 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11424 if (callerApp == null) {
11425 throw new SecurityException(
11426 "Unable to find app for caller " + caller
11427 + " (pid=" + Binder.getCallingPid()
11428 + ") when binding service " + service);
11429 }
11430
11431 HistoryRecord activity = null;
11432 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011433 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011435 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 return 0;
11437 }
11438 activity = (HistoryRecord)mHistory.get(aindex);
11439 }
11440
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011441 int clientLabel = 0;
11442 PendingIntent clientIntent = null;
11443
11444 if (callerApp.info.uid == Process.SYSTEM_UID) {
11445 // Hacky kind of thing -- allow system stuff to tell us
11446 // what they are, so we can report this elsewhere for
11447 // others to know why certain services are running.
11448 try {
11449 clientIntent = (PendingIntent)service.getParcelableExtra(
11450 Intent.EXTRA_CLIENT_INTENT);
11451 } catch (RuntimeException e) {
11452 }
11453 if (clientIntent != null) {
11454 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11455 if (clientLabel != 0) {
11456 // There are no useful extras in the intent, trash them.
11457 // System code calling with this stuff just needs to know
11458 // this will happen.
11459 service = service.cloneFilter();
11460 }
11461 }
11462 }
11463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011464 ServiceLookupResult res =
11465 retrieveServiceLocked(service, resolvedType,
11466 Binder.getCallingPid(), Binder.getCallingUid());
11467 if (res == null) {
11468 return 0;
11469 }
11470 if (res.record == null) {
11471 return -1;
11472 }
11473 ServiceRecord s = res.record;
11474
11475 final long origId = Binder.clearCallingIdentity();
11476
11477 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011478 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011479 + s.shortName);
11480 }
11481
11482 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11483 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011484 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485
11486 IBinder binder = connection.asBinder();
11487 s.connections.put(binder, c);
11488 b.connections.add(c);
11489 if (activity != null) {
11490 if (activity.connections == null) {
11491 activity.connections = new HashSet<ConnectionRecord>();
11492 }
11493 activity.connections.add(c);
11494 }
11495 b.client.connections.add(c);
11496 mServiceConnections.put(binder, c);
11497
11498 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11499 s.lastActivity = SystemClock.uptimeMillis();
11500 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11501 return 0;
11502 }
11503 }
11504
11505 if (s.app != null) {
11506 // This could have made the service more important.
11507 updateOomAdjLocked(s.app);
11508 }
11509
Joe Onorato8a9b2202010-02-26 18:56:32 -080011510 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 + ": received=" + b.intent.received
11512 + " apps=" + b.intent.apps.size()
11513 + " doRebind=" + b.intent.doRebind);
11514
11515 if (s.app != null && b.intent.received) {
11516 // Service is already running, so we can immediately
11517 // publish the connection.
11518 try {
11519 c.conn.connected(s.name, b.intent.binder);
11520 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011521 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011522 + " to connection " + c.conn.asBinder()
11523 + " (in " + c.binding.client.processName + ")", e);
11524 }
11525
11526 // If this is the first app connected back to this binding,
11527 // and the service had previously asked to be told when
11528 // rebound, then do so.
11529 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11530 requestServiceBindingLocked(s, b.intent, true);
11531 }
11532 } else if (!b.intent.requested) {
11533 requestServiceBindingLocked(s, b.intent, false);
11534 }
11535
11536 Binder.restoreCallingIdentity(origId);
11537 }
11538
11539 return 1;
11540 }
11541
11542 private void removeConnectionLocked(
11543 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11544 IBinder binder = c.conn.asBinder();
11545 AppBindRecord b = c.binding;
11546 ServiceRecord s = b.service;
11547 s.connections.remove(binder);
11548 b.connections.remove(c);
11549 if (c.activity != null && c.activity != skipAct) {
11550 if (c.activity.connections != null) {
11551 c.activity.connections.remove(c);
11552 }
11553 }
11554 if (b.client != skipApp) {
11555 b.client.connections.remove(c);
11556 }
11557 mServiceConnections.remove(binder);
11558
11559 if (b.connections.size() == 0) {
11560 b.intent.apps.remove(b.client);
11561 }
11562
Joe Onorato8a9b2202010-02-26 18:56:32 -080011563 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011564 + ": shouldUnbind=" + b.intent.hasBound);
11565 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11566 && b.intent.hasBound) {
11567 try {
11568 bumpServiceExecutingLocked(s);
11569 updateOomAdjLocked(s.app);
11570 b.intent.hasBound = false;
11571 // Assume the client doesn't want to know about a rebind;
11572 // we will deal with that later if it asks for one.
11573 b.intent.doRebind = false;
11574 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11575 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011576 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011577 serviceDoneExecutingLocked(s, true);
11578 }
11579 }
11580
11581 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11582 bringDownServiceLocked(s, false);
11583 }
11584 }
11585
11586 public boolean unbindService(IServiceConnection connection) {
11587 synchronized (this) {
11588 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011589 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011590 ConnectionRecord r = mServiceConnections.get(binder);
11591 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011592 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011593 + connection.asBinder());
11594 return false;
11595 }
11596
11597 final long origId = Binder.clearCallingIdentity();
11598
11599 removeConnectionLocked(r, null, null);
11600
11601 if (r.binding.service.app != null) {
11602 // This could have made the service less important.
11603 updateOomAdjLocked(r.binding.service.app);
11604 }
11605
11606 Binder.restoreCallingIdentity(origId);
11607 }
11608
11609 return true;
11610 }
11611
11612 public void publishService(IBinder token, Intent intent, IBinder service) {
11613 // Refuse possible leaked file descriptors
11614 if (intent != null && intent.hasFileDescriptors() == true) {
11615 throw new IllegalArgumentException("File descriptors passed in Intent");
11616 }
11617
11618 synchronized(this) {
11619 if (!(token instanceof ServiceRecord)) {
11620 throw new IllegalArgumentException("Invalid service token");
11621 }
11622 ServiceRecord r = (ServiceRecord)token;
11623
11624 final long origId = Binder.clearCallingIdentity();
11625
Joe Onorato8a9b2202010-02-26 18:56:32 -080011626 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011627 + " " + intent + ": " + service);
11628 if (r != null) {
11629 Intent.FilterComparison filter
11630 = new Intent.FilterComparison(intent);
11631 IntentBindRecord b = r.bindings.get(filter);
11632 if (b != null && !b.received) {
11633 b.binder = service;
11634 b.requested = true;
11635 b.received = true;
11636 if (r.connections.size() > 0) {
11637 Iterator<ConnectionRecord> it
11638 = r.connections.values().iterator();
11639 while (it.hasNext()) {
11640 ConnectionRecord c = it.next();
11641 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011642 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011644 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011645 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011646 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011647 TAG, "Published intent: " + intent);
11648 continue;
11649 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011650 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011651 try {
11652 c.conn.connected(r.name, service);
11653 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011654 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011655 " to connection " + c.conn.asBinder() +
11656 " (in " + c.binding.client.processName + ")", e);
11657 }
11658 }
11659 }
11660 }
11661
11662 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11663
11664 Binder.restoreCallingIdentity(origId);
11665 }
11666 }
11667 }
11668
11669 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11670 // Refuse possible leaked file descriptors
11671 if (intent != null && intent.hasFileDescriptors() == true) {
11672 throw new IllegalArgumentException("File descriptors passed in Intent");
11673 }
11674
11675 synchronized(this) {
11676 if (!(token instanceof ServiceRecord)) {
11677 throw new IllegalArgumentException("Invalid service token");
11678 }
11679 ServiceRecord r = (ServiceRecord)token;
11680
11681 final long origId = Binder.clearCallingIdentity();
11682
11683 if (r != null) {
11684 Intent.FilterComparison filter
11685 = new Intent.FilterComparison(intent);
11686 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011687 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011688 + " at " + b + ": apps="
11689 + (b != null ? b.apps.size() : 0));
11690 if (b != null) {
11691 if (b.apps.size() > 0) {
11692 // Applications have already bound since the last
11693 // unbind, so just rebind right here.
11694 requestServiceBindingLocked(r, b, true);
11695 } else {
11696 // Note to tell the service the next time there is
11697 // a new client.
11698 b.doRebind = true;
11699 }
11700 }
11701
11702 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11703
11704 Binder.restoreCallingIdentity(origId);
11705 }
11706 }
11707 }
11708
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011709 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011710 synchronized(this) {
11711 if (!(token instanceof ServiceRecord)) {
11712 throw new IllegalArgumentException("Invalid service token");
11713 }
11714 ServiceRecord r = (ServiceRecord)token;
11715 boolean inStopping = mStoppingServices.contains(token);
11716 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011717 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011718 + ": nesting=" + r.executeNesting
11719 + ", inStopping=" + inStopping);
11720 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011721 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011722 + " with incorrect token: given " + token
11723 + ", expected " + r);
11724 return;
11725 }
11726
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011727 if (type == 1) {
11728 // This is a call from a service start... take care of
11729 // book-keeping.
11730 r.callStart = true;
11731 switch (res) {
11732 case Service.START_STICKY_COMPATIBILITY:
11733 case Service.START_STICKY: {
11734 // We are done with the associated start arguments.
11735 r.findDeliveredStart(startId, true);
11736 // Don't stop if killed.
11737 r.stopIfKilled = false;
11738 break;
11739 }
11740 case Service.START_NOT_STICKY: {
11741 // We are done with the associated start arguments.
11742 r.findDeliveredStart(startId, true);
11743 if (r.lastStartId == startId) {
11744 // There is no more work, and this service
11745 // doesn't want to hang around if killed.
11746 r.stopIfKilled = true;
11747 }
11748 break;
11749 }
11750 case Service.START_REDELIVER_INTENT: {
11751 // We'll keep this item until they explicitly
11752 // call stop for it, but keep track of the fact
11753 // that it was delivered.
11754 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11755 if (si != null) {
11756 si.deliveryCount = 0;
11757 si.doneExecutingCount++;
11758 // Don't stop if killed.
11759 r.stopIfKilled = true;
11760 }
11761 break;
11762 }
11763 default:
11764 throw new IllegalArgumentException(
11765 "Unknown service start result: " + res);
11766 }
11767 if (res == Service.START_STICKY_COMPATIBILITY) {
11768 r.callStart = false;
11769 }
11770 }
11771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011772 final long origId = Binder.clearCallingIdentity();
11773 serviceDoneExecutingLocked(r, inStopping);
11774 Binder.restoreCallingIdentity(origId);
11775 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011776 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011777 + " with token " + token);
11778 }
11779 }
11780 }
11781
11782 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11783 r.executeNesting--;
11784 if (r.executeNesting <= 0 && r.app != null) {
11785 r.app.executingServices.remove(r);
11786 if (r.app.executingServices.size() == 0) {
11787 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11788 }
11789 if (inStopping) {
11790 mStoppingServices.remove(r);
11791 }
11792 updateOomAdjLocked(r.app);
11793 }
11794 }
11795
11796 void serviceTimeout(ProcessRecord proc) {
11797 synchronized(this) {
11798 if (proc.executingServices.size() == 0 || proc.thread == null) {
11799 return;
11800 }
11801 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11802 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11803 ServiceRecord timeout = null;
11804 long nextTime = 0;
11805 while (it.hasNext()) {
11806 ServiceRecord sr = it.next();
11807 if (sr.executingStart < maxTime) {
11808 timeout = sr;
11809 break;
11810 }
11811 if (sr.executingStart > nextTime) {
11812 nextTime = sr.executingStart;
11813 }
11814 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011815 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011816 Slog.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011817 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011818 } else {
11819 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11820 msg.obj = proc;
11821 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11822 }
11823 }
11824 }
11825
11826 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011827 // BACKUP AND RESTORE
11828 // =========================================================
11829
11830 // Cause the target app to be launched if necessary and its backup agent
11831 // instantiated. The backup agent will invoke backupAgentCreated() on the
11832 // activity manager to announce its creation.
11833 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011834 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011835 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11836
11837 synchronized(this) {
11838 // !!! TODO: currently no check here that we're already bound
11839 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11840 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11841 synchronized (stats) {
11842 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11843 }
11844
11845 BackupRecord r = new BackupRecord(ss, app, backupMode);
11846 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11847 // startProcessLocked() returns existing proc's record if it's already running
11848 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011849 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011850 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011851 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011852 return false;
11853 }
11854
11855 r.app = proc;
11856 mBackupTarget = r;
11857 mBackupAppName = app.packageName;
11858
Christopher Tate6fa95972009-06-05 18:43:55 -070011859 // Try not to kill the process during backup
11860 updateOomAdjLocked(proc);
11861
Christopher Tate181fafa2009-05-14 11:12:14 -070011862 // If the process is already attached, schedule the creation of the backup agent now.
11863 // If it is not yet live, this will be done when it attaches to the framework.
11864 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011865 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011866 try {
11867 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11868 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011869 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011870 }
11871 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011872 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011873 }
11874 // Invariants: at this point, the target app process exists and the application
11875 // is either already running or in the process of coming up. mBackupTarget and
11876 // mBackupAppName describe the app, so that when it binds back to the AM we
11877 // know that it's scheduled for a backup-agent operation.
11878 }
11879
11880 return true;
11881 }
11882
11883 // A backup agent has just come up
11884 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011885 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011886 + " = " + agent);
11887
11888 synchronized(this) {
11889 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011890 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011891 return;
11892 }
11893
Christopher Tate043dadc2009-06-02 16:11:00 -070011894 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011895 try {
11896 IBackupManager bm = IBackupManager.Stub.asInterface(
11897 ServiceManager.getService(Context.BACKUP_SERVICE));
11898 bm.agentConnected(agentPackageName, agent);
11899 } catch (RemoteException e) {
11900 // can't happen; the backup manager service is local
11901 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011902 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070011903 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011904 } finally {
11905 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011906 }
11907 }
11908 }
11909
11910 // done with this agent
11911 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011912 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011913 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011914 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011915 return;
11916 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011917
11918 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011919 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011920 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011921 return;
11922 }
11923
Christopher Tate181fafa2009-05-14 11:12:14 -070011924 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011925 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011926 return;
11927 }
11928
Christopher Tate6fa95972009-06-05 18:43:55 -070011929 ProcessRecord proc = mBackupTarget.app;
11930 mBackupTarget = null;
11931 mBackupAppName = null;
11932
11933 // Not backing this app up any more; reset its OOM adjustment
11934 updateOomAdjLocked(proc);
11935
Christopher Tatec7b31e32009-06-10 15:49:30 -070011936 // If the app crashed during backup, 'thread' will be null here
11937 if (proc.thread != null) {
11938 try {
11939 proc.thread.scheduleDestroyBackupAgent(appInfo);
11940 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011941 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070011942 e.printStackTrace();
11943 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011944 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011945 }
11946 }
11947 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011948 // BROADCASTS
11949 // =========================================================
11950
Josh Bartel7f208742010-02-25 11:01:44 -060011951 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 List cur) {
11953 final ContentResolver resolver = mContext.getContentResolver();
11954 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11955 if (list == null) {
11956 return cur;
11957 }
11958 int N = list.size();
11959 for (int i=0; i<N; i++) {
11960 Intent intent = list.get(i);
11961 if (filter.match(resolver, intent, true, TAG) >= 0) {
11962 if (cur == null) {
11963 cur = new ArrayList<Intent>();
11964 }
11965 cur.add(intent);
11966 }
11967 }
11968 return cur;
11969 }
11970
11971 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011972 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011973 + mBroadcastsScheduled);
11974
11975 if (mBroadcastsScheduled) {
11976 return;
11977 }
11978 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11979 mBroadcastsScheduled = true;
11980 }
11981
11982 public Intent registerReceiver(IApplicationThread caller,
11983 IIntentReceiver receiver, IntentFilter filter, String permission) {
11984 synchronized(this) {
11985 ProcessRecord callerApp = null;
11986 if (caller != null) {
11987 callerApp = getRecordForAppLocked(caller);
11988 if (callerApp == null) {
11989 throw new SecurityException(
11990 "Unable to find app for caller " + caller
11991 + " (pid=" + Binder.getCallingPid()
11992 + ") when registering receiver " + receiver);
11993 }
11994 }
11995
11996 List allSticky = null;
11997
11998 // Look for any matching sticky broadcasts...
11999 Iterator actions = filter.actionsIterator();
12000 if (actions != null) {
12001 while (actions.hasNext()) {
12002 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012003 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012004 }
12005 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012006 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012007 }
12008
12009 // The first sticky in the list is returned directly back to
12010 // the client.
12011 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12012
Joe Onorato8a9b2202010-02-26 18:56:32 -080012013 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012014 + ": " + sticky);
12015
12016 if (receiver == null) {
12017 return sticky;
12018 }
12019
12020 ReceiverList rl
12021 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12022 if (rl == null) {
12023 rl = new ReceiverList(this, callerApp,
12024 Binder.getCallingPid(),
12025 Binder.getCallingUid(), receiver);
12026 if (rl.app != null) {
12027 rl.app.receivers.add(rl);
12028 } else {
12029 try {
12030 receiver.asBinder().linkToDeath(rl, 0);
12031 } catch (RemoteException e) {
12032 return sticky;
12033 }
12034 rl.linkedToDeath = true;
12035 }
12036 mRegisteredReceivers.put(receiver.asBinder(), rl);
12037 }
12038 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12039 rl.add(bf);
12040 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012041 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012042 }
12043 mReceiverResolver.addFilter(bf);
12044
12045 // Enqueue broadcasts for all existing stickies that match
12046 // this filter.
12047 if (allSticky != null) {
12048 ArrayList receivers = new ArrayList();
12049 receivers.add(bf);
12050
12051 int N = allSticky.size();
12052 for (int i=0; i<N; i++) {
12053 Intent intent = (Intent)allSticky.get(i);
12054 BroadcastRecord r = new BroadcastRecord(intent, null,
12055 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012056 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012057 if (mParallelBroadcasts.size() == 0) {
12058 scheduleBroadcastsLocked();
12059 }
12060 mParallelBroadcasts.add(r);
12061 }
12062 }
12063
12064 return sticky;
12065 }
12066 }
12067
12068 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012069 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012070
12071 boolean doNext = false;
12072
12073 synchronized(this) {
12074 ReceiverList rl
12075 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12076 if (rl != null) {
12077 if (rl.curBroadcast != null) {
12078 BroadcastRecord r = rl.curBroadcast;
12079 doNext = finishReceiverLocked(
12080 receiver.asBinder(), r.resultCode, r.resultData,
12081 r.resultExtras, r.resultAbort, true);
12082 }
12083
12084 if (rl.app != null) {
12085 rl.app.receivers.remove(rl);
12086 }
12087 removeReceiverLocked(rl);
12088 if (rl.linkedToDeath) {
12089 rl.linkedToDeath = false;
12090 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12091 }
12092 }
12093 }
12094
12095 if (!doNext) {
12096 return;
12097 }
12098
12099 final long origId = Binder.clearCallingIdentity();
12100 processNextBroadcast(false);
12101 trimApplications();
12102 Binder.restoreCallingIdentity(origId);
12103 }
12104
12105 void removeReceiverLocked(ReceiverList rl) {
12106 mRegisteredReceivers.remove(rl.receiver.asBinder());
12107 int N = rl.size();
12108 for (int i=0; i<N; i++) {
12109 mReceiverResolver.removeFilter(rl.get(i));
12110 }
12111 }
12112
12113 private final int broadcastIntentLocked(ProcessRecord callerApp,
12114 String callerPackage, Intent intent, String resolvedType,
12115 IIntentReceiver resultTo, int resultCode, String resultData,
12116 Bundle map, String requiredPermission,
12117 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12118 intent = new Intent(intent);
12119
Joe Onorato8a9b2202010-02-26 18:56:32 -080012120 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012121 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12122 + " ordered=" + ordered);
12123 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012124 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012125 }
12126
12127 // Handle special intents: if this broadcast is from the package
12128 // manager about a package being removed, we need to remove all of
12129 // its activities from the history stack.
12130 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12131 intent.getAction());
12132 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12133 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012134 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012135 || uidRemoved) {
12136 if (checkComponentPermission(
12137 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12138 callingPid, callingUid, -1)
12139 == PackageManager.PERMISSION_GRANTED) {
12140 if (uidRemoved) {
12141 final Bundle intentExtras = intent.getExtras();
12142 final int uid = intentExtras != null
12143 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12144 if (uid >= 0) {
12145 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12146 synchronized (bs) {
12147 bs.removeUidStatsLocked(uid);
12148 }
12149 }
12150 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012151 // If resources are unvailble just force stop all
12152 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012153 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012154 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12155 if (list != null && (list.length > 0)) {
12156 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012157 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012158 }
12159 }
12160 } else {
12161 Uri data = intent.getData();
12162 String ssp;
12163 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12164 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12165 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012166 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012168 }
12169 }
12170 }
12171 } else {
12172 String msg = "Permission Denial: " + intent.getAction()
12173 + " broadcast from " + callerPackage + " (pid=" + callingPid
12174 + ", uid=" + callingUid + ")"
12175 + " requires "
12176 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012177 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012178 throw new SecurityException(msg);
12179 }
12180 }
12181
12182 /*
12183 * If this is the time zone changed action, queue up a message that will reset the timezone
12184 * of all currently running processes. This message will get queued up before the broadcast
12185 * happens.
12186 */
12187 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12188 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12189 }
12190
Dianne Hackborn854060af2009-07-09 18:14:31 -070012191 /*
12192 * Prevent non-system code (defined here to be non-persistent
12193 * processes) from sending protected broadcasts.
12194 */
12195 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12196 || callingUid == Process.SHELL_UID || callingUid == 0) {
12197 // Always okay.
12198 } else if (callerApp == null || !callerApp.persistent) {
12199 try {
12200 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12201 intent.getAction())) {
12202 String msg = "Permission Denial: not allowed to send broadcast "
12203 + intent.getAction() + " from pid="
12204 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012205 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012206 throw new SecurityException(msg);
12207 }
12208 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012209 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012210 return BROADCAST_SUCCESS;
12211 }
12212 }
12213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012214 // Add to the sticky list if requested.
12215 if (sticky) {
12216 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12217 callingPid, callingUid)
12218 != PackageManager.PERMISSION_GRANTED) {
12219 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12220 + callingPid + ", uid=" + callingUid
12221 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012222 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012223 throw new SecurityException(msg);
12224 }
12225 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012226 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012227 + " and enforce permission " + requiredPermission);
12228 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12229 }
12230 if (intent.getComponent() != null) {
12231 throw new SecurityException(
12232 "Sticky broadcasts can't target a specific component");
12233 }
12234 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12235 if (list == null) {
12236 list = new ArrayList<Intent>();
12237 mStickyBroadcasts.put(intent.getAction(), list);
12238 }
12239 int N = list.size();
12240 int i;
12241 for (i=0; i<N; i++) {
12242 if (intent.filterEquals(list.get(i))) {
12243 // This sticky already exists, replace it.
12244 list.set(i, new Intent(intent));
12245 break;
12246 }
12247 }
12248 if (i >= N) {
12249 list.add(new Intent(intent));
12250 }
12251 }
12252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012253 // Figure out who all will receive this broadcast.
12254 List receivers = null;
12255 List<BroadcastFilter> registeredReceivers = null;
12256 try {
12257 if (intent.getComponent() != null) {
12258 // Broadcast is going to one specific receiver class...
12259 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012260 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012261 if (ai != null) {
12262 receivers = new ArrayList();
12263 ResolveInfo ri = new ResolveInfo();
12264 ri.activityInfo = ai;
12265 receivers.add(ri);
12266 }
12267 } else {
12268 // Need to resolve the intent to interested receivers...
12269 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12270 == 0) {
12271 receivers =
12272 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012273 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012274 }
Mihai Preda074edef2009-05-18 17:13:31 +020012275 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012276 }
12277 } catch (RemoteException ex) {
12278 // pm is in same process, this will never happen.
12279 }
12280
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012281 final boolean replacePending =
12282 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12283
Joe Onorato8a9b2202010-02-26 18:56:32 -080012284 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012285 + " replacePending=" + replacePending);
12286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012287 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12288 if (!ordered && NR > 0) {
12289 // If we are not serializing this broadcast, then send the
12290 // registered receivers separately so they don't wait for the
12291 // components to be launched.
12292 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12293 callerPackage, callingPid, callingUid, requiredPermission,
12294 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012295 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012296 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012297 TAG, "Enqueueing parallel broadcast " + r
12298 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012299 boolean replaced = false;
12300 if (replacePending) {
12301 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12302 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012303 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012304 "***** DROPPING PARALLEL: " + intent);
12305 mParallelBroadcasts.set(i, r);
12306 replaced = true;
12307 break;
12308 }
12309 }
12310 }
12311 if (!replaced) {
12312 mParallelBroadcasts.add(r);
12313 scheduleBroadcastsLocked();
12314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012315 registeredReceivers = null;
12316 NR = 0;
12317 }
12318
12319 // Merge into one list.
12320 int ir = 0;
12321 if (receivers != null) {
12322 // A special case for PACKAGE_ADDED: do not allow the package
12323 // being added to see this broadcast. This prevents them from
12324 // using this as a back door to get run as soon as they are
12325 // installed. Maybe in the future we want to have a special install
12326 // broadcast or such for apps, but we'd like to deliberately make
12327 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012328 String skipPackages[] = null;
12329 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12330 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12331 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12332 Uri data = intent.getData();
12333 if (data != null) {
12334 String pkgName = data.getSchemeSpecificPart();
12335 if (pkgName != null) {
12336 skipPackages = new String[] { pkgName };
12337 }
12338 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012339 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012340 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012341 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012342 if (skipPackages != null && (skipPackages.length > 0)) {
12343 for (String skipPackage : skipPackages) {
12344 if (skipPackage != null) {
12345 int NT = receivers.size();
12346 for (int it=0; it<NT; it++) {
12347 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12348 if (curt.activityInfo.packageName.equals(skipPackage)) {
12349 receivers.remove(it);
12350 it--;
12351 NT--;
12352 }
12353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012354 }
12355 }
12356 }
12357
12358 int NT = receivers != null ? receivers.size() : 0;
12359 int it = 0;
12360 ResolveInfo curt = null;
12361 BroadcastFilter curr = null;
12362 while (it < NT && ir < NR) {
12363 if (curt == null) {
12364 curt = (ResolveInfo)receivers.get(it);
12365 }
12366 if (curr == null) {
12367 curr = registeredReceivers.get(ir);
12368 }
12369 if (curr.getPriority() >= curt.priority) {
12370 // Insert this broadcast record into the final list.
12371 receivers.add(it, curr);
12372 ir++;
12373 curr = null;
12374 it++;
12375 NT++;
12376 } else {
12377 // Skip to the next ResolveInfo in the final list.
12378 it++;
12379 curt = null;
12380 }
12381 }
12382 }
12383 while (ir < NR) {
12384 if (receivers == null) {
12385 receivers = new ArrayList();
12386 }
12387 receivers.add(registeredReceivers.get(ir));
12388 ir++;
12389 }
12390
12391 if ((receivers != null && receivers.size() > 0)
12392 || resultTo != null) {
12393 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12394 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012395 receivers, resultTo, resultCode, resultData, map, ordered,
12396 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012397 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012398 TAG, "Enqueueing ordered broadcast " + r
12399 + ": prev had " + mOrderedBroadcasts.size());
12400 if (DEBUG_BROADCAST) {
12401 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012402 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012404 boolean replaced = false;
12405 if (replacePending) {
12406 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12407 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012408 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012409 "***** DROPPING ORDERED: " + intent);
12410 mOrderedBroadcasts.set(i, r);
12411 replaced = true;
12412 break;
12413 }
12414 }
12415 }
12416 if (!replaced) {
12417 mOrderedBroadcasts.add(r);
12418 scheduleBroadcastsLocked();
12419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012420 }
12421
12422 return BROADCAST_SUCCESS;
12423 }
12424
12425 public final int broadcastIntent(IApplicationThread caller,
12426 Intent intent, String resolvedType, IIntentReceiver resultTo,
12427 int resultCode, String resultData, Bundle map,
12428 String requiredPermission, boolean serialized, boolean sticky) {
12429 // Refuse possible leaked file descriptors
12430 if (intent != null && intent.hasFileDescriptors() == true) {
12431 throw new IllegalArgumentException("File descriptors passed in Intent");
12432 }
12433
12434 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012435 int flags = intent.getFlags();
12436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012437 if (!mSystemReady) {
12438 // if the caller really truly claims to know what they're doing, go
12439 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012440 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12441 intent = new Intent(intent);
12442 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12443 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012444 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012445 + " before boot completion");
12446 throw new IllegalStateException("Cannot broadcast before boot completed");
12447 }
12448 }
12449
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012450 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12451 throw new IllegalArgumentException(
12452 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12453 }
12454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012455 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12456 final int callingPid = Binder.getCallingPid();
12457 final int callingUid = Binder.getCallingUid();
12458 final long origId = Binder.clearCallingIdentity();
12459 int res = broadcastIntentLocked(callerApp,
12460 callerApp != null ? callerApp.info.packageName : null,
12461 intent, resolvedType, resultTo,
12462 resultCode, resultData, map, requiredPermission, serialized,
12463 sticky, callingPid, callingUid);
12464 Binder.restoreCallingIdentity(origId);
12465 return res;
12466 }
12467 }
12468
12469 int broadcastIntentInPackage(String packageName, int uid,
12470 Intent intent, String resolvedType, IIntentReceiver resultTo,
12471 int resultCode, String resultData, Bundle map,
12472 String requiredPermission, boolean serialized, boolean sticky) {
12473 synchronized(this) {
12474 final long origId = Binder.clearCallingIdentity();
12475 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12476 resultTo, resultCode, resultData, map, requiredPermission,
12477 serialized, sticky, -1, uid);
12478 Binder.restoreCallingIdentity(origId);
12479 return res;
12480 }
12481 }
12482
12483 public final void unbroadcastIntent(IApplicationThread caller,
12484 Intent intent) {
12485 // Refuse possible leaked file descriptors
12486 if (intent != null && intent.hasFileDescriptors() == true) {
12487 throw new IllegalArgumentException("File descriptors passed in Intent");
12488 }
12489
12490 synchronized(this) {
12491 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12492 != PackageManager.PERMISSION_GRANTED) {
12493 String msg = "Permission Denial: unbroadcastIntent() from pid="
12494 + Binder.getCallingPid()
12495 + ", uid=" + Binder.getCallingUid()
12496 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012497 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012498 throw new SecurityException(msg);
12499 }
12500 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12501 if (list != null) {
12502 int N = list.size();
12503 int i;
12504 for (i=0; i<N; i++) {
12505 if (intent.filterEquals(list.get(i))) {
12506 list.remove(i);
12507 break;
12508 }
12509 }
12510 }
12511 }
12512 }
12513
12514 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12515 String resultData, Bundle resultExtras, boolean resultAbort,
12516 boolean explicit) {
12517 if (mOrderedBroadcasts.size() == 0) {
12518 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012519 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012520 }
12521 return false;
12522 }
12523 BroadcastRecord r = mOrderedBroadcasts.get(0);
12524 if (r.receiver == null) {
12525 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012526 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012527 }
12528 return false;
12529 }
12530 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012531 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012532 return false;
12533 }
12534 int state = r.state;
12535 r.state = r.IDLE;
12536 if (state == r.IDLE) {
12537 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012538 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012539 }
12540 }
12541 r.receiver = null;
12542 r.intent.setComponent(null);
12543 if (r.curApp != null) {
12544 r.curApp.curReceiver = null;
12545 }
12546 if (r.curFilter != null) {
12547 r.curFilter.receiverList.curBroadcast = null;
12548 }
12549 r.curFilter = null;
12550 r.curApp = null;
12551 r.curComponent = null;
12552 r.curReceiver = null;
12553 mPendingBroadcast = null;
12554
12555 r.resultCode = resultCode;
12556 r.resultData = resultData;
12557 r.resultExtras = resultExtras;
12558 r.resultAbort = resultAbort;
12559
12560 // We will process the next receiver right now if this is finishing
12561 // an app receiver (which is always asynchronous) or after we have
12562 // come back from calling a receiver.
12563 return state == BroadcastRecord.APP_RECEIVE
12564 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12565 }
12566
12567 public void finishReceiver(IBinder who, int resultCode, String resultData,
12568 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012569 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012570
12571 // Refuse possible leaked file descriptors
12572 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12573 throw new IllegalArgumentException("File descriptors passed in Bundle");
12574 }
12575
12576 boolean doNext;
12577
12578 final long origId = Binder.clearCallingIdentity();
12579
12580 synchronized(this) {
12581 doNext = finishReceiverLocked(
12582 who, resultCode, resultData, resultExtras, resultAbort, true);
12583 }
12584
12585 if (doNext) {
12586 processNextBroadcast(false);
12587 }
12588 trimApplications();
12589
12590 Binder.restoreCallingIdentity(origId);
12591 }
12592
12593 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12594 if (r.nextReceiver > 0) {
12595 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12596 if (curReceiver instanceof BroadcastFilter) {
12597 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012598 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012599 System.identityHashCode(r),
12600 r.intent.getAction(),
12601 r.nextReceiver - 1,
12602 System.identityHashCode(bf));
12603 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012604 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012605 System.identityHashCode(r),
12606 r.intent.getAction(),
12607 r.nextReceiver - 1,
12608 ((ResolveInfo)curReceiver).toString());
12609 }
12610 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012611 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012612 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012613 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012614 System.identityHashCode(r),
12615 r.intent.getAction(),
12616 r.nextReceiver,
12617 "NONE");
12618 }
12619 }
12620
12621 private final void broadcastTimeout() {
12622 synchronized (this) {
12623 if (mOrderedBroadcasts.size() == 0) {
12624 return;
12625 }
12626 long now = SystemClock.uptimeMillis();
12627 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012628 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012629 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012630 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012631 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012632 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012633 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012634 return;
12635 }
12636
Joe Onorato8a9b2202010-02-26 18:56:32 -080012637 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012638 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012639 r.anrCount++;
12640
12641 // Current receiver has passed its expiration date.
12642 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012643 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012644 return;
12645 }
12646
12647 ProcessRecord app = null;
12648
12649 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012650 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012651 logBroadcastReceiverDiscard(r);
12652 if (curReceiver instanceof BroadcastFilter) {
12653 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12654 if (bf.receiverList.pid != 0
12655 && bf.receiverList.pid != MY_PID) {
12656 synchronized (this.mPidsSelfLocked) {
12657 app = this.mPidsSelfLocked.get(
12658 bf.receiverList.pid);
12659 }
12660 }
12661 } else {
12662 app = r.curApp;
12663 }
12664
12665 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012666 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012667 }
12668
12669 if (mPendingBroadcast == r) {
12670 mPendingBroadcast = null;
12671 }
12672
12673 // Move on to the next receiver.
12674 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12675 r.resultExtras, r.resultAbort, true);
12676 scheduleBroadcastsLocked();
12677 }
12678 }
12679
12680 private final void processCurBroadcastLocked(BroadcastRecord r,
12681 ProcessRecord app) throws RemoteException {
12682 if (app.thread == null) {
12683 throw new RemoteException();
12684 }
12685 r.receiver = app.thread.asBinder();
12686 r.curApp = app;
12687 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012688 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012689
12690 // Tell the application to launch this receiver.
12691 r.intent.setComponent(r.curComponent);
12692
12693 boolean started = false;
12694 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012695 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012696 "Delivering to component " + r.curComponent
12697 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012698 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012699 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12700 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12701 started = true;
12702 } finally {
12703 if (!started) {
12704 r.receiver = null;
12705 r.curApp = null;
12706 app.curReceiver = null;
12707 }
12708 }
12709
12710 }
12711
12712 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012713 Intent intent, int resultCode, String data, Bundle extras,
12714 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012715 if (app != null && app.thread != null) {
12716 // If we have an app thread, do the call through that so it is
12717 // correctly ordered with other one-way calls.
12718 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012719 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012720 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012721 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012722 }
12723 }
12724
12725 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12726 BroadcastFilter filter, boolean ordered) {
12727 boolean skip = false;
12728 if (filter.requiredPermission != null) {
12729 int perm = checkComponentPermission(filter.requiredPermission,
12730 r.callingPid, r.callingUid, -1);
12731 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012732 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012733 + r.intent.toString()
12734 + " from " + r.callerPackage + " (pid="
12735 + r.callingPid + ", uid=" + r.callingUid + ")"
12736 + " requires " + filter.requiredPermission
12737 + " due to registered receiver " + filter);
12738 skip = true;
12739 }
12740 }
12741 if (r.requiredPermission != null) {
12742 int perm = checkComponentPermission(r.requiredPermission,
12743 filter.receiverList.pid, filter.receiverList.uid, -1);
12744 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012745 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012746 + r.intent.toString()
12747 + " to " + filter.receiverList.app
12748 + " (pid=" + filter.receiverList.pid
12749 + ", uid=" + filter.receiverList.uid + ")"
12750 + " requires " + r.requiredPermission
12751 + " due to sender " + r.callerPackage
12752 + " (uid " + r.callingUid + ")");
12753 skip = true;
12754 }
12755 }
12756
12757 if (!skip) {
12758 // If this is not being sent as an ordered broadcast, then we
12759 // don't want to touch the fields that keep track of the current
12760 // state of ordered broadcasts.
12761 if (ordered) {
12762 r.receiver = filter.receiverList.receiver.asBinder();
12763 r.curFilter = filter;
12764 filter.receiverList.curBroadcast = r;
12765 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012766 if (filter.receiverList.app != null) {
12767 // Bump hosting application to no longer be in background
12768 // scheduling class. Note that we can't do that if there
12769 // isn't an app... but we can only be in that case for
12770 // things that directly call the IActivityManager API, which
12771 // are already core system stuff so don't matter for this.
12772 r.curApp = filter.receiverList.app;
12773 filter.receiverList.app.curReceiver = r;
12774 updateOomAdjLocked();
12775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012776 }
12777 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012778 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012779 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012780 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012781 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012782 }
12783 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12784 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012785 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012786 if (ordered) {
12787 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12788 }
12789 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012790 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012791 if (ordered) {
12792 r.receiver = null;
12793 r.curFilter = null;
12794 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012795 if (filter.receiverList.app != null) {
12796 filter.receiverList.app.curReceiver = null;
12797 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012798 }
12799 }
12800 }
12801 }
12802
Dianne Hackborn12527f92009-11-11 17:39:50 -080012803 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12804 if (r.callingUid < 0) {
12805 // This was from a registerReceiver() call; ignore it.
12806 return;
12807 }
12808 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12809 MAX_BROADCAST_HISTORY-1);
12810 r.finishTime = SystemClock.uptimeMillis();
12811 mBroadcastHistory[0] = r;
12812 }
12813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012814 private final void processNextBroadcast(boolean fromMsg) {
12815 synchronized(this) {
12816 BroadcastRecord r;
12817
Joe Onorato8a9b2202010-02-26 18:56:32 -080012818 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012819 + mParallelBroadcasts.size() + " broadcasts, "
12820 + mOrderedBroadcasts.size() + " serialized broadcasts");
12821
12822 updateCpuStats();
12823
12824 if (fromMsg) {
12825 mBroadcastsScheduled = false;
12826 }
12827
12828 // First, deliver any non-serialized broadcasts right away.
12829 while (mParallelBroadcasts.size() > 0) {
12830 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012831 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012832 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012833 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012834 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012835 for (int i=0; i<N; i++) {
12836 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012837 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012838 "Delivering non-serialized to registered "
12839 + target + ": " + r);
12840 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12841 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012842 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012843 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012844 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012845 }
12846
12847 // Now take care of the next serialized one...
12848
12849 // If we are waiting for a process to come up to handle the next
12850 // broadcast, then do nothing at this point. Just in case, we
12851 // check that the process we're waiting for still exists.
12852 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012853 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012854 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012855 + mPendingBroadcast.curApp);
12856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012857
12858 boolean isDead;
12859 synchronized (mPidsSelfLocked) {
12860 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12861 }
12862 if (!isDead) {
12863 // It's still alive, so keep waiting
12864 return;
12865 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012866 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012867 + " died before responding to broadcast");
12868 mPendingBroadcast = null;
12869 }
12870 }
12871
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012872 boolean looped = false;
12873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012874 do {
12875 if (mOrderedBroadcasts.size() == 0) {
12876 // No more broadcasts pending, so all done!
12877 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012878 if (looped) {
12879 // If we had finished the last ordered broadcast, then
12880 // make sure all processes have correct oom and sched
12881 // adjustments.
12882 updateOomAdjLocked();
12883 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012884 return;
12885 }
12886 r = mOrderedBroadcasts.get(0);
12887 boolean forceReceive = false;
12888
12889 // Ensure that even if something goes awry with the timeout
12890 // detection, we catch "hung" broadcasts here, discard them,
12891 // and continue to make progress.
12892 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12893 long now = SystemClock.uptimeMillis();
12894 if (r.dispatchTime > 0) {
12895 if ((numReceivers > 0) &&
12896 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012897 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012898 + " now=" + now
12899 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012900 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012901 + " intent=" + r.intent
12902 + " numReceivers=" + numReceivers
12903 + " nextReceiver=" + r.nextReceiver
12904 + " state=" + r.state);
12905 broadcastTimeout(); // forcibly finish this broadcast
12906 forceReceive = true;
12907 r.state = BroadcastRecord.IDLE;
12908 }
12909 }
12910
12911 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012912 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012913 "processNextBroadcast() called when not idle (state="
12914 + r.state + ")");
12915 return;
12916 }
12917
12918 if (r.receivers == null || r.nextReceiver >= numReceivers
12919 || r.resultAbort || forceReceive) {
12920 // No more receivers for this broadcast! Send the final
12921 // result if requested...
12922 if (r.resultTo != null) {
12923 try {
12924 if (DEBUG_BROADCAST) {
12925 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012926 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012927 + " seq=" + seq + " app=" + r.callerApp);
12928 }
12929 performReceive(r.callerApp, r.resultTo,
12930 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012931 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012932 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012933 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012934 }
12935 }
12936
Joe Onorato8a9b2202010-02-26 18:56:32 -080012937 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012938 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12939
Joe Onorato8a9b2202010-02-26 18:56:32 -080012940 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012941 + r);
12942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012943 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012944 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012945 mOrderedBroadcasts.remove(0);
12946 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012947 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012948 continue;
12949 }
12950 } while (r == null);
12951
12952 // Get the next receiver...
12953 int recIdx = r.nextReceiver++;
12954
12955 // Keep track of when this receiver started, and make sure there
12956 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012957 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012958 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012959 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012960
Joe Onorato8a9b2202010-02-26 18:56:32 -080012961 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012962 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012963 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012964 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012965 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012966 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012967 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012968 }
12969
12970 Object nextReceiver = r.receivers.get(recIdx);
12971 if (nextReceiver instanceof BroadcastFilter) {
12972 // Simple case: this is a registered receiver who gets
12973 // a direct call.
12974 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012975 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012976 "Delivering serialized to registered "
12977 + filter + ": " + r);
12978 deliverToRegisteredReceiver(r, filter, r.ordered);
12979 if (r.receiver == null || !r.ordered) {
12980 // The receiver has already finished, so schedule to
12981 // process the next one.
12982 r.state = BroadcastRecord.IDLE;
12983 scheduleBroadcastsLocked();
12984 }
12985 return;
12986 }
12987
12988 // Hard case: need to instantiate the receiver, possibly
12989 // starting its application process to host it.
12990
12991 ResolveInfo info =
12992 (ResolveInfo)nextReceiver;
12993
12994 boolean skip = false;
12995 int perm = checkComponentPermission(info.activityInfo.permission,
12996 r.callingPid, r.callingUid,
12997 info.activityInfo.exported
12998 ? -1 : info.activityInfo.applicationInfo.uid);
12999 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013000 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013001 + r.intent.toString()
13002 + " from " + r.callerPackage + " (pid=" + r.callingPid
13003 + ", uid=" + r.callingUid + ")"
13004 + " requires " + info.activityInfo.permission
13005 + " due to receiver " + info.activityInfo.packageName
13006 + "/" + info.activityInfo.name);
13007 skip = true;
13008 }
13009 if (r.callingUid != Process.SYSTEM_UID &&
13010 r.requiredPermission != null) {
13011 try {
13012 perm = ActivityThread.getPackageManager().
13013 checkPermission(r.requiredPermission,
13014 info.activityInfo.applicationInfo.packageName);
13015 } catch (RemoteException e) {
13016 perm = PackageManager.PERMISSION_DENIED;
13017 }
13018 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013019 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013020 + r.intent + " to "
13021 + info.activityInfo.applicationInfo.packageName
13022 + " requires " + r.requiredPermission
13023 + " due to sender " + r.callerPackage
13024 + " (uid " + r.callingUid + ")");
13025 skip = true;
13026 }
13027 }
13028 if (r.curApp != null && r.curApp.crashing) {
13029 // If the target process is crashing, just skip it.
13030 skip = true;
13031 }
13032
13033 if (skip) {
13034 r.receiver = null;
13035 r.curFilter = null;
13036 r.state = BroadcastRecord.IDLE;
13037 scheduleBroadcastsLocked();
13038 return;
13039 }
13040
13041 r.state = BroadcastRecord.APP_RECEIVE;
13042 String targetProcess = info.activityInfo.processName;
13043 r.curComponent = new ComponentName(
13044 info.activityInfo.applicationInfo.packageName,
13045 info.activityInfo.name);
13046 r.curReceiver = info.activityInfo;
13047
13048 // Is this receiver's application already running?
13049 ProcessRecord app = getProcessRecordLocked(targetProcess,
13050 info.activityInfo.applicationInfo.uid);
13051 if (app != null && app.thread != null) {
13052 try {
13053 processCurBroadcastLocked(r, app);
13054 return;
13055 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013056 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013057 + r.curComponent, e);
13058 }
13059
13060 // If a dead object exception was thrown -- fall through to
13061 // restart the application.
13062 }
13063
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013064 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013065 if ((r.curApp=startProcessLocked(targetProcess,
13066 info.activityInfo.applicationInfo, true,
13067 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013068 "broadcast", r.curComponent,
13069 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13070 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013071 // Ah, this recipient is unavailable. Finish it if necessary,
13072 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013073 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013074 + info.activityInfo.applicationInfo.packageName + "/"
13075 + info.activityInfo.applicationInfo.uid + " for broadcast "
13076 + r.intent + ": process is bad");
13077 logBroadcastReceiverDiscard(r);
13078 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13079 r.resultExtras, r.resultAbort, true);
13080 scheduleBroadcastsLocked();
13081 r.state = BroadcastRecord.IDLE;
13082 return;
13083 }
13084
13085 mPendingBroadcast = r;
13086 }
13087 }
13088
13089 // =========================================================
13090 // INSTRUMENTATION
13091 // =========================================================
13092
13093 public boolean startInstrumentation(ComponentName className,
13094 String profileFile, int flags, Bundle arguments,
13095 IInstrumentationWatcher watcher) {
13096 // Refuse possible leaked file descriptors
13097 if (arguments != null && arguments.hasFileDescriptors()) {
13098 throw new IllegalArgumentException("File descriptors passed in Bundle");
13099 }
13100
13101 synchronized(this) {
13102 InstrumentationInfo ii = null;
13103 ApplicationInfo ai = null;
13104 try {
13105 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013106 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013107 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013108 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013109 } catch (PackageManager.NameNotFoundException e) {
13110 }
13111 if (ii == null) {
13112 reportStartInstrumentationFailure(watcher, className,
13113 "Unable to find instrumentation info for: " + className);
13114 return false;
13115 }
13116 if (ai == null) {
13117 reportStartInstrumentationFailure(watcher, className,
13118 "Unable to find instrumentation target package: " + ii.targetPackage);
13119 return false;
13120 }
13121
13122 int match = mContext.getPackageManager().checkSignatures(
13123 ii.targetPackage, ii.packageName);
13124 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13125 String msg = "Permission Denial: starting instrumentation "
13126 + className + " from pid="
13127 + Binder.getCallingPid()
13128 + ", uid=" + Binder.getCallingPid()
13129 + " not allowed because package " + ii.packageName
13130 + " does not have a signature matching the target "
13131 + ii.targetPackage;
13132 reportStartInstrumentationFailure(watcher, className, msg);
13133 throw new SecurityException(msg);
13134 }
13135
13136 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013137 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013138 ProcessRecord app = addAppLocked(ai);
13139 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013140 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013141 app.instrumentationProfileFile = profileFile;
13142 app.instrumentationArguments = arguments;
13143 app.instrumentationWatcher = watcher;
13144 app.instrumentationResultClass = className;
13145 Binder.restoreCallingIdentity(origId);
13146 }
13147
13148 return true;
13149 }
13150
13151 /**
13152 * Report errors that occur while attempting to start Instrumentation. Always writes the
13153 * error to the logs, but if somebody is watching, send the report there too. This enables
13154 * the "am" command to report errors with more information.
13155 *
13156 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13157 * @param cn The component name of the instrumentation.
13158 * @param report The error report.
13159 */
13160 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13161 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013162 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013163 try {
13164 if (watcher != null) {
13165 Bundle results = new Bundle();
13166 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13167 results.putString("Error", report);
13168 watcher.instrumentationStatus(cn, -1, results);
13169 }
13170 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013171 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013172 }
13173 }
13174
13175 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13176 if (app.instrumentationWatcher != null) {
13177 try {
13178 // NOTE: IInstrumentationWatcher *must* be oneway here
13179 app.instrumentationWatcher.instrumentationFinished(
13180 app.instrumentationClass,
13181 resultCode,
13182 results);
13183 } catch (RemoteException e) {
13184 }
13185 }
13186 app.instrumentationWatcher = null;
13187 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013188 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013189 app.instrumentationProfileFile = null;
13190 app.instrumentationArguments = null;
13191
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013192 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013193 }
13194
13195 public void finishInstrumentation(IApplicationThread target,
13196 int resultCode, Bundle results) {
13197 // Refuse possible leaked file descriptors
13198 if (results != null && results.hasFileDescriptors()) {
13199 throw new IllegalArgumentException("File descriptors passed in Intent");
13200 }
13201
13202 synchronized(this) {
13203 ProcessRecord app = getRecordForAppLocked(target);
13204 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013205 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013206 return;
13207 }
13208 final long origId = Binder.clearCallingIdentity();
13209 finishInstrumentationLocked(app, resultCode, results);
13210 Binder.restoreCallingIdentity(origId);
13211 }
13212 }
13213
13214 // =========================================================
13215 // CONFIGURATION
13216 // =========================================================
13217
13218 public ConfigurationInfo getDeviceConfigurationInfo() {
13219 ConfigurationInfo config = new ConfigurationInfo();
13220 synchronized (this) {
13221 config.reqTouchScreen = mConfiguration.touchscreen;
13222 config.reqKeyboardType = mConfiguration.keyboard;
13223 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013224 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13225 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013226 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13227 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013228 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13229 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013230 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13231 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013232 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013233 }
13234 return config;
13235 }
13236
13237 public Configuration getConfiguration() {
13238 Configuration ci;
13239 synchronized(this) {
13240 ci = new Configuration(mConfiguration);
13241 }
13242 return ci;
13243 }
13244
13245 public void updateConfiguration(Configuration values) {
13246 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13247 "updateConfiguration()");
13248
13249 synchronized(this) {
13250 if (values == null && mWindowManager != null) {
13251 // sentinel: fetch the current configuration from the window manager
13252 values = mWindowManager.computeNewConfiguration();
13253 }
13254
13255 final long origId = Binder.clearCallingIdentity();
13256 updateConfigurationLocked(values, null);
13257 Binder.restoreCallingIdentity(origId);
13258 }
13259 }
13260
13261 /**
13262 * Do either or both things: (1) change the current configuration, and (2)
13263 * make sure the given activity is running with the (now) current
13264 * configuration. Returns true if the activity has been left running, or
13265 * false if <var>starting</var> is being destroyed to match the new
13266 * configuration.
13267 */
13268 public boolean updateConfigurationLocked(Configuration values,
13269 HistoryRecord starting) {
13270 int changes = 0;
13271
13272 boolean kept = true;
13273
13274 if (values != null) {
13275 Configuration newConfig = new Configuration(mConfiguration);
13276 changes = newConfig.updateFrom(values);
13277 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013278 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013279 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013280 }
13281
Doug Zongker2bec3d42009-12-04 12:52:44 -080013282 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013283
13284 if (values.locale != null) {
13285 saveLocaleLocked(values.locale,
13286 !values.locale.equals(mConfiguration.locale),
13287 values.userSetLocale);
13288 }
13289
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013290 mConfigurationSeq++;
13291 if (mConfigurationSeq <= 0) {
13292 mConfigurationSeq = 1;
13293 }
13294 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013295 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013296 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013297
13298 AttributeCache ac = AttributeCache.instance();
13299 if (ac != null) {
13300 ac.updateConfiguration(mConfiguration);
13301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013302
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013303 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13304 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13305 msg.obj = new Configuration(mConfiguration);
13306 mHandler.sendMessage(msg);
13307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013308
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013309 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13310 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013311 try {
13312 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013313 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013314 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013315 app.thread.scheduleConfigurationChanged(mConfiguration);
13316 }
13317 } catch (Exception e) {
13318 }
13319 }
13320 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013321 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13322 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013323 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13324 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013325 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13326 broadcastIntentLocked(null, null,
13327 new Intent(Intent.ACTION_LOCALE_CHANGED),
13328 null, null, 0, null, null,
13329 null, false, false, MY_PID, Process.SYSTEM_UID);
13330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013331 }
13332 }
13333
13334 if (changes != 0 && starting == null) {
13335 // If the configuration changed, and the caller is not already
13336 // in the process of starting an activity, then find the top
13337 // activity to check if its configuration needs to change.
13338 starting = topRunningActivityLocked(null);
13339 }
13340
13341 if (starting != null) {
13342 kept = ensureActivityConfigurationLocked(starting, changes);
13343 if (kept) {
13344 // If this didn't result in the starting activity being
13345 // destroyed, then we need to make sure at this point that all
13346 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013347 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013348 + ", ensuring others are correct.");
13349 ensureActivitiesVisibleLocked(starting, changes);
13350 }
13351 }
13352
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013353 if (values != null && mWindowManager != null) {
13354 mWindowManager.setNewConfiguration(mConfiguration);
13355 }
13356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013357 return kept;
13358 }
13359
13360 private final boolean relaunchActivityLocked(HistoryRecord r,
13361 int changes, boolean andResume) {
13362 List<ResultInfo> results = null;
13363 List<Intent> newIntents = null;
13364 if (andResume) {
13365 results = r.results;
13366 newIntents = r.newIntents;
13367 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013368 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013369 + " with results=" + results + " newIntents=" + newIntents
13370 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013371 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13372 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013373 r.task.taskId, r.shortComponentName);
13374
13375 r.startFreezingScreenLocked(r.app, 0);
13376
13377 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013378 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013379 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013380 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381 // Note: don't need to call pauseIfSleepingLocked() here, because
13382 // the caller will only pass in 'andResume' if this activity is
13383 // currently resumed, which implies we aren't sleeping.
13384 } catch (RemoteException e) {
13385 return false;
13386 }
13387
13388 if (andResume) {
13389 r.results = null;
13390 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013391 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392 }
13393
13394 return true;
13395 }
13396
13397 /**
13398 * Make sure the given activity matches the current configuration. Returns
13399 * false if the activity had to be destroyed. Returns true if the
13400 * configuration is the same, or the activity will remain running as-is
13401 * for whatever reason. Ensures the HistoryRecord is updated with the
13402 * correct configuration and all other bookkeeping is handled.
13403 */
13404 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13405 int globalChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013406 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013407 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013408
13409 // Short circuit: if the two configurations are the exact same
13410 // object (the common case), then there is nothing to do.
13411 Configuration newConfig = mConfiguration;
13412 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013413 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013414 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013415 return true;
13416 }
13417
13418 // We don't worry about activities that are finishing.
13419 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013420 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013421 "Configuration doesn't matter in finishing " + r);
13422 r.stopFreezingScreenLocked(false);
13423 return true;
13424 }
13425
13426 // Okay we now are going to make this activity have the new config.
13427 // But then we need to figure out how it needs to deal with that.
13428 Configuration oldConfig = r.configuration;
13429 r.configuration = newConfig;
13430
13431 // If the activity isn't currently running, just leave the new
13432 // configuration and it will pick that up next time it starts.
13433 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013434 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013435 "Configuration doesn't matter not running " + r);
13436 r.stopFreezingScreenLocked(false);
13437 return true;
13438 }
13439
13440 // If the activity isn't persistent, there is a chance we will
13441 // need to restart it.
13442 if (!r.persistent) {
13443
13444 // Figure out what has changed between the two configurations.
13445 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013446 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013447 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013448 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013449 + Integer.toHexString(r.info.configChanges)
13450 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013451 }
13452 if ((changes&(~r.info.configChanges)) != 0) {
13453 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13454 r.configChangeFlags |= changes;
13455 r.startFreezingScreenLocked(r.app, globalChanges);
13456 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013457 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013458 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013459 destroyActivityLocked(r, true);
13460 } else if (r.state == ActivityState.PAUSING) {
13461 // A little annoying: we are waiting for this activity to
13462 // finish pausing. Let's not do anything now, but just
13463 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013464 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013465 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013466 r.configDestroy = true;
13467 return true;
13468 } else if (r.state == ActivityState.RESUMED) {
13469 // Try to optimize this case: the configuration is changing
13470 // and we need to restart the top, resumed activity.
13471 // Instead of doing the normal handshaking, just say
13472 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013473 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013474 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013475 relaunchActivityLocked(r, r.configChangeFlags, true);
13476 r.configChangeFlags = 0;
13477 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013478 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013479 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013480 relaunchActivityLocked(r, r.configChangeFlags, false);
13481 r.configChangeFlags = 0;
13482 }
13483
13484 // All done... tell the caller we weren't able to keep this
13485 // activity around.
13486 return false;
13487 }
13488 }
13489
13490 // Default case: the activity can handle this new configuration, so
13491 // hand it over. Note that we don't need to give it the new
13492 // configuration, since we always send configuration changes to all
13493 // process when they happen so it can just use whatever configuration
13494 // it last got.
13495 if (r.app != null && r.app.thread != null) {
13496 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013497 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013498 r.app.thread.scheduleActivityConfigurationChanged(r);
13499 } catch (RemoteException e) {
13500 // If process died, whatever.
13501 }
13502 }
13503 r.stopFreezingScreenLocked(false);
13504
13505 return true;
13506 }
13507
13508 /**
13509 * Save the locale. You must be inside a synchronized (this) block.
13510 */
13511 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13512 if(isDiff) {
13513 SystemProperties.set("user.language", l.getLanguage());
13514 SystemProperties.set("user.region", l.getCountry());
13515 }
13516
13517 if(isPersist) {
13518 SystemProperties.set("persist.sys.language", l.getLanguage());
13519 SystemProperties.set("persist.sys.country", l.getCountry());
13520 SystemProperties.set("persist.sys.localevar", l.getVariant());
13521 }
13522 }
13523
13524 // =========================================================
13525 // LIFETIME MANAGEMENT
13526 // =========================================================
13527
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013528 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13529 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013530 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013531 // This adjustment has already been computed. If we are calling
13532 // from the top, we may have already computed our adjustment with
13533 // an earlier hidden adjustment that isn't really for us... if
13534 // so, use the new hidden adjustment.
13535 if (!recursed && app.hidden) {
13536 app.curAdj = hiddenAdj;
13537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013538 return app.curAdj;
13539 }
13540
13541 if (app.thread == null) {
13542 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013543 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013544 return (app.curAdj=EMPTY_APP_ADJ);
13545 }
13546
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013547 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13548 // The max adjustment doesn't allow this app to be anything
13549 // below foreground, so it is not worth doing work for it.
13550 app.adjType = "fixed";
13551 app.adjSeq = mAdjSeq;
13552 app.curRawAdj = app.maxAdj;
13553 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13554 return (app.curAdj=app.maxAdj);
13555 }
13556
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013557 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013558 app.adjSource = null;
13559 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013560 app.empty = false;
13561 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013562
The Android Open Source Project4df24232009-03-05 14:34:35 -080013563 // Determine the importance of the process, starting with most
13564 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013565 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013566 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013567 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013568 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013569 // The last app on the list is the foreground app.
13570 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013571 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013572 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013573 } else if (app.instrumentationClass != null) {
13574 // Don't want to kill running instrumentation.
13575 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013576 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013577 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013578 } else if (app.persistentActivities > 0) {
13579 // Special persistent activities... shouldn't be used these days.
13580 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013581 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013582 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013583 } else if (app.curReceiver != null ||
13584 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13585 // An app that is currently receiving a broadcast also
13586 // counts as being in the foreground.
13587 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013588 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013589 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013590 } else if (app.executingServices.size() > 0) {
13591 // An app that is currently executing a service callback also
13592 // counts as being in the foreground.
13593 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013594 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013595 app.adjType = "exec-service";
13596 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013597 // The user is aware of this app, so make it visible.
13598 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013599 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013600 app.adjType = "foreground-service";
13601 } else if (app.forcingToForeground != null) {
13602 // The user is aware of this app, so make it visible.
13603 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013604 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013605 app.adjType = "force-foreground";
13606 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013607 } else if (app == mHomeProcess) {
13608 // This process is hosting what we currently consider to be the
13609 // home app, so we don't want to let it go into the background.
13610 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013611 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013612 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013613 } else if ((N=app.activities.size()) != 0) {
13614 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013615 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013616 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013617 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013618 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013619 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013620 for (int j=0; j<N; j++) {
13621 if (((HistoryRecord)app.activities.get(j)).visible) {
13622 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013623 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013624 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013625 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013626 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013627 break;
13628 }
13629 }
13630 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013631 // A very not-needed process. If this is lower in the lru list,
13632 // we will push it in to the empty bucket.
13633 app.hidden = true;
13634 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013635 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013636 adj = hiddenAdj;
13637 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013638 }
13639
Joe Onorato8a9b2202010-02-26 18:56:32 -080013640 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013641
The Android Open Source Project4df24232009-03-05 14:34:35 -080013642 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013643 // there are applications dependent on our services or providers, but
13644 // this gives us a baseline and makes sure we don't get into an
13645 // infinite recursion.
13646 app.adjSeq = mAdjSeq;
13647 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013648
Christopher Tate6fa95972009-06-05 18:43:55 -070013649 if (mBackupTarget != null && app == mBackupTarget.app) {
13650 // If possible we want to avoid killing apps while they're being backed up
13651 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013652 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013653 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013654 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013655 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013656 }
13657 }
13658
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013659 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13660 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013661 final long now = SystemClock.uptimeMillis();
13662 // This process is more important if the top activity is
13663 // bound to the service.
13664 Iterator jt = app.services.iterator();
13665 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13666 ServiceRecord s = (ServiceRecord)jt.next();
13667 if (s.startRequested) {
13668 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13669 // This service has seen some activity within
13670 // recent memory, so we will keep its process ahead
13671 // of the background processes.
13672 if (adj > SECONDARY_SERVER_ADJ) {
13673 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013674 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013675 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013676 }
13677 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013678 // If we have let the service slide into the background
13679 // state, still have some text describing what it is doing
13680 // even though the service no longer has an impact.
13681 if (adj > SECONDARY_SERVER_ADJ) {
13682 app.adjType = "started-bg-services";
13683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013684 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013685 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13686 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013687 Iterator<ConnectionRecord> kt
13688 = s.connections.values().iterator();
13689 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13690 // XXX should compute this based on the max of
13691 // all connected clients.
13692 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013693 if (cr.binding.client == app) {
13694 // Binding to ourself is not interesting.
13695 continue;
13696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013697 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13698 ProcessRecord client = cr.binding.client;
13699 int myHiddenAdj = hiddenAdj;
13700 if (myHiddenAdj > client.hiddenAdj) {
13701 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13702 myHiddenAdj = client.hiddenAdj;
13703 } else {
13704 myHiddenAdj = VISIBLE_APP_ADJ;
13705 }
13706 }
13707 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013708 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013709 if (adj > clientAdj) {
13710 adj = clientAdj > VISIBLE_APP_ADJ
13711 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013712 if (!client.hidden) {
13713 app.hidden = false;
13714 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013715 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013716 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13717 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013718 app.adjSource = cr.binding.client;
13719 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013720 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013721 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13722 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13723 schedGroup = Process.THREAD_GROUP_DEFAULT;
13724 }
13725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013726 }
13727 HistoryRecord a = cr.activity;
13728 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013729 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013730 //}
13731 if (a != null && adj > FOREGROUND_APP_ADJ &&
13732 (a.state == ActivityState.RESUMED
13733 || a.state == ActivityState.PAUSING)) {
13734 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013735 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013736 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013737 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013738 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13739 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013740 app.adjSource = a;
13741 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013742 }
13743 }
13744 }
13745 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013746
13747 // Finally, f this process has active services running in it, we
13748 // would like to avoid killing it unless it would prevent the current
13749 // application from running. By default we put the process in
13750 // with the rest of the background processes; as we scan through
13751 // its services we may bump it up from there.
13752 if (adj > hiddenAdj) {
13753 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013754 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013755 app.adjType = "bg-services";
13756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013757 }
13758
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013759 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13760 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013761 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013762 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13763 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013764 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13765 if (cpr.clients.size() != 0) {
13766 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13767 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13768 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013769 if (client == app) {
13770 // Being our own client is not interesting.
13771 continue;
13772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013773 int myHiddenAdj = hiddenAdj;
13774 if (myHiddenAdj > client.hiddenAdj) {
13775 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13776 myHiddenAdj = client.hiddenAdj;
13777 } else {
13778 myHiddenAdj = FOREGROUND_APP_ADJ;
13779 }
13780 }
13781 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013782 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013783 if (adj > clientAdj) {
13784 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013785 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013786 if (!client.hidden) {
13787 app.hidden = false;
13788 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013789 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013790 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13791 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013792 app.adjSource = client;
13793 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013794 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013795 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13796 schedGroup = Process.THREAD_GROUP_DEFAULT;
13797 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013798 }
13799 }
13800 // If the provider has external (non-framework) process
13801 // dependencies, ensure that its adjustment is at least
13802 // FOREGROUND_APP_ADJ.
13803 if (cpr.externals != 0) {
13804 if (adj > FOREGROUND_APP_ADJ) {
13805 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013806 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013807 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013808 app.adjType = "provider";
13809 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013810 }
13811 }
13812 }
13813 }
13814
13815 app.curRawAdj = adj;
13816
Joe Onorato8a9b2202010-02-26 18:56:32 -080013817 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013818 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13819 if (adj > app.maxAdj) {
13820 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013821 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13822 schedGroup = Process.THREAD_GROUP_DEFAULT;
13823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013824 }
13825
13826 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013827 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013829 return adj;
13830 }
13831
13832 /**
13833 * Ask a given process to GC right now.
13834 */
13835 final void performAppGcLocked(ProcessRecord app) {
13836 try {
13837 app.lastRequestedGc = SystemClock.uptimeMillis();
13838 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013839 if (app.reportLowMemory) {
13840 app.reportLowMemory = false;
13841 app.thread.scheduleLowMemory();
13842 } else {
13843 app.thread.processInBackground();
13844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013845 }
13846 } catch (Exception e) {
13847 // whatever.
13848 }
13849 }
13850
13851 /**
13852 * Returns true if things are idle enough to perform GCs.
13853 */
Josh Bartel7f208742010-02-25 11:01:44 -060013854 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013855 return mParallelBroadcasts.size() == 0
13856 && mOrderedBroadcasts.size() == 0
13857 && (mSleeping || (mResumedActivity != null &&
13858 mResumedActivity.idle));
13859 }
13860
13861 /**
13862 * Perform GCs on all processes that are waiting for it, but only
13863 * if things are idle.
13864 */
13865 final void performAppGcsLocked() {
13866 final int N = mProcessesToGc.size();
13867 if (N <= 0) {
13868 return;
13869 }
Josh Bartel7f208742010-02-25 11:01:44 -060013870 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013871 while (mProcessesToGc.size() > 0) {
13872 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013873 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13874 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13875 <= SystemClock.uptimeMillis()) {
13876 // To avoid spamming the system, we will GC processes one
13877 // at a time, waiting a few seconds between each.
13878 performAppGcLocked(proc);
13879 scheduleAppGcsLocked();
13880 return;
13881 } else {
13882 // It hasn't been long enough since we last GCed this
13883 // process... put it in the list to wait for its time.
13884 addProcessToGcListLocked(proc);
13885 break;
13886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013887 }
13888 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013889
13890 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013891 }
13892 }
13893
13894 /**
13895 * If all looks good, perform GCs on all processes waiting for them.
13896 */
13897 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060013898 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013899 performAppGcsLocked();
13900 return;
13901 }
13902 // Still not idle, wait some more.
13903 scheduleAppGcsLocked();
13904 }
13905
13906 /**
13907 * Schedule the execution of all pending app GCs.
13908 */
13909 final void scheduleAppGcsLocked() {
13910 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013911
13912 if (mProcessesToGc.size() > 0) {
13913 // Schedule a GC for the time to the next process.
13914 ProcessRecord proc = mProcessesToGc.get(0);
13915 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13916
13917 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13918 long now = SystemClock.uptimeMillis();
13919 if (when < (now+GC_TIMEOUT)) {
13920 when = now + GC_TIMEOUT;
13921 }
13922 mHandler.sendMessageAtTime(msg, when);
13923 }
13924 }
13925
13926 /**
13927 * Add a process to the array of processes waiting to be GCed. Keeps the
13928 * list in sorted order by the last GC time. The process can't already be
13929 * on the list.
13930 */
13931 final void addProcessToGcListLocked(ProcessRecord proc) {
13932 boolean added = false;
13933 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13934 if (mProcessesToGc.get(i).lastRequestedGc <
13935 proc.lastRequestedGc) {
13936 added = true;
13937 mProcessesToGc.add(i+1, proc);
13938 break;
13939 }
13940 }
13941 if (!added) {
13942 mProcessesToGc.add(0, proc);
13943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013944 }
13945
13946 /**
13947 * Set up to ask a process to GC itself. This will either do it
13948 * immediately, or put it on the list of processes to gc the next
13949 * time things are idle.
13950 */
13951 final void scheduleAppGcLocked(ProcessRecord app) {
13952 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013953 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013954 return;
13955 }
13956 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013957 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013958 scheduleAppGcsLocked();
13959 }
13960 }
13961
13962 private final boolean updateOomAdjLocked(
13963 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13964 app.hiddenAdj = hiddenAdj;
13965
13966 if (app.thread == null) {
13967 return true;
13968 }
13969
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013970 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013971
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013972 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013973 if (app.curRawAdj != app.setRawAdj) {
13974 if (app.curRawAdj > FOREGROUND_APP_ADJ
13975 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13976 // If this app is transitioning from foreground to
13977 // non-foreground, have it do a gc.
13978 scheduleAppGcLocked(app);
13979 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13980 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13981 // Likewise do a gc when an app is moving in to the
13982 // background (such as a service stopping).
13983 scheduleAppGcLocked(app);
13984 }
13985 app.setRawAdj = app.curRawAdj;
13986 }
13987 if (adj != app.setAdj) {
13988 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013989 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013990 TAG, "Set app " + app.processName +
13991 " oom adj to " + adj);
13992 app.setAdj = adj;
13993 } else {
13994 return false;
13995 }
13996 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013997 if (app.setSchedGroup != app.curSchedGroup) {
13998 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013999 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014000 "Setting process group of " + app.processName
14001 + " to " + app.curSchedGroup);
14002 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014003 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014004 try {
14005 Process.setProcessGroup(app.pid, app.curSchedGroup);
14006 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014007 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014008 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014009 e.printStackTrace();
14010 } finally {
14011 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014012 }
14013 }
14014 if (false) {
14015 if (app.thread != null) {
14016 try {
14017 app.thread.setSchedulingGroup(app.curSchedGroup);
14018 } catch (RemoteException e) {
14019 }
14020 }
14021 }
14022 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014023 }
14024
14025 return true;
14026 }
14027
14028 private final HistoryRecord resumedAppLocked() {
14029 HistoryRecord resumedActivity = mResumedActivity;
14030 if (resumedActivity == null || resumedActivity.app == null) {
14031 resumedActivity = mPausingActivity;
14032 if (resumedActivity == null || resumedActivity.app == null) {
14033 resumedActivity = topRunningActivityLocked(null);
14034 }
14035 }
14036 return resumedActivity;
14037 }
14038
14039 private final boolean updateOomAdjLocked(ProcessRecord app) {
14040 final HistoryRecord TOP_ACT = resumedAppLocked();
14041 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14042 int curAdj = app.curAdj;
14043 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14044 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14045
14046 mAdjSeq++;
14047
14048 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14049 if (res) {
14050 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14051 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14052 if (nowHidden != wasHidden) {
14053 // Changed to/from hidden state, so apps after it in the LRU
14054 // list may also be changed.
14055 updateOomAdjLocked();
14056 }
14057 }
14058 return res;
14059 }
14060
14061 private final boolean updateOomAdjLocked() {
14062 boolean didOomAdj = true;
14063 final HistoryRecord TOP_ACT = resumedAppLocked();
14064 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14065
14066 if (false) {
14067 RuntimeException e = new RuntimeException();
14068 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014069 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014070 }
14071
14072 mAdjSeq++;
14073
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014074 // Let's determine how many processes we have running vs.
14075 // how many slots we have for background processes; we may want
14076 // to put multiple processes in a slot of there are enough of
14077 // them.
14078 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14079 int factor = (mLruProcesses.size()-4)/numSlots;
14080 if (factor < 1) factor = 1;
14081 int step = 0;
14082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014083 // First try updating the OOM adjustment for each of the
14084 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014085 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014086 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14087 while (i > 0) {
14088 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014089 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014090 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014091 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014092 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014093 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014094 step++;
14095 if (step >= factor) {
14096 step = 0;
14097 curHiddenAdj++;
14098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014099 }
14100 } else {
14101 didOomAdj = false;
14102 }
14103 }
14104
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014105 // If we return false, we will fall back on killing processes to
14106 // have a fixed limit. Do this if a limit has been requested; else
14107 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014108 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14109 }
14110
14111 private final void trimApplications() {
14112 synchronized (this) {
14113 int i;
14114
14115 // First remove any unused application processes whose package
14116 // has been removed.
14117 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14118 final ProcessRecord app = mRemovedProcesses.get(i);
14119 if (app.activities.size() == 0
14120 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014121 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014122 TAG, "Exiting empty application process "
14123 + app.processName + " ("
14124 + (app.thread != null ? app.thread.asBinder() : null)
14125 + ")\n");
14126 if (app.pid > 0 && app.pid != MY_PID) {
14127 Process.killProcess(app.pid);
14128 } else {
14129 try {
14130 app.thread.scheduleExit();
14131 } catch (Exception e) {
14132 // Ignore exceptions.
14133 }
14134 }
14135 cleanUpApplicationRecordLocked(app, false, -1);
14136 mRemovedProcesses.remove(i);
14137
14138 if (app.persistent) {
14139 if (app.persistent) {
14140 addAppLocked(app.info);
14141 }
14142 }
14143 }
14144 }
14145
14146 // Now try updating the OOM adjustment for each of the
14147 // application processes based on their current state.
14148 // If the setOomAdj() API is not supported, then go with our
14149 // back-up plan...
14150 if (!updateOomAdjLocked()) {
14151
14152 // Count how many processes are running services.
14153 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014154 for (i=mLruProcesses.size()-1; i>=0; i--) {
14155 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014156
14157 if (app.persistent || app.services.size() != 0
14158 || app.curReceiver != null
14159 || app.persistentActivities > 0) {
14160 // Don't count processes holding services against our
14161 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014162 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014163 TAG, "Not trimming app " + app + " with services: "
14164 + app.services);
14165 numServiceProcs++;
14166 }
14167 }
14168
14169 int curMaxProcs = mProcessLimit;
14170 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14171 if (mAlwaysFinishActivities) {
14172 curMaxProcs = 1;
14173 }
14174 curMaxProcs += numServiceProcs;
14175
14176 // Quit as many processes as we can to get down to the desired
14177 // process count. First remove any processes that no longer
14178 // have activites running in them.
14179 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014180 i<mLruProcesses.size()
14181 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014182 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014183 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014184 // Quit an application only if it is not currently
14185 // running any activities.
14186 if (!app.persistent && app.activities.size() == 0
14187 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014188 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014189 TAG, "Exiting empty application process "
14190 + app.processName + " ("
14191 + (app.thread != null ? app.thread.asBinder() : null)
14192 + ")\n");
14193 if (app.pid > 0 && app.pid != MY_PID) {
14194 Process.killProcess(app.pid);
14195 } else {
14196 try {
14197 app.thread.scheduleExit();
14198 } catch (Exception e) {
14199 // Ignore exceptions.
14200 }
14201 }
14202 // todo: For now we assume the application is not buggy
14203 // or evil, and will quit as a result of our request.
14204 // Eventually we need to drive this off of the death
14205 // notification, and kill the process if it takes too long.
14206 cleanUpApplicationRecordLocked(app, false, i);
14207 i--;
14208 }
14209 }
14210
14211 // If we still have too many processes, now from the least
14212 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014213 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014214 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014215 " of " + curMaxProcs + " processes");
14216 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014217 i<mLruProcesses.size()
14218 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014219 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014220 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014221 // Quit the application only if we have a state saved for
14222 // all of its activities.
14223 boolean canQuit = !app.persistent && app.curReceiver == null
14224 && app.services.size() == 0
14225 && app.persistentActivities == 0;
14226 int NUMA = app.activities.size();
14227 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014228 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014229 TAG, "Looking to quit " + app.processName);
14230 for (j=0; j<NUMA && canQuit; j++) {
14231 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014232 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014233 TAG, " " + r.intent.getComponent().flattenToShortString()
14234 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14235 canQuit = (r.haveState || !r.stateNotNeeded)
14236 && !r.visible && r.stopped;
14237 }
14238 if (canQuit) {
14239 // Finish all of the activities, and then the app itself.
14240 for (j=0; j<NUMA; j++) {
14241 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14242 if (!r.finishing) {
14243 destroyActivityLocked(r, false);
14244 }
14245 r.resultTo = null;
14246 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014247 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014248 + app.processName + " ("
14249 + (app.thread != null ? app.thread.asBinder() : null)
14250 + ")\n");
14251 if (app.pid > 0 && app.pid != MY_PID) {
14252 Process.killProcess(app.pid);
14253 } else {
14254 try {
14255 app.thread.scheduleExit();
14256 } catch (Exception e) {
14257 // Ignore exceptions.
14258 }
14259 }
14260 // todo: For now we assume the application is not buggy
14261 // or evil, and will quit as a result of our request.
14262 // Eventually we need to drive this off of the death
14263 // notification, and kill the process if it takes too long.
14264 cleanUpApplicationRecordLocked(app, false, i);
14265 i--;
14266 //dump();
14267 }
14268 }
14269
14270 }
14271
14272 int curMaxActivities = MAX_ACTIVITIES;
14273 if (mAlwaysFinishActivities) {
14274 curMaxActivities = 1;
14275 }
14276
14277 // Finally, if there are too many activities now running, try to
14278 // finish as many as we can to get back down to the limit.
14279 for ( i=0;
14280 i<mLRUActivities.size()
14281 && mLRUActivities.size() > curMaxActivities;
14282 i++) {
14283 final HistoryRecord r
14284 = (HistoryRecord)mLRUActivities.get(i);
14285
14286 // We can finish this one if we have its icicle saved and
14287 // it is not persistent.
14288 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14289 && r.stopped && !r.persistent && !r.finishing) {
14290 final int origSize = mLRUActivities.size();
14291 destroyActivityLocked(r, true);
14292
14293 // This will remove it from the LRU list, so keep
14294 // our index at the same value. Note that this check to
14295 // see if the size changes is just paranoia -- if
14296 // something unexpected happens, we don't want to end up
14297 // in an infinite loop.
14298 if (origSize > mLRUActivities.size()) {
14299 i--;
14300 }
14301 }
14302 }
14303 }
14304 }
14305
14306 /** This method sends the specified signal to each of the persistent apps */
14307 public void signalPersistentProcesses(int sig) throws RemoteException {
14308 if (sig != Process.SIGNAL_USR1) {
14309 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14310 }
14311
14312 synchronized (this) {
14313 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14314 != PackageManager.PERMISSION_GRANTED) {
14315 throw new SecurityException("Requires permission "
14316 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14317 }
14318
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014319 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14320 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014321 if (r.thread != null && r.persistent) {
14322 Process.sendSignal(r.pid, sig);
14323 }
14324 }
14325 }
14326 }
14327
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014328 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014329 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014330
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014331 try {
14332 synchronized (this) {
14333 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14334 // its own permission.
14335 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14336 != PackageManager.PERMISSION_GRANTED) {
14337 throw new SecurityException("Requires permission "
14338 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014339 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014340
14341 if (start && fd == null) {
14342 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014343 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014344
14345 ProcessRecord proc = null;
14346 try {
14347 int pid = Integer.parseInt(process);
14348 synchronized (mPidsSelfLocked) {
14349 proc = mPidsSelfLocked.get(pid);
14350 }
14351 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014352 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014353
14354 if (proc == null) {
14355 HashMap<String, SparseArray<ProcessRecord>> all
14356 = mProcessNames.getMap();
14357 SparseArray<ProcessRecord> procs = all.get(process);
14358 if (procs != null && procs.size() > 0) {
14359 proc = procs.valueAt(0);
14360 }
14361 }
14362
14363 if (proc == null || proc.thread == null) {
14364 throw new IllegalArgumentException("Unknown process: " + process);
14365 }
14366
14367 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14368 if (isSecure) {
14369 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14370 throw new SecurityException("Process not debuggable: " + proc);
14371 }
14372 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014373
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014374 proc.thread.profilerControl(start, path, fd);
14375 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014376 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014377 }
14378 } catch (RemoteException e) {
14379 throw new IllegalStateException("Process disappeared");
14380 } finally {
14381 if (fd != null) {
14382 try {
14383 fd.close();
14384 } catch (IOException e) {
14385 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014386 }
14387 }
14388 }
14389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014390 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14391 public void monitor() {
14392 synchronized (this) { }
14393 }
14394}