blob: f7340530a884bb6bb3eca8775e9bdde052d1df26 [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 Hackborn2ccda4d2010-03-22 21:49:15 -07003615 boolean debug, WaitResult outResult, Configuration config) {
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);
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003669 if (config != null) {
3670 // If the caller also wants to switch to a new configuration,
3671 // do so now. This allows a clean switch, as we are waiting
3672 // for the current activity to pause (so we will not destroy
3673 // it), and have not yet started the next activity.
3674 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3675 "updateConfiguration()");
3676 updateConfigurationLocked(config, null);
3677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003678 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003679
3680 if (outResult != null) {
3681 outResult.result = res;
3682 if (res == IActivityManager.START_SUCCESS) {
3683 mWaitingActivityLaunched.add(outResult);
3684 do {
3685 try {
3686 wait();
3687 } catch (InterruptedException e) {
3688 }
3689 } while (!outResult.timeout && outResult.who == null);
3690 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3691 HistoryRecord r = this.topRunningActivityLocked(null);
3692 if (r.nowVisible) {
3693 outResult.timeout = false;
3694 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3695 outResult.totalTime = 0;
3696 outResult.thisTime = 0;
3697 } else {
3698 outResult.thisTime = SystemClock.uptimeMillis();
3699 mWaitingActivityVisible.add(outResult);
3700 do {
3701 try {
3702 wait();
3703 } catch (InterruptedException e) {
3704 }
3705 } while (!outResult.timeout && outResult.who == null);
3706 }
3707 }
3708 }
3709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 return res;
3711 }
3712 }
3713
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003714 public final int startActivity(IApplicationThread caller,
3715 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3716 int grantedMode, IBinder resultTo,
3717 String resultWho, int requestCode, boolean onlyIfNeeded,
3718 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003719 return startActivityMayWait(caller, intent, resolvedType,
3720 grantedUriPermissions, grantedMode, resultTo, resultWho,
3721 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003722 }
3723
3724 public final WaitResult startActivityAndWait(IApplicationThread caller,
3725 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3726 int grantedMode, IBinder resultTo,
3727 String resultWho, int requestCode, boolean onlyIfNeeded,
3728 boolean debug) {
3729 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003730 startActivityMayWait(caller, intent, resolvedType,
3731 grantedUriPermissions, grantedMode, resultTo, resultWho,
3732 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003733 return res;
3734 }
3735
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003736 public final int startActivityWithConfig(IApplicationThread caller,
3737 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3738 int grantedMode, IBinder resultTo,
3739 String resultWho, int requestCode, boolean onlyIfNeeded,
3740 boolean debug, Configuration config) {
3741 return startActivityMayWait(caller, intent, resolvedType,
3742 grantedUriPermissions, grantedMode, resultTo, resultWho,
3743 requestCode, onlyIfNeeded, debug, null, config);
3744 }
3745
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003746 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003747 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003748 IBinder resultTo, String resultWho, int requestCode,
3749 int flagsMask, int flagsValues) {
3750 // Refuse possible leaked file descriptors
3751 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3752 throw new IllegalArgumentException("File descriptors passed in Intent");
3753 }
3754
3755 IIntentSender sender = intent.getTarget();
3756 if (!(sender instanceof PendingIntentRecord)) {
3757 throw new IllegalArgumentException("Bad PendingIntent object");
3758 }
3759
3760 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003761
3762 synchronized (this) {
3763 // If this is coming from the currently resumed activity, it is
3764 // effectively saying that app switches are allowed at this point.
3765 if (mResumedActivity != null
3766 && mResumedActivity.info.applicationInfo.uid ==
3767 Binder.getCallingUid()) {
3768 mAppSwitchesAllowedTime = 0;
3769 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003770 }
3771
3772 return pir.sendInner(0, fillInIntent, resolvedType,
3773 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3774 }
3775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 public boolean startNextMatchingActivity(IBinder callingActivity,
3777 Intent intent) {
3778 // Refuse possible leaked file descriptors
3779 if (intent != null && intent.hasFileDescriptors() == true) {
3780 throw new IllegalArgumentException("File descriptors passed in Intent");
3781 }
3782
3783 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003784 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003785 if (index < 0) {
3786 return false;
3787 }
3788 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3789 if (r.app == null || r.app.thread == null) {
3790 // The caller is not running... d'oh!
3791 return false;
3792 }
3793 intent = new Intent(intent);
3794 // The caller is not allowed to change the data.
3795 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3796 // And we are resetting to find the next component...
3797 intent.setComponent(null);
3798
3799 ActivityInfo aInfo = null;
3800 try {
3801 List<ResolveInfo> resolves =
3802 ActivityThread.getPackageManager().queryIntentActivities(
3803 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003804 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805
3806 // Look for the original activity in the list...
3807 final int N = resolves != null ? resolves.size() : 0;
3808 for (int i=0; i<N; i++) {
3809 ResolveInfo rInfo = resolves.get(i);
3810 if (rInfo.activityInfo.packageName.equals(r.packageName)
3811 && rInfo.activityInfo.name.equals(r.info.name)) {
3812 // We found the current one... the next matching is
3813 // after it.
3814 i++;
3815 if (i<N) {
3816 aInfo = resolves.get(i).activityInfo;
3817 }
3818 break;
3819 }
3820 }
3821 } catch (RemoteException e) {
3822 }
3823
3824 if (aInfo == null) {
3825 // Nobody who is next!
3826 return false;
3827 }
3828
3829 intent.setComponent(new ComponentName(
3830 aInfo.applicationInfo.packageName, aInfo.name));
3831 intent.setFlags(intent.getFlags()&~(
3832 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3833 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3834 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3835 Intent.FLAG_ACTIVITY_NEW_TASK));
3836
3837 // Okay now we need to start the new activity, replacing the
3838 // currently running activity. This is a little tricky because
3839 // we want to start the new one as if the current one is finished,
3840 // but not finish the current one first so that there is no flicker.
3841 // And thus...
3842 final boolean wasFinishing = r.finishing;
3843 r.finishing = true;
3844
3845 // Propagate reply information over to the new activity.
3846 final HistoryRecord resultTo = r.resultTo;
3847 final String resultWho = r.resultWho;
3848 final int requestCode = r.requestCode;
3849 r.resultTo = null;
3850 if (resultTo != null) {
3851 resultTo.removeResultsLocked(r, resultWho, requestCode);
3852 }
3853
3854 final long origId = Binder.clearCallingIdentity();
3855 // XXX we are not dealing with propagating grantedUriPermissions...
3856 // those are not yet exposed to user code, so there is no need.
3857 int res = startActivityLocked(r.app.thread, intent,
3858 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003859 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 Binder.restoreCallingIdentity(origId);
3861
3862 r.finishing = wasFinishing;
3863 if (res != START_SUCCESS) {
3864 return false;
3865 }
3866 return true;
3867 }
3868 }
3869
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003870 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003871 Intent intent, String resolvedType, IBinder resultTo,
3872 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003873
3874 // This is so super not safe, that only the system (or okay root)
3875 // can do it.
3876 final int callingUid = Binder.getCallingUid();
3877 if (callingUid != 0 && callingUid != Process.myUid()) {
3878 throw new SecurityException(
3879 "startActivityInPackage only available to the system");
3880 }
3881
The Android Open Source Project4df24232009-03-05 14:34:35 -08003882 final boolean componentSpecified = intent.getComponent() != null;
3883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 // Don't modify the client's object!
3885 intent = new Intent(intent);
3886
3887 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 ActivityInfo aInfo;
3889 try {
3890 ResolveInfo rInfo =
3891 ActivityThread.getPackageManager().resolveIntent(
3892 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003893 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 aInfo = rInfo != null ? rInfo.activityInfo : null;
3895 } catch (RemoteException e) {
3896 aInfo = null;
3897 }
3898
3899 if (aInfo != null) {
3900 // Store the found target back into the intent, because now that
3901 // we have it we never want to do this again. For example, if the
3902 // user navigates back to this point in the history, we should
3903 // always restart the exact same activity.
3904 intent.setComponent(new ComponentName(
3905 aInfo.applicationInfo.packageName, aInfo.name));
3906 }
3907
3908 synchronized(this) {
3909 return startActivityLocked(null, intent, resolvedType,
3910 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003911 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 }
3913 }
3914
Josh Bartel7f208742010-02-25 11:01:44 -06003915 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 // Remove any existing entries that are the same kind of task.
3917 int N = mRecentTasks.size();
3918 for (int i=0; i<N; i++) {
3919 TaskRecord tr = mRecentTasks.get(i);
3920 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3921 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3922 mRecentTasks.remove(i);
3923 i--;
3924 N--;
3925 if (task.intent == null) {
3926 // If the new recent task we are adding is not fully
3927 // specified, then replace it with the existing recent task.
3928 task = tr;
3929 }
3930 }
3931 }
3932 if (N >= MAX_RECENT_TASKS) {
3933 mRecentTasks.remove(N-1);
3934 }
3935 mRecentTasks.add(0, task);
3936 }
3937
3938 public void setRequestedOrientation(IBinder token,
3939 int requestedOrientation) {
3940 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003941 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 if (index < 0) {
3943 return;
3944 }
3945 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3946 final long origId = Binder.clearCallingIdentity();
3947 mWindowManager.setAppOrientation(r, requestedOrientation);
3948 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003949 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 r.mayFreezeScreenLocked(r.app) ? r : null);
3951 if (config != null) {
3952 r.frozenBeforeDestroy = true;
3953 if (!updateConfigurationLocked(config, r)) {
3954 resumeTopActivityLocked(null);
3955 }
3956 }
3957 Binder.restoreCallingIdentity(origId);
3958 }
3959 }
3960
3961 public int getRequestedOrientation(IBinder token) {
3962 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003963 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 if (index < 0) {
3965 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3966 }
3967 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3968 return mWindowManager.getAppOrientation(r);
3969 }
3970 }
3971
3972 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003973 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3975 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3976 if (!r.finishing) {
3977 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3978 "no-history");
3979 }
3980 } else if (r.app != null && r.app.thread != null) {
3981 if (mFocusedActivity == r) {
3982 setFocusedActivityLocked(topRunningActivityLocked(null));
3983 }
3984 r.resumeKeyDispatchingLocked();
3985 try {
3986 r.stopped = false;
3987 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003988 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003989 TAG, "Stopping visible=" + r.visible + " for " + r);
3990 if (!r.visible) {
3991 mWindowManager.setAppVisibility(r, false);
3992 }
3993 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3994 } catch (Exception e) {
3995 // Maybe just ignore exceptions here... if the process
3996 // has crashed, our death notification will clean things
3997 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003998 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 // Just in case, assume it to be stopped.
4000 r.stopped = true;
4001 r.state = ActivityState.STOPPED;
4002 if (r.configDestroy) {
4003 destroyActivityLocked(r, true);
4004 }
4005 }
4006 }
4007 }
4008
4009 /**
4010 * @return Returns true if the activity is being finished, false if for
4011 * some reason it is being left as-is.
4012 */
4013 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4014 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004015 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004016 TAG, "Finishing activity: token=" + token
4017 + ", result=" + resultCode + ", data=" + resultData);
4018
Dianne Hackborn75b03852009-06-12 15:43:26 -07004019 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004020 if (index < 0) {
4021 return false;
4022 }
4023 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4024
4025 // Is this the last activity left?
4026 boolean lastActivity = true;
4027 for (int i=mHistory.size()-1; i>=0; i--) {
4028 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4029 if (!p.finishing && p != r) {
4030 lastActivity = false;
4031 break;
4032 }
4033 }
4034
4035 // If this is the last activity, but it is the home activity, then
4036 // just don't finish it.
4037 if (lastActivity) {
4038 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4039 return false;
4040 }
4041 }
4042
4043 finishActivityLocked(r, index, resultCode, resultData, reason);
4044 return true;
4045 }
4046
4047 /**
4048 * @return Returns true if this activity has been removed from the history
4049 * list, or false if it is still in the list and will be removed later.
4050 */
4051 private final boolean finishActivityLocked(HistoryRecord r, int index,
4052 int resultCode, Intent resultData, String reason) {
4053 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004054 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055 return false;
4056 }
4057
4058 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004059 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060 System.identityHashCode(r),
4061 r.task.taskId, r.shortComponentName, reason);
4062 r.task.numActivities--;
4063 if (r.frontOfTask && index < (mHistory.size()-1)) {
4064 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4065 if (next.task == r.task) {
4066 next.frontOfTask = true;
4067 }
4068 }
4069
4070 r.pauseKeyDispatchingLocked();
4071 if (mFocusedActivity == r) {
4072 setFocusedActivityLocked(topRunningActivityLocked(null));
4073 }
4074
4075 // send the result
4076 HistoryRecord resultTo = r.resultTo;
4077 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004078 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004079 + " who=" + r.resultWho + " req=" + r.requestCode
4080 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081 if (r.info.applicationInfo.uid > 0) {
4082 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4083 r.packageName, resultData, r);
4084 }
4085 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4086 resultData);
4087 r.resultTo = null;
4088 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004089 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004090
4091 // Make sure this HistoryRecord is not holding on to other resources,
4092 // because clients have remote IPC references to this object so we
4093 // can't assume that will go away and want to avoid circular IPC refs.
4094 r.results = null;
4095 r.pendingResults = null;
4096 r.newIntents = null;
4097 r.icicle = null;
4098
4099 if (mPendingThumbnails.size() > 0) {
4100 // There are clients waiting to receive thumbnails so, in case
4101 // this is an activity that someone is waiting for, add it
4102 // to the pending list so we can correctly update the clients.
4103 mCancelledThumbnails.add(r);
4104 }
4105
4106 if (mResumedActivity == r) {
4107 boolean endTask = index <= 0
4108 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004109 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004110 "Prepare close transition: finishing " + r);
4111 mWindowManager.prepareAppTransition(endTask
4112 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4113 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4114
4115 // Tell window manager to prepare for this one to be removed.
4116 mWindowManager.setAppVisibility(r, false);
4117
4118 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004119 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4120 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 startPausingLocked(false, false);
4122 }
4123
4124 } else if (r.state != ActivityState.PAUSING) {
4125 // If the activity is PAUSING, we will complete the finish once
4126 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004127 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 return finishCurrentActivityLocked(r, index,
4129 FINISH_AFTER_PAUSE) == null;
4130 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004131 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 }
4133
4134 return false;
4135 }
4136
4137 private static final int FINISH_IMMEDIATELY = 0;
4138 private static final int FINISH_AFTER_PAUSE = 1;
4139 private static final int FINISH_AFTER_VISIBLE = 2;
4140
4141 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4142 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004143 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144 if (index < 0) {
4145 return null;
4146 }
4147
4148 return finishCurrentActivityLocked(r, index, mode);
4149 }
4150
4151 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4152 int index, int mode) {
4153 // First things first: if this activity is currently visible,
4154 // and the resumed activity is not yet visible, then hold off on
4155 // finishing until the resumed one becomes visible.
4156 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4157 if (!mStoppingActivities.contains(r)) {
4158 mStoppingActivities.add(r);
4159 if (mStoppingActivities.size() > 3) {
4160 // If we already have a few activities waiting to stop,
4161 // then give up on things going idle and start clearing
4162 // them out.
4163 Message msg = Message.obtain();
4164 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4165 mHandler.sendMessage(msg);
4166 }
4167 }
4168 r.state = ActivityState.STOPPING;
4169 updateOomAdjLocked();
4170 return r;
4171 }
4172
4173 // make sure the record is cleaned out of other places.
4174 mStoppingActivities.remove(r);
4175 mWaitingVisibleActivities.remove(r);
4176 if (mResumedActivity == r) {
4177 mResumedActivity = null;
4178 }
4179 final ActivityState prevState = r.state;
4180 r.state = ActivityState.FINISHING;
4181
4182 if (mode == FINISH_IMMEDIATELY
4183 || prevState == ActivityState.STOPPED
4184 || prevState == ActivityState.INITIALIZING) {
4185 // If this activity is already stopped, we can just finish
4186 // it right now.
4187 return destroyActivityLocked(r, true) ? null : r;
4188 } else {
4189 // Need to go through the full pause cycle to get this
4190 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004191 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004192 mFinishingActivities.add(r);
4193 resumeTopActivityLocked(null);
4194 }
4195 return r;
4196 }
4197
4198 /**
4199 * This is the internal entry point for handling Activity.finish().
4200 *
4201 * @param token The Binder token referencing the Activity we want to finish.
4202 * @param resultCode Result code, if any, from this Activity.
4203 * @param resultData Result data (Intent), if any, from this Activity.
4204 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004205 * @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 -08004206 */
4207 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4208 // Refuse possible leaked file descriptors
4209 if (resultData != null && resultData.hasFileDescriptors() == true) {
4210 throw new IllegalArgumentException("File descriptors passed in Intent");
4211 }
4212
4213 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004214 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004215 // Find the first activity that is not finishing.
4216 HistoryRecord next = topRunningActivityLocked(token, 0);
4217 if (next != null) {
4218 // ask watcher if this is allowed
4219 boolean resumeOK = true;
4220 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004221 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004222 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004223 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 }
4225
4226 if (!resumeOK) {
4227 return false;
4228 }
4229 }
4230 }
4231 final long origId = Binder.clearCallingIdentity();
4232 boolean res = requestFinishActivityLocked(token, resultCode,
4233 resultData, "app-request");
4234 Binder.restoreCallingIdentity(origId);
4235 return res;
4236 }
4237 }
4238
4239 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4240 String resultWho, int requestCode, int resultCode, Intent data) {
4241
4242 if (callingUid > 0) {
4243 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4244 data, r);
4245 }
4246
Joe Onorato8a9b2202010-02-26 18:56:32 -08004247 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004248 + " : who=" + resultWho + " req=" + requestCode
4249 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4251 try {
4252 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4253 list.add(new ResultInfo(resultWho, requestCode,
4254 resultCode, data));
4255 r.app.thread.scheduleSendResult(r, list);
4256 return;
4257 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004258 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 }
4260 }
4261
4262 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4263 }
4264
4265 public final void finishSubActivity(IBinder token, String resultWho,
4266 int requestCode) {
4267 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004268 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 if (index < 0) {
4270 return;
4271 }
4272 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4273
4274 final long origId = Binder.clearCallingIdentity();
4275
4276 int i;
4277 for (i=mHistory.size()-1; i>=0; i--) {
4278 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4279 if (r.resultTo == self && r.requestCode == requestCode) {
4280 if ((r.resultWho == null && resultWho == null) ||
4281 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4282 finishActivityLocked(r, i,
4283 Activity.RESULT_CANCELED, null, "request-sub");
4284 }
4285 }
4286 }
4287
4288 Binder.restoreCallingIdentity(origId);
4289 }
4290 }
4291
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004292 public boolean willActivityBeVisible(IBinder token) {
4293 synchronized(this) {
4294 int i;
4295 for (i=mHistory.size()-1; i>=0; i--) {
4296 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4297 if (r == token) {
4298 return true;
4299 }
4300 if (r.fullscreen && !r.finishing) {
4301 return false;
4302 }
4303 }
4304 return true;
4305 }
4306 }
4307
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004308 public void overridePendingTransition(IBinder token, String packageName,
4309 int enterAnim, int exitAnim) {
4310 synchronized(this) {
4311 int index = indexOfTokenLocked(token);
4312 if (index < 0) {
4313 return;
4314 }
4315 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4316
4317 final long origId = Binder.clearCallingIdentity();
4318
4319 if (self.state == ActivityState.RESUMED
4320 || self.state == ActivityState.PAUSING) {
4321 mWindowManager.overridePendingAppTransition(packageName,
4322 enterAnim, exitAnim);
4323 }
4324
4325 Binder.restoreCallingIdentity(origId);
4326 }
4327 }
4328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004329 /**
4330 * Perform clean-up of service connections in an activity record.
4331 */
4332 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4333 // Throw away any services that have been bound by this activity.
4334 if (r.connections != null) {
4335 Iterator<ConnectionRecord> it = r.connections.iterator();
4336 while (it.hasNext()) {
4337 ConnectionRecord c = it.next();
4338 removeConnectionLocked(c, null, r);
4339 }
4340 r.connections = null;
4341 }
4342 }
4343
4344 /**
4345 * Perform the common clean-up of an activity record. This is called both
4346 * as part of destroyActivityLocked() (when destroying the client-side
4347 * representation) and cleaning things up as a result of its hosting
4348 * processing going away, in which case there is no remaining client-side
4349 * state to destroy so only the cleanup here is needed.
4350 */
4351 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4352 if (mResumedActivity == r) {
4353 mResumedActivity = null;
4354 }
4355 if (mFocusedActivity == r) {
4356 mFocusedActivity = null;
4357 }
4358
4359 r.configDestroy = false;
4360 r.frozenBeforeDestroy = false;
4361
4362 // Make sure this record is no longer in the pending finishes list.
4363 // This could happen, for example, if we are trimming activities
4364 // down to the max limit while they are still waiting to finish.
4365 mFinishingActivities.remove(r);
4366 mWaitingVisibleActivities.remove(r);
4367
4368 // Remove any pending results.
4369 if (r.finishing && r.pendingResults != null) {
4370 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4371 PendingIntentRecord rec = apr.get();
4372 if (rec != null) {
4373 cancelIntentSenderLocked(rec, false);
4374 }
4375 }
4376 r.pendingResults = null;
4377 }
4378
4379 if (cleanServices) {
4380 cleanUpActivityServicesLocked(r);
4381 }
4382
4383 if (mPendingThumbnails.size() > 0) {
4384 // There are clients waiting to receive thumbnails so, in case
4385 // this is an activity that someone is waiting for, add it
4386 // to the pending list so we can correctly update the clients.
4387 mCancelledThumbnails.add(r);
4388 }
4389
4390 // Get rid of any pending idle timeouts.
4391 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4392 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4393 }
4394
4395 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4396 if (r.state != ActivityState.DESTROYED) {
4397 mHistory.remove(r);
4398 r.inHistory = false;
4399 r.state = ActivityState.DESTROYED;
4400 mWindowManager.removeAppToken(r);
4401 if (VALIDATE_TOKENS) {
4402 mWindowManager.validateAppTokens(mHistory);
4403 }
4404 cleanUpActivityServicesLocked(r);
4405 removeActivityUriPermissionsLocked(r);
4406 }
4407 }
4408
4409 /**
4410 * Destroy the current CLIENT SIDE instance of an activity. This may be
4411 * called both when actually finishing an activity, or when performing
4412 * a configuration switch where we destroy the current client-side object
4413 * but then create a new client-side object for this same HistoryRecord.
4414 */
4415 private final boolean destroyActivityLocked(HistoryRecord r,
4416 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004417 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004418 TAG, "Removing activity: token=" + r
4419 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004420 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004421 System.identityHashCode(r),
4422 r.task.taskId, r.shortComponentName);
4423
4424 boolean removedFromHistory = false;
4425
4426 cleanUpActivityLocked(r, false);
4427
Dianne Hackborn03abb812010-01-04 18:43:19 -08004428 final boolean hadApp = r.app != null;
4429
4430 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 if (removeFromApp) {
4432 int idx = r.app.activities.indexOf(r);
4433 if (idx >= 0) {
4434 r.app.activities.remove(idx);
4435 }
4436 if (r.persistent) {
4437 decPersistentCountLocked(r.app);
4438 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004439 if (r.app.activities.size() == 0) {
4440 // No longer have activities, so update location in
4441 // LRU list.
4442 updateLruProcessLocked(r.app, true, false);
4443 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 }
4445
4446 boolean skipDestroy = false;
4447
4448 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004449 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004450 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4451 r.configChangeFlags);
4452 } catch (Exception e) {
4453 // We can just ignore exceptions here... if the process
4454 // has crashed, our death notification will clean things
4455 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004456 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 if (r.finishing) {
4458 removeActivityFromHistoryLocked(r);
4459 removedFromHistory = true;
4460 skipDestroy = true;
4461 }
4462 }
4463
4464 r.app = null;
4465 r.nowVisible = false;
4466
4467 if (r.finishing && !skipDestroy) {
4468 r.state = ActivityState.DESTROYING;
4469 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4470 msg.obj = r;
4471 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4472 } else {
4473 r.state = ActivityState.DESTROYED;
4474 }
4475 } else {
4476 // remove this record from the history.
4477 if (r.finishing) {
4478 removeActivityFromHistoryLocked(r);
4479 removedFromHistory = true;
4480 } else {
4481 r.state = ActivityState.DESTROYED;
4482 }
4483 }
4484
4485 r.configChangeFlags = 0;
4486
Dianne Hackborn03abb812010-01-04 18:43:19 -08004487 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004488 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 }
4490
4491 return removedFromHistory;
4492 }
4493
Dianne Hackborn03abb812010-01-04 18:43:19 -08004494 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004495 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004496 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 TAG, "Removing app " + app + " from list " + list
4498 + " with " + i + " entries");
4499 while (i > 0) {
4500 i--;
4501 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004502 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4504 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004505 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 list.remove(i);
4507 }
4508 }
4509 }
4510
4511 /**
4512 * Main function for removing an existing process from the activity manager
4513 * as a result of that process going away. Clears out all connections
4514 * to the process.
4515 */
4516 private final void handleAppDiedLocked(ProcessRecord app,
4517 boolean restarting) {
4518 cleanUpApplicationRecordLocked(app, restarting, -1);
4519 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004520 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 }
4522
4523 // Just in case...
4524 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004525 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004526 mPausingActivity = null;
4527 }
4528 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4529 mLastPausedActivity = null;
4530 }
4531
4532 // Remove this application's activities from active lists.
4533 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4534 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4535 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4536 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4537
4538 boolean atTop = true;
4539 boolean hasVisibleActivities = false;
4540
4541 // Clean out the history list.
4542 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004543 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 TAG, "Removing app " + app + " from history with " + i + " entries");
4545 while (i > 0) {
4546 i--;
4547 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004548 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004549 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4550 if (r.app == app) {
4551 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004552 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004553 TAG, "Removing this entry! frozen=" + r.haveState
4554 + " finishing=" + r.finishing);
4555 mHistory.remove(i);
4556
4557 r.inHistory = false;
4558 mWindowManager.removeAppToken(r);
4559 if (VALIDATE_TOKENS) {
4560 mWindowManager.validateAppTokens(mHistory);
4561 }
4562 removeActivityUriPermissionsLocked(r);
4563
4564 } else {
4565 // We have the current state for this activity, so
4566 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004567 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 TAG, "Keeping entry, setting app to null");
4569 if (r.visible) {
4570 hasVisibleActivities = true;
4571 }
4572 r.app = null;
4573 r.nowVisible = false;
4574 if (!r.haveState) {
4575 r.icicle = null;
4576 }
4577 }
4578
4579 cleanUpActivityLocked(r, true);
4580 r.state = ActivityState.STOPPED;
4581 }
4582 atTop = false;
4583 }
4584
4585 app.activities.clear();
4586
4587 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004588 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004589 + " running instrumentation " + app.instrumentationClass);
4590 Bundle info = new Bundle();
4591 info.putString("shortMsg", "Process crashed.");
4592 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4593 }
4594
4595 if (!restarting) {
4596 if (!resumeTopActivityLocked(null)) {
4597 // If there was nothing to resume, and we are not already
4598 // restarting this process, but there is a visible activity that
4599 // is hosted by the process... then make sure all visible
4600 // activities are running, taking care of restarting this
4601 // process.
4602 if (hasVisibleActivities) {
4603 ensureActivitiesVisibleLocked(null, 0);
4604 }
4605 }
4606 }
4607 }
4608
4609 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4610 IBinder threadBinder = thread.asBinder();
4611
4612 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004613 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4614 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004615 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4616 return i;
4617 }
4618 }
4619 return -1;
4620 }
4621
4622 private final ProcessRecord getRecordForAppLocked(
4623 IApplicationThread thread) {
4624 if (thread == null) {
4625 return null;
4626 }
4627
4628 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004629 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630 }
4631
4632 private final void appDiedLocked(ProcessRecord app, int pid,
4633 IApplicationThread thread) {
4634
4635 mProcDeaths[0]++;
4636
Magnus Edlund7bb25812010-02-24 15:45:06 +01004637 // Clean up already done if the process has been re-started.
4638 if (app.pid == pid && app.thread != null &&
4639 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004640 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004642 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004643 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 TAG, "Dying app: " + app + ", pid: " + pid
4645 + ", thread: " + thread.asBinder());
4646 boolean doLowMem = app.instrumentationClass == null;
4647 handleAppDiedLocked(app, false);
4648
4649 if (doLowMem) {
4650 // If there are no longer any background processes running,
4651 // and the app that died was not running instrumentation,
4652 // then tell everyone we are now low on memory.
4653 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004654 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4655 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4657 haveBg = true;
4658 break;
4659 }
4660 }
4661
4662 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004663 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004664 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004665 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004666 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4667 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004668 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004669 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4670 // The low memory report is overriding any current
4671 // state for a GC request. Make sure to do
4672 // visible/foreground processes first.
4673 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4674 rec.lastRequestedGc = 0;
4675 } else {
4676 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004677 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004678 rec.reportLowMemory = true;
4679 rec.lastLowMemory = now;
4680 mProcessesToGc.remove(rec);
4681 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004682 }
4683 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004684 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004685 }
4686 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004687 } else if (app.pid != pid) {
4688 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004689 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004690 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004691 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004692 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004693 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 + thread.asBinder());
4695 }
4696 }
4697
Dan Egnor42471dd2010-01-07 17:25:22 -08004698 /**
4699 * If a stack trace dump file is configured, dump process stack traces.
4700 * @param pids of dalvik VM processes to dump stack traces for
4701 * @return file containing stack traces, or null if no dump file is configured
4702 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004703 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004704 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4705 if (tracesPath == null || tracesPath.length() == 0) {
4706 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004708
4709 File tracesFile = new File(tracesPath);
4710 try {
4711 File tracesDir = tracesFile.getParentFile();
4712 if (!tracesDir.exists()) tracesFile.mkdirs();
4713 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4714
4715 if (tracesFile.exists()) tracesFile.delete();
4716 tracesFile.createNewFile();
4717 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4718 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004719 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004720 return null;
4721 }
4722
4723 // Use a FileObserver to detect when traces finish writing.
4724 // The order of traces is considered important to maintain for legibility.
4725 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4726 public synchronized void onEvent(int event, String path) { notify(); }
4727 };
4728
4729 try {
4730 observer.startWatching();
4731 int num = pids.size();
4732 for (int i = 0; i < num; i++) {
4733 synchronized (observer) {
4734 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4735 observer.wait(200); // Wait for write-close, give up after 200msec
4736 }
4737 }
4738 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004739 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004740 } finally {
4741 observer.stopWatching();
4742 }
4743
4744 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 }
4746
Dan Egnor42471dd2010-01-07 17:25:22 -08004747 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4748 HistoryRecord parent, final String annotation) {
Mike Lockwoodb62f9592010-03-12 07:55:23 -05004749 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4750 if (mShuttingDown || app.notResponding || app.crashing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004751 return;
4752 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004755 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4756 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757
Dan Egnor42471dd2010-01-07 17:25:22 -08004758 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4759 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4760 pids.add(app.pid);
4761
4762 int parentPid = app.pid;
4763 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4764 if (parentPid != app.pid) pids.add(parentPid);
4765
4766 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4767
4768 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4769 ProcessRecord r = mLruProcesses.get(i);
4770 if (r != null && r.thread != null) {
4771 int pid = r.pid;
4772 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 }
4774 }
4775
Dan Egnor42471dd2010-01-07 17:25:22 -08004776 File tracesFile = dumpStackTraces(pids);
4777
4778 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004779 StringBuilder info = mStringBuilder;
4780 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004781 info.append("ANR in ").append(app.processName);
4782 if (activity != null && activity.shortComponentName != null) {
4783 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004784 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004785 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004786 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004787 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004789 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004790 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792
Dan Egnor42471dd2010-01-07 17:25:22 -08004793 String cpuInfo = null;
4794 if (MONITOR_CPU_USAGE) {
4795 updateCpuStatsNow();
4796 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4797 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004798 }
4799
Joe Onorato8a9b2202010-02-26 18:56:32 -08004800 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004801 if (tracesFile == null) {
4802 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4803 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4804 }
4805
4806 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4807
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004808 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004810 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4811 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004812 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004813 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4814 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 }
4816 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004817 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004818 }
4819 }
4820
Dan Egnor42471dd2010-01-07 17:25:22 -08004821 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4822 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4823 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4824 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4825 Process.killProcess(app.pid);
4826 return;
4827 }
4828
4829 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 makeAppNotRespondingLocked(app,
4831 activity != null ? activity.shortComponentName : null,
4832 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004833 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004834
4835 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004836 Message msg = Message.obtain();
4837 HashMap map = new HashMap();
4838 msg.what = SHOW_NOT_RESPONDING_MSG;
4839 msg.obj = map;
4840 map.put("app", app);
4841 if (activity != null) {
4842 map.put("activity", activity);
4843 }
4844
4845 mHandler.sendMessage(msg);
4846 return;
4847 }
4848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004849 private final void decPersistentCountLocked(ProcessRecord app)
4850 {
4851 app.persistentActivities--;
4852 if (app.persistentActivities > 0) {
4853 // Still more of 'em...
4854 return;
4855 }
4856 if (app.persistent) {
4857 // Ah, but the application itself is persistent. Whatever!
4858 return;
4859 }
4860
4861 // App is no longer persistent... make sure it and the ones
4862 // following it in the LRU list have the correc oom_adj.
4863 updateOomAdjLocked();
4864 }
4865
4866 public void setPersistent(IBinder token, boolean isPersistent) {
4867 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4868 != PackageManager.PERMISSION_GRANTED) {
4869 String msg = "Permission Denial: setPersistent() from pid="
4870 + Binder.getCallingPid()
4871 + ", uid=" + Binder.getCallingUid()
4872 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004873 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 throw new SecurityException(msg);
4875 }
4876
4877 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004878 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 if (index < 0) {
4880 return;
4881 }
4882 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4883 ProcessRecord app = r.app;
4884
Joe Onorato8a9b2202010-02-26 18:56:32 -08004885 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 TAG, "Setting persistence " + isPersistent + ": " + r);
4887
4888 if (isPersistent) {
4889 if (r.persistent) {
4890 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004891 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892 return;
4893 }
4894 r.persistent = true;
4895 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004896 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004897 if (app.persistentActivities > 1) {
4898 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004899 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004900 return;
4901 }
4902 if (app.persistent) {
4903 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004904 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004905 return;
4906 }
4907
4908 // App is now persistent... make sure it and the ones
4909 // following it now have the correct oom_adj.
4910 final long origId = Binder.clearCallingIdentity();
4911 updateOomAdjLocked();
4912 Binder.restoreCallingIdentity(origId);
4913
4914 } else {
4915 if (!r.persistent) {
4916 // Okay okay, I heard you already!
4917 return;
4918 }
4919 r.persistent = false;
4920 final long origId = Binder.clearCallingIdentity();
4921 decPersistentCountLocked(app);
4922 Binder.restoreCallingIdentity(origId);
4923
4924 }
4925 }
4926 }
4927
4928 public boolean clearApplicationUserData(final String packageName,
4929 final IPackageDataObserver observer) {
4930 int uid = Binder.getCallingUid();
4931 int pid = Binder.getCallingPid();
4932 long callingId = Binder.clearCallingIdentity();
4933 try {
4934 IPackageManager pm = ActivityThread.getPackageManager();
4935 int pkgUid = -1;
4936 synchronized(this) {
4937 try {
4938 pkgUid = pm.getPackageUid(packageName);
4939 } catch (RemoteException e) {
4940 }
4941 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004942 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004943 return false;
4944 }
4945 if (uid == pkgUid || checkComponentPermission(
4946 android.Manifest.permission.CLEAR_APP_USER_DATA,
4947 pid, uid, -1)
4948 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004949 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950 } else {
4951 throw new SecurityException(pid+" does not have permission:"+
4952 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4953 "for process:"+packageName);
4954 }
4955 }
4956
4957 try {
4958 //clear application user data
4959 pm.clearApplicationUserData(packageName, observer);
4960 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4961 Uri.fromParts("package", packageName, null));
4962 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06004963 synchronized (this) {
4964 broadcastIntentLocked(null, null, intent,
4965 null, null, 0, null, null, null,
4966 false, false, MY_PID, Process.SYSTEM_UID);
4967 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004968 } catch (RemoteException e) {
4969 }
4970 } finally {
4971 Binder.restoreCallingIdentity(callingId);
4972 }
4973 return true;
4974 }
4975
Dianne Hackborn03abb812010-01-04 18:43:19 -08004976 public void killBackgroundProcesses(final String packageName) {
4977 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4978 != PackageManager.PERMISSION_GRANTED &&
4979 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4980 != PackageManager.PERMISSION_GRANTED) {
4981 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 + Binder.getCallingPid()
4983 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004984 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004985 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 throw new SecurityException(msg);
4987 }
4988
4989 long callingId = Binder.clearCallingIdentity();
4990 try {
4991 IPackageManager pm = ActivityThread.getPackageManager();
4992 int pkgUid = -1;
4993 synchronized(this) {
4994 try {
4995 pkgUid = pm.getPackageUid(packageName);
4996 } catch (RemoteException e) {
4997 }
4998 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004999 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 return;
5001 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005002 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005003 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005004 }
5005 } finally {
5006 Binder.restoreCallingIdentity(callingId);
5007 }
5008 }
5009
5010 public void forceStopPackage(final String packageName) {
5011 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5012 != PackageManager.PERMISSION_GRANTED) {
5013 String msg = "Permission Denial: forceStopPackage() from pid="
5014 + Binder.getCallingPid()
5015 + ", uid=" + Binder.getCallingUid()
5016 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005017 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005018 throw new SecurityException(msg);
5019 }
5020
5021 long callingId = Binder.clearCallingIdentity();
5022 try {
5023 IPackageManager pm = ActivityThread.getPackageManager();
5024 int pkgUid = -1;
5025 synchronized(this) {
5026 try {
5027 pkgUid = pm.getPackageUid(packageName);
5028 } catch (RemoteException e) {
5029 }
5030 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005031 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005032 return;
5033 }
5034 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005035 }
5036 } finally {
5037 Binder.restoreCallingIdentity(callingId);
5038 }
5039 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005040
5041 /*
5042 * The pkg name and uid have to be specified.
5043 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5044 */
5045 public void killApplicationWithUid(String pkg, int uid) {
5046 if (pkg == null) {
5047 return;
5048 }
5049 // Make sure the uid is valid.
5050 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005051 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005052 return;
5053 }
5054 int callerUid = Binder.getCallingUid();
5055 // Only the system server can kill an application
5056 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005057 // Post an aysnc message to kill the application
5058 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5059 msg.arg1 = uid;
5060 msg.arg2 = 0;
5061 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005062 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005063 } else {
5064 throw new SecurityException(callerUid + " cannot kill pkg: " +
5065 pkg);
5066 }
5067 }
5068
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005069 public void closeSystemDialogs(String reason) {
5070 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5071 if (reason != null) {
5072 intent.putExtra("reason", reason);
5073 }
5074
5075 final int uid = Binder.getCallingUid();
5076 final long origId = Binder.clearCallingIdentity();
5077 synchronized (this) {
5078 int i = mWatchers.beginBroadcast();
5079 while (i > 0) {
5080 i--;
5081 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5082 if (w != null) {
5083 try {
5084 w.closingSystemDialogs(reason);
5085 } catch (RemoteException e) {
5086 }
5087 }
5088 }
5089 mWatchers.finishBroadcast();
5090
Dianne Hackbornffa42482009-09-23 22:20:11 -07005091 mWindowManager.closeSystemDialogs(reason);
5092
5093 for (i=mHistory.size()-1; i>=0; i--) {
5094 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5095 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5096 finishActivityLocked(r, i,
5097 Activity.RESULT_CANCELED, null, "close-sys");
5098 }
5099 }
5100
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005101 broadcastIntentLocked(null, null, intent, null,
5102 null, 0, null, null, null, false, false, -1, uid);
5103 }
5104 Binder.restoreCallingIdentity(origId);
5105 }
5106
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005107 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005108 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005109 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5110 for (int i=pids.length-1; i>=0; i--) {
5111 infos[i] = new Debug.MemoryInfo();
5112 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005113 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005114 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005115 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005116
5117 public void killApplicationProcess(String processName, int uid) {
5118 if (processName == null) {
5119 return;
5120 }
5121
5122 int callerUid = Binder.getCallingUid();
5123 // Only the system server can kill an application
5124 if (callerUid == Process.SYSTEM_UID) {
5125 synchronized (this) {
5126 ProcessRecord app = getProcessRecordLocked(processName, uid);
5127 if (app != null) {
5128 try {
5129 app.thread.scheduleSuicide();
5130 } catch (RemoteException e) {
5131 // If the other end already died, then our work here is done.
5132 }
5133 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005134 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005135 + processName + " / " + uid);
5136 }
5137 }
5138 } else {
5139 throw new SecurityException(callerUid + " cannot kill app process: " +
5140 processName);
5141 }
5142 }
5143
Dianne Hackborn03abb812010-01-04 18:43:19 -08005144 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005145 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5147 Uri.fromParts("package", packageName, null));
5148 intent.putExtra(Intent.EXTRA_UID, uid);
5149 broadcastIntentLocked(null, null, intent,
5150 null, null, 0, null, null, null,
5151 false, false, MY_PID, Process.SYSTEM_UID);
5152 }
5153
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005154 private final boolean killPackageProcessesLocked(String packageName, int uid,
5155 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005156 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005157
Dianne Hackborn03abb812010-01-04 18:43:19 -08005158 // Remove all processes this package may have touched: all with the
5159 // same UID (except for the system or root user), and all whose name
5160 // matches the package name.
5161 final String procNamePrefix = packageName + ":";
5162 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5163 final int NA = apps.size();
5164 for (int ia=0; ia<NA; ia++) {
5165 ProcessRecord app = apps.valueAt(ia);
5166 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005167 if (doit) {
5168 procs.add(app);
5169 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005170 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5171 || app.processName.equals(packageName)
5172 || app.processName.startsWith(procNamePrefix)) {
5173 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005174 if (!doit) {
5175 return true;
5176 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005177 app.removed = true;
5178 procs.add(app);
5179 }
5180 }
5181 }
5182 }
5183
5184 int N = procs.size();
5185 for (int i=0; i<N; i++) {
5186 removeProcessLocked(procs.get(i), callerWillRestart);
5187 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005188 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005189 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005190
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005191 private final boolean forceStopPackageLocked(String name, int uid,
5192 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193 int i, N;
5194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 if (uid < 0) {
5196 try {
5197 uid = ActivityThread.getPackageManager().getPackageUid(name);
5198 } catch (RemoteException e) {
5199 }
5200 }
5201
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005202 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005203 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005204
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005205 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5206 while (badApps.hasNext()) {
5207 SparseArray<Long> ba = badApps.next();
5208 if (ba.get(uid) != null) {
5209 badApps.remove();
5210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005211 }
5212 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005213
5214 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5215 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005216
5217 for (i=mHistory.size()-1; i>=0; i--) {
5218 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5219 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005220 if (!doit) {
5221 return true;
5222 }
5223 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005224 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 if (r.app != null) {
5226 r.app.removed = true;
5227 }
5228 r.app = null;
5229 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5230 }
5231 }
5232
5233 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5234 for (ServiceRecord service : mServices.values()) {
5235 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005236 if (!doit) {
5237 return true;
5238 }
5239 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005240 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005241 if (service.app != null) {
5242 service.app.removed = true;
5243 }
5244 service.app = null;
5245 services.add(service);
5246 }
5247 }
5248
5249 N = services.size();
5250 for (i=0; i<N; i++) {
5251 bringDownServiceLocked(services.get(i), true);
5252 }
5253
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005254 if (doit) {
5255 if (purgeCache) {
5256 AttributeCache ac = AttributeCache.instance();
5257 if (ac != null) {
5258 ac.removePackage(name);
5259 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005260 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005261 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005262 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005263
5264 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005265 }
5266
5267 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5268 final String name = app.processName;
5269 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005270 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 TAG, "Force removing process " + app + " (" + name
5272 + "/" + uid + ")");
5273
5274 mProcessNames.remove(name, uid);
5275 boolean needRestart = false;
5276 if (app.pid > 0 && app.pid != MY_PID) {
5277 int pid = app.pid;
5278 synchronized (mPidsSelfLocked) {
5279 mPidsSelfLocked.remove(pid);
5280 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5281 }
5282 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005283 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 Process.killProcess(pid);
5285
5286 if (app.persistent) {
5287 if (!callerWillRestart) {
5288 addAppLocked(app.info);
5289 } else {
5290 needRestart = true;
5291 }
5292 }
5293 } else {
5294 mRemovedProcesses.add(app);
5295 }
5296
5297 return needRestart;
5298 }
5299
5300 private final void processStartTimedOutLocked(ProcessRecord app) {
5301 final int pid = app.pid;
5302 boolean gone = false;
5303 synchronized (mPidsSelfLocked) {
5304 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5305 if (knownApp != null && knownApp.thread == null) {
5306 mPidsSelfLocked.remove(pid);
5307 gone = true;
5308 }
5309 }
5310
5311 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005312 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005313 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005314 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005315 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005316 // Take care of any launching providers waiting for this process.
5317 checkAppInLaunchingProvidersLocked(app, true);
5318 // Take care of any services that are waiting for the process.
5319 for (int i=0; i<mPendingServices.size(); i++) {
5320 ServiceRecord sr = mPendingServices.get(i);
5321 if (app.info.uid == sr.appInfo.uid
5322 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005323 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005324 mPendingServices.remove(i);
5325 i--;
5326 bringDownServiceLocked(sr, true);
5327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005329 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005330 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005331 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005332 try {
5333 IBackupManager bm = IBackupManager.Stub.asInterface(
5334 ServiceManager.getService(Context.BACKUP_SERVICE));
5335 bm.agentDisconnected(app.info.packageName);
5336 } catch (RemoteException e) {
5337 // Can't happen; the backup manager is local
5338 }
5339 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005340 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005341 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005342 mPendingBroadcast = null;
5343 scheduleBroadcastsLocked();
5344 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005346 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347 }
5348 }
5349
5350 private final boolean attachApplicationLocked(IApplicationThread thread,
5351 int pid) {
5352
5353 // Find the application record that is being attached... either via
5354 // the pid if we are running in multiple processes, or just pull the
5355 // next app record if we are emulating process with anonymous threads.
5356 ProcessRecord app;
5357 if (pid != MY_PID && pid >= 0) {
5358 synchronized (mPidsSelfLocked) {
5359 app = mPidsSelfLocked.get(pid);
5360 }
5361 } else if (mStartingProcesses.size() > 0) {
5362 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005363 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 } else {
5365 app = null;
5366 }
5367
5368 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005369 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005370 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005371 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005372 if (pid > 0 && pid != MY_PID) {
5373 Process.killProcess(pid);
5374 } else {
5375 try {
5376 thread.scheduleExit();
5377 } catch (Exception e) {
5378 // Ignore exceptions.
5379 }
5380 }
5381 return false;
5382 }
5383
5384 // If this application record is still attached to a previous
5385 // process, clean it up now.
5386 if (app.thread != null) {
5387 handleAppDiedLocked(app, true);
5388 }
5389
5390 // Tell the process all about itself.
5391
Joe Onorato8a9b2202010-02-26 18:56:32 -08005392 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005393 TAG, "Binding process pid " + pid + " to record " + app);
5394
5395 String processName = app.processName;
5396 try {
5397 thread.asBinder().linkToDeath(new AppDeathRecipient(
5398 app, pid, thread), 0);
5399 } catch (RemoteException e) {
5400 app.resetPackageList();
5401 startProcessLocked(app, "link fail", processName);
5402 return false;
5403 }
5404
Doug Zongker2bec3d42009-12-04 12:52:44 -08005405 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406
5407 app.thread = thread;
5408 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005409 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5410 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005411 app.forcingToForeground = null;
5412 app.foregroundServices = false;
5413 app.debugging = false;
5414
5415 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5416
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005417 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5418 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005419
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005420 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005421 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005422 }
5423
Joe Onorato8a9b2202010-02-26 18:56:32 -08005424 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005425 TAG, "New app record " + app
5426 + " thread=" + thread.asBinder() + " pid=" + pid);
5427 try {
5428 int testMode = IApplicationThread.DEBUG_OFF;
5429 if (mDebugApp != null && mDebugApp.equals(processName)) {
5430 testMode = mWaitForDebugger
5431 ? IApplicationThread.DEBUG_WAIT
5432 : IApplicationThread.DEBUG_ON;
5433 app.debugging = true;
5434 if (mDebugTransient) {
5435 mDebugApp = mOrigDebugApp;
5436 mWaitForDebugger = mOrigWaitForDebugger;
5437 }
5438 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005439
Christopher Tate181fafa2009-05-14 11:12:14 -07005440 // If the app is being launched for restore or full backup, set it up specially
5441 boolean isRestrictedBackupMode = false;
5442 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5443 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5444 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5445 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005446
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005447 ensurePackageDexOpt(app.instrumentationInfo != null
5448 ? app.instrumentationInfo.packageName
5449 : app.info.packageName);
5450 if (app.instrumentationClass != null) {
5451 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005452 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005453 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005454 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005455 thread.bindApplication(processName, app.instrumentationInfo != null
5456 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005457 app.instrumentationClass, app.instrumentationProfileFile,
5458 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005459 isRestrictedBackupMode || !normalMode,
5460 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005461 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005462 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 } catch (Exception e) {
5464 // todo: Yikes! What should we do? For now we will try to
5465 // start another process, but that could easily get us in
5466 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005467 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005468
5469 app.resetPackageList();
5470 startProcessLocked(app, "bind fail", processName);
5471 return false;
5472 }
5473
5474 // Remove this record from the list of starting applications.
5475 mPersistentStartingProcesses.remove(app);
5476 mProcessesOnHold.remove(app);
5477
5478 boolean badApp = false;
5479 boolean didSomething = false;
5480
5481 // See if the top visible activity is waiting to run in this process...
5482 HistoryRecord hr = topRunningActivityLocked(null);
5483 if (hr != null) {
5484 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5485 && processName.equals(hr.processName)) {
5486 try {
5487 if (realStartActivityLocked(hr, app, true, true)) {
5488 didSomething = true;
5489 }
5490 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005491 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492 + hr.intent.getComponent().flattenToShortString(), e);
5493 badApp = true;
5494 }
5495 } else {
5496 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5497 }
5498 }
5499
5500 // Find any services that should be running in this process...
5501 if (!badApp && mPendingServices.size() > 0) {
5502 ServiceRecord sr = null;
5503 try {
5504 for (int i=0; i<mPendingServices.size(); i++) {
5505 sr = mPendingServices.get(i);
5506 if (app.info.uid != sr.appInfo.uid
5507 || !processName.equals(sr.processName)) {
5508 continue;
5509 }
5510
5511 mPendingServices.remove(i);
5512 i--;
5513 realStartServiceLocked(sr, app);
5514 didSomething = true;
5515 }
5516 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005517 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 + sr.shortName, e);
5519 badApp = true;
5520 }
5521 }
5522
5523 // Check if the next broadcast receiver is in this process...
5524 BroadcastRecord br = mPendingBroadcast;
5525 if (!badApp && br != null && br.curApp == app) {
5526 try {
5527 mPendingBroadcast = null;
5528 processCurBroadcastLocked(br, app);
5529 didSomething = true;
5530 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005531 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005532 + br.curComponent.flattenToShortString(), e);
5533 badApp = true;
5534 logBroadcastReceiverDiscard(br);
5535 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5536 br.resultExtras, br.resultAbort, true);
5537 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005538 // We need to reset the state if we fails to start the receiver.
5539 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005540 }
5541 }
5542
Christopher Tate181fafa2009-05-14 11:12:14 -07005543 // Check whether the next backup agent is in this process...
5544 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005545 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005546 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005547 try {
5548 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5549 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005550 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005551 e.printStackTrace();
5552 }
5553 }
5554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005555 if (badApp) {
5556 // todo: Also need to kill application to deal with all
5557 // kinds of exceptions.
5558 handleAppDiedLocked(app, false);
5559 return false;
5560 }
5561
5562 if (!didSomething) {
5563 updateOomAdjLocked();
5564 }
5565
5566 return true;
5567 }
5568
5569 public final void attachApplication(IApplicationThread thread) {
5570 synchronized (this) {
5571 int callingPid = Binder.getCallingPid();
5572 final long origId = Binder.clearCallingIdentity();
5573 attachApplicationLocked(thread, callingPid);
5574 Binder.restoreCallingIdentity(origId);
5575 }
5576 }
5577
Dianne Hackborne88846e2009-09-30 21:34:25 -07005578 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005580 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 Binder.restoreCallingIdentity(origId);
5582 }
5583
5584 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5585 boolean remove) {
5586 int N = mStoppingActivities.size();
5587 if (N <= 0) return null;
5588
5589 ArrayList<HistoryRecord> stops = null;
5590
5591 final boolean nowVisible = mResumedActivity != null
5592 && mResumedActivity.nowVisible
5593 && !mResumedActivity.waitingVisible;
5594 for (int i=0; i<N; i++) {
5595 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005596 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 + nowVisible + " waitingVisible=" + s.waitingVisible
5598 + " finishing=" + s.finishing);
5599 if (s.waitingVisible && nowVisible) {
5600 mWaitingVisibleActivities.remove(s);
5601 s.waitingVisible = false;
5602 if (s.finishing) {
5603 // If this activity is finishing, it is sitting on top of
5604 // everyone else but we now know it is no longer needed...
5605 // so get rid of it. Otherwise, we need to go through the
5606 // normal flow and hide it once we determine that it is
5607 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005608 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005609 mWindowManager.setAppVisibility(s, false);
5610 }
5611 }
5612 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005613 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005614 if (stops == null) {
5615 stops = new ArrayList<HistoryRecord>();
5616 }
5617 stops.add(s);
5618 mStoppingActivities.remove(i);
5619 N--;
5620 i--;
5621 }
5622 }
5623
5624 return stops;
5625 }
5626
5627 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005628 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005629 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 mWindowManager.enableScreenAfterBoot();
5631 }
5632
Dianne Hackborne88846e2009-09-30 21:34:25 -07005633 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5634 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005635 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636
5637 ArrayList<HistoryRecord> stops = null;
5638 ArrayList<HistoryRecord> finishes = null;
5639 ArrayList<HistoryRecord> thumbnails = null;
5640 int NS = 0;
5641 int NF = 0;
5642 int NT = 0;
5643 IApplicationThread sendThumbnail = null;
5644 boolean booting = false;
5645 boolean enableScreen = false;
5646
5647 synchronized (this) {
5648 if (token != null) {
5649 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5650 }
5651
5652 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005653 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005654 if (index >= 0) {
5655 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5656
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005657 if (fromTimeout) {
5658 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5659 }
5660
Dianne Hackborne88846e2009-09-30 21:34:25 -07005661 // This is a hack to semi-deal with a race condition
5662 // in the client where it can be constructed with a
5663 // newer configuration from when we asked it to launch.
5664 // We'll update with whatever configuration it now says
5665 // it used to launch.
5666 if (config != null) {
5667 r.configuration = config;
5668 }
5669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005670 // No longer need to keep the device awake.
5671 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5672 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5673 mLaunchingActivity.release();
5674 }
5675
5676 // We are now idle. If someone is waiting for a thumbnail from
5677 // us, we can now deliver.
5678 r.idle = true;
5679 scheduleAppGcsLocked();
5680 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5681 sendThumbnail = r.app.thread;
5682 r.thumbnailNeeded = false;
5683 }
5684
5685 // If this activity is fullscreen, set up to hide those under it.
5686
Joe Onorato8a9b2202010-02-26 18:56:32 -08005687 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005688 ensureActivitiesVisibleLocked(null, 0);
5689
Joe Onorato8a9b2202010-02-26 18:56:32 -08005690 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005691 if (!mBooted && !fromTimeout) {
5692 mBooted = true;
5693 enableScreen = true;
5694 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005695
5696 } else if (fromTimeout) {
5697 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005698 }
5699
5700 // Atomically retrieve all of the other things to do.
5701 stops = processStoppingActivitiesLocked(true);
5702 NS = stops != null ? stops.size() : 0;
5703 if ((NF=mFinishingActivities.size()) > 0) {
5704 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5705 mFinishingActivities.clear();
5706 }
5707 if ((NT=mCancelledThumbnails.size()) > 0) {
5708 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5709 mCancelledThumbnails.clear();
5710 }
5711
5712 booting = mBooting;
5713 mBooting = false;
5714 }
5715
5716 int i;
5717
5718 // Send thumbnail if requested.
5719 if (sendThumbnail != null) {
5720 try {
5721 sendThumbnail.requestThumbnail(token);
5722 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005723 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 sendPendingThumbnail(null, token, null, null, true);
5725 }
5726 }
5727
5728 // Stop any activities that are scheduled to do so but have been
5729 // waiting for the next one to start.
5730 for (i=0; i<NS; i++) {
5731 HistoryRecord r = (HistoryRecord)stops.get(i);
5732 synchronized (this) {
5733 if (r.finishing) {
5734 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5735 } else {
5736 stopActivityLocked(r);
5737 }
5738 }
5739 }
5740
5741 // Finish any activities that are scheduled to do so but have been
5742 // waiting for the next one to start.
5743 for (i=0; i<NF; i++) {
5744 HistoryRecord r = (HistoryRecord)finishes.get(i);
5745 synchronized (this) {
5746 destroyActivityLocked(r, true);
5747 }
5748 }
5749
5750 // Report back to any thumbnail receivers.
5751 for (i=0; i<NT; i++) {
5752 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5753 sendPendingThumbnail(r, null, null, null, true);
5754 }
5755
5756 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005757 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 }
5759
5760 trimApplications();
5761 //dump();
5762 //mWindowManager.dump();
5763
5764 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 enableScreenAfterBoot();
5766 }
5767 }
5768
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005769 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005770 IntentFilter pkgFilter = new IntentFilter();
5771 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5772 pkgFilter.addDataScheme("package");
5773 mContext.registerReceiver(new BroadcastReceiver() {
5774 @Override
5775 public void onReceive(Context context, Intent intent) {
5776 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5777 if (pkgs != null) {
5778 for (String pkg : pkgs) {
5779 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5780 setResultCode(Activity.RESULT_OK);
5781 return;
5782 }
5783 }
5784 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005785 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005786 }, pkgFilter);
5787
5788 synchronized (this) {
5789 // Ensure that any processes we had put on hold are now started
5790 // up.
5791 final int NP = mProcessesOnHold.size();
5792 if (NP > 0) {
5793 ArrayList<ProcessRecord> procs =
5794 new ArrayList<ProcessRecord>(mProcessesOnHold);
5795 for (int ip=0; ip<NP; ip++) {
5796 this.startProcessLocked(procs.get(ip), "on-hold", null);
5797 }
5798 }
5799
5800 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5801 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005802 broadcastIntentLocked(null, null,
5803 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5804 null, null, 0, null, null,
5805 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5806 false, false, MY_PID, Process.SYSTEM_UID);
5807 }
5808 }
5809 }
5810
5811 final void ensureBootCompleted() {
5812 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005813 boolean enableScreen;
5814 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005815 booting = mBooting;
5816 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005817 enableScreen = !mBooted;
5818 mBooted = true;
5819 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005820
5821 if (booting) {
5822 finishBooting();
5823 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005824
5825 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005826 enableScreenAfterBoot();
5827 }
5828 }
5829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 public final void activityPaused(IBinder token, Bundle icicle) {
5831 // Refuse possible leaked file descriptors
5832 if (icicle != null && icicle.hasFileDescriptors()) {
5833 throw new IllegalArgumentException("File descriptors passed in Bundle");
5834 }
5835
5836 final long origId = Binder.clearCallingIdentity();
5837 activityPaused(token, icicle, false);
5838 Binder.restoreCallingIdentity(origId);
5839 }
5840
5841 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005842 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5844 + ", timeout=" + timeout);
5845
5846 HistoryRecord r = null;
5847
5848 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005849 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005850 if (index >= 0) {
5851 r = (HistoryRecord)mHistory.get(index);
5852 if (!timeout) {
5853 r.icicle = icicle;
5854 r.haveState = true;
5855 }
5856 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5857 if (mPausingActivity == r) {
5858 r.state = ActivityState.PAUSED;
5859 completePauseLocked();
5860 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005861 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 System.identityHashCode(r), r.shortComponentName,
5863 mPausingActivity != null
5864 ? mPausingActivity.shortComponentName : "(none)");
5865 }
5866 }
5867 }
5868 }
5869
5870 public final void activityStopped(IBinder token, Bitmap thumbnail,
5871 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005872 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005873 TAG, "Activity stopped: token=" + token);
5874
5875 HistoryRecord r = null;
5876
5877 final long origId = Binder.clearCallingIdentity();
5878
5879 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005880 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 if (index >= 0) {
5882 r = (HistoryRecord)mHistory.get(index);
5883 r.thumbnail = thumbnail;
5884 r.description = description;
5885 r.stopped = true;
5886 r.state = ActivityState.STOPPED;
5887 if (!r.finishing) {
5888 if (r.configDestroy) {
5889 destroyActivityLocked(r, true);
5890 resumeTopActivityLocked(null);
5891 }
5892 }
5893 }
5894 }
5895
5896 if (r != null) {
5897 sendPendingThumbnail(r, null, null, null, false);
5898 }
5899
5900 trimApplications();
5901
5902 Binder.restoreCallingIdentity(origId);
5903 }
5904
5905 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005906 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 synchronized (this) {
5908 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5909
Dianne Hackborn75b03852009-06-12 15:43:26 -07005910 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005911 if (index >= 0) {
5912 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5913 if (r.state == ActivityState.DESTROYING) {
5914 final long origId = Binder.clearCallingIdentity();
5915 removeActivityFromHistoryLocked(r);
5916 Binder.restoreCallingIdentity(origId);
5917 }
5918 }
5919 }
5920 }
5921
5922 public String getCallingPackage(IBinder token) {
5923 synchronized (this) {
5924 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005925 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005926 }
5927 }
5928
5929 public ComponentName getCallingActivity(IBinder token) {
5930 synchronized (this) {
5931 HistoryRecord r = getCallingRecordLocked(token);
5932 return r != null ? r.intent.getComponent() : null;
5933 }
5934 }
5935
5936 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005937 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 if (index >= 0) {
5939 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5940 if (r != null) {
5941 return r.resultTo;
5942 }
5943 }
5944 return null;
5945 }
5946
5947 public ComponentName getActivityClassForToken(IBinder token) {
5948 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005949 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005950 if (index >= 0) {
5951 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5952 return r.intent.getComponent();
5953 }
5954 return null;
5955 }
5956 }
5957
5958 public String getPackageForToken(IBinder token) {
5959 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005960 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005961 if (index >= 0) {
5962 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5963 return r.packageName;
5964 }
5965 return null;
5966 }
5967 }
5968
5969 public IIntentSender getIntentSender(int type,
5970 String packageName, IBinder token, String resultWho,
5971 int requestCode, Intent intent, String resolvedType, int flags) {
5972 // Refuse possible leaked file descriptors
5973 if (intent != null && intent.hasFileDescriptors() == true) {
5974 throw new IllegalArgumentException("File descriptors passed in Intent");
5975 }
5976
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005977 if (type == INTENT_SENDER_BROADCAST) {
5978 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5979 throw new IllegalArgumentException(
5980 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5981 }
5982 }
5983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 synchronized(this) {
5985 int callingUid = Binder.getCallingUid();
5986 try {
5987 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5988 Process.supportsProcesses()) {
5989 int uid = ActivityThread.getPackageManager()
5990 .getPackageUid(packageName);
5991 if (uid != Binder.getCallingUid()) {
5992 String msg = "Permission Denial: getIntentSender() from pid="
5993 + Binder.getCallingPid()
5994 + ", uid=" + Binder.getCallingUid()
5995 + ", (need uid=" + uid + ")"
5996 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005997 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005998 throw new SecurityException(msg);
5999 }
6000 }
6001 } catch (RemoteException e) {
6002 throw new SecurityException(e);
6003 }
6004 HistoryRecord activity = null;
6005 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006006 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006007 if (index < 0) {
6008 return null;
6009 }
6010 activity = (HistoryRecord)mHistory.get(index);
6011 if (activity.finishing) {
6012 return null;
6013 }
6014 }
6015
6016 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6017 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6018 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6019 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6020 |PendingIntent.FLAG_UPDATE_CURRENT);
6021
6022 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6023 type, packageName, activity, resultWho,
6024 requestCode, intent, resolvedType, flags);
6025 WeakReference<PendingIntentRecord> ref;
6026 ref = mIntentSenderRecords.get(key);
6027 PendingIntentRecord rec = ref != null ? ref.get() : null;
6028 if (rec != null) {
6029 if (!cancelCurrent) {
6030 if (updateCurrent) {
6031 rec.key.requestIntent.replaceExtras(intent);
6032 }
6033 return rec;
6034 }
6035 rec.canceled = true;
6036 mIntentSenderRecords.remove(key);
6037 }
6038 if (noCreate) {
6039 return rec;
6040 }
6041 rec = new PendingIntentRecord(this, key, callingUid);
6042 mIntentSenderRecords.put(key, rec.ref);
6043 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6044 if (activity.pendingResults == null) {
6045 activity.pendingResults
6046 = new HashSet<WeakReference<PendingIntentRecord>>();
6047 }
6048 activity.pendingResults.add(rec.ref);
6049 }
6050 return rec;
6051 }
6052 }
6053
6054 public void cancelIntentSender(IIntentSender sender) {
6055 if (!(sender instanceof PendingIntentRecord)) {
6056 return;
6057 }
6058 synchronized(this) {
6059 PendingIntentRecord rec = (PendingIntentRecord)sender;
6060 try {
6061 int uid = ActivityThread.getPackageManager()
6062 .getPackageUid(rec.key.packageName);
6063 if (uid != Binder.getCallingUid()) {
6064 String msg = "Permission Denial: cancelIntentSender() from pid="
6065 + Binder.getCallingPid()
6066 + ", uid=" + Binder.getCallingUid()
6067 + " is not allowed to cancel packges "
6068 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006069 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006070 throw new SecurityException(msg);
6071 }
6072 } catch (RemoteException e) {
6073 throw new SecurityException(e);
6074 }
6075 cancelIntentSenderLocked(rec, true);
6076 }
6077 }
6078
6079 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6080 rec.canceled = true;
6081 mIntentSenderRecords.remove(rec.key);
6082 if (cleanActivity && rec.key.activity != null) {
6083 rec.key.activity.pendingResults.remove(rec.ref);
6084 }
6085 }
6086
6087 public String getPackageForIntentSender(IIntentSender pendingResult) {
6088 if (!(pendingResult instanceof PendingIntentRecord)) {
6089 return null;
6090 }
6091 synchronized(this) {
6092 try {
6093 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6094 return res.key.packageName;
6095 } catch (ClassCastException e) {
6096 }
6097 }
6098 return null;
6099 }
6100
6101 public void setProcessLimit(int max) {
6102 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6103 "setProcessLimit()");
6104 mProcessLimit = max;
6105 }
6106
6107 public int getProcessLimit() {
6108 return mProcessLimit;
6109 }
6110
6111 void foregroundTokenDied(ForegroundToken token) {
6112 synchronized (ActivityManagerService.this) {
6113 synchronized (mPidsSelfLocked) {
6114 ForegroundToken cur
6115 = mForegroundProcesses.get(token.pid);
6116 if (cur != token) {
6117 return;
6118 }
6119 mForegroundProcesses.remove(token.pid);
6120 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6121 if (pr == null) {
6122 return;
6123 }
6124 pr.forcingToForeground = null;
6125 pr.foregroundServices = false;
6126 }
6127 updateOomAdjLocked();
6128 }
6129 }
6130
6131 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6132 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6133 "setProcessForeground()");
6134 synchronized(this) {
6135 boolean changed = false;
6136
6137 synchronized (mPidsSelfLocked) {
6138 ProcessRecord pr = mPidsSelfLocked.get(pid);
6139 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006140 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006141 return;
6142 }
6143 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6144 if (oldToken != null) {
6145 oldToken.token.unlinkToDeath(oldToken, 0);
6146 mForegroundProcesses.remove(pid);
6147 pr.forcingToForeground = null;
6148 changed = true;
6149 }
6150 if (isForeground && token != null) {
6151 ForegroundToken newToken = new ForegroundToken() {
6152 public void binderDied() {
6153 foregroundTokenDied(this);
6154 }
6155 };
6156 newToken.pid = pid;
6157 newToken.token = token;
6158 try {
6159 token.linkToDeath(newToken, 0);
6160 mForegroundProcesses.put(pid, newToken);
6161 pr.forcingToForeground = token;
6162 changed = true;
6163 } catch (RemoteException e) {
6164 // If the process died while doing this, we will later
6165 // do the cleanup with the process death link.
6166 }
6167 }
6168 }
6169
6170 if (changed) {
6171 updateOomAdjLocked();
6172 }
6173 }
6174 }
6175
6176 // =========================================================
6177 // PERMISSIONS
6178 // =========================================================
6179
6180 static class PermissionController extends IPermissionController.Stub {
6181 ActivityManagerService mActivityManagerService;
6182 PermissionController(ActivityManagerService activityManagerService) {
6183 mActivityManagerService = activityManagerService;
6184 }
6185
6186 public boolean checkPermission(String permission, int pid, int uid) {
6187 return mActivityManagerService.checkPermission(permission, pid,
6188 uid) == PackageManager.PERMISSION_GRANTED;
6189 }
6190 }
6191
6192 /**
6193 * This can be called with or without the global lock held.
6194 */
6195 int checkComponentPermission(String permission, int pid, int uid,
6196 int reqUid) {
6197 // We might be performing an operation on behalf of an indirect binder
6198 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6199 // client identity accordingly before proceeding.
6200 Identity tlsIdentity = sCallerIdentity.get();
6201 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006202 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006203 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6204 uid = tlsIdentity.uid;
6205 pid = tlsIdentity.pid;
6206 }
6207
6208 // Root, system server and our own process get to do everything.
6209 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6210 !Process.supportsProcesses()) {
6211 return PackageManager.PERMISSION_GRANTED;
6212 }
6213 // If the target requires a specific UID, always fail for others.
6214 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006215 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006216 return PackageManager.PERMISSION_DENIED;
6217 }
6218 if (permission == null) {
6219 return PackageManager.PERMISSION_GRANTED;
6220 }
6221 try {
6222 return ActivityThread.getPackageManager()
6223 .checkUidPermission(permission, uid);
6224 } catch (RemoteException e) {
6225 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006226 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006227 }
6228 return PackageManager.PERMISSION_DENIED;
6229 }
6230
6231 /**
6232 * As the only public entry point for permissions checking, this method
6233 * can enforce the semantic that requesting a check on a null global
6234 * permission is automatically denied. (Internally a null permission
6235 * string is used when calling {@link #checkComponentPermission} in cases
6236 * when only uid-based security is needed.)
6237 *
6238 * This can be called with or without the global lock held.
6239 */
6240 public int checkPermission(String permission, int pid, int uid) {
6241 if (permission == null) {
6242 return PackageManager.PERMISSION_DENIED;
6243 }
6244 return checkComponentPermission(permission, pid, uid, -1);
6245 }
6246
6247 /**
6248 * Binder IPC calls go through the public entry point.
6249 * This can be called with or without the global lock held.
6250 */
6251 int checkCallingPermission(String permission) {
6252 return checkPermission(permission,
6253 Binder.getCallingPid(),
6254 Binder.getCallingUid());
6255 }
6256
6257 /**
6258 * This can be called with or without the global lock held.
6259 */
6260 void enforceCallingPermission(String permission, String func) {
6261 if (checkCallingPermission(permission)
6262 == PackageManager.PERMISSION_GRANTED) {
6263 return;
6264 }
6265
6266 String msg = "Permission Denial: " + func + " from pid="
6267 + Binder.getCallingPid()
6268 + ", uid=" + Binder.getCallingUid()
6269 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006270 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006271 throw new SecurityException(msg);
6272 }
6273
6274 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6275 ProviderInfo pi, int uid, int modeFlags) {
6276 try {
6277 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6278 if ((pi.readPermission != null) &&
6279 (pm.checkUidPermission(pi.readPermission, uid)
6280 != PackageManager.PERMISSION_GRANTED)) {
6281 return false;
6282 }
6283 }
6284 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6285 if ((pi.writePermission != null) &&
6286 (pm.checkUidPermission(pi.writePermission, uid)
6287 != PackageManager.PERMISSION_GRANTED)) {
6288 return false;
6289 }
6290 }
6291 return true;
6292 } catch (RemoteException e) {
6293 return false;
6294 }
6295 }
6296
6297 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6298 int modeFlags) {
6299 // Root gets to do everything.
6300 if (uid == 0 || !Process.supportsProcesses()) {
6301 return true;
6302 }
6303 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6304 if (perms == null) return false;
6305 UriPermission perm = perms.get(uri);
6306 if (perm == null) return false;
6307 return (modeFlags&perm.modeFlags) == modeFlags;
6308 }
6309
6310 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6311 // Another redirected-binder-call permissions check as in
6312 // {@link checkComponentPermission}.
6313 Identity tlsIdentity = sCallerIdentity.get();
6314 if (tlsIdentity != null) {
6315 uid = tlsIdentity.uid;
6316 pid = tlsIdentity.pid;
6317 }
6318
6319 // Our own process gets to do everything.
6320 if (pid == MY_PID) {
6321 return PackageManager.PERMISSION_GRANTED;
6322 }
6323 synchronized(this) {
6324 return checkUriPermissionLocked(uri, uid, modeFlags)
6325 ? PackageManager.PERMISSION_GRANTED
6326 : PackageManager.PERMISSION_DENIED;
6327 }
6328 }
6329
6330 private void grantUriPermissionLocked(int callingUid,
6331 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6332 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6333 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6334 if (modeFlags == 0) {
6335 return;
6336 }
6337
Joe Onorato8a9b2202010-02-26 18:56:32 -08006338 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006339 "Requested grant " + targetPkg + " permission to " + uri);
6340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006341 final IPackageManager pm = ActivityThread.getPackageManager();
6342
6343 // If this is not a content: uri, we can't do anything with it.
6344 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006345 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006346 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006347 return;
6348 }
6349
6350 String name = uri.getAuthority();
6351 ProviderInfo pi = null;
6352 ContentProviderRecord cpr
6353 = (ContentProviderRecord)mProvidersByName.get(name);
6354 if (cpr != null) {
6355 pi = cpr.info;
6356 } else {
6357 try {
6358 pi = pm.resolveContentProvider(name,
6359 PackageManager.GET_URI_PERMISSION_PATTERNS);
6360 } catch (RemoteException ex) {
6361 }
6362 }
6363 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006364 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 return;
6366 }
6367
6368 int targetUid;
6369 try {
6370 targetUid = pm.getPackageUid(targetPkg);
6371 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006372 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006373 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 return;
6375 }
6376 } catch (RemoteException ex) {
6377 return;
6378 }
6379
6380 // First... does the target actually need this permission?
6381 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6382 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006383 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006384 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006385 return;
6386 }
6387
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006388 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006389 if (!pi.grantUriPermissions) {
6390 throw new SecurityException("Provider " + pi.packageName
6391 + "/" + pi.name
6392 + " does not allow granting of Uri permissions (uri "
6393 + uri + ")");
6394 }
6395 if (pi.uriPermissionPatterns != null) {
6396 final int N = pi.uriPermissionPatterns.length;
6397 boolean allowed = false;
6398 for (int i=0; i<N; i++) {
6399 if (pi.uriPermissionPatterns[i] != null
6400 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6401 allowed = true;
6402 break;
6403 }
6404 }
6405 if (!allowed) {
6406 throw new SecurityException("Provider " + pi.packageName
6407 + "/" + pi.name
6408 + " does not allow granting of permission to path of Uri "
6409 + uri);
6410 }
6411 }
6412
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006413 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006414 // this uri?
6415 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6416 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6417 throw new SecurityException("Uid " + callingUid
6418 + " does not have permission to uri " + uri);
6419 }
6420 }
6421
6422 // Okay! So here we are: the caller has the assumed permission
6423 // to the uri, and the target doesn't. Let's now give this to
6424 // the target.
6425
Joe Onorato8a9b2202010-02-26 18:56:32 -08006426 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006427 "Granting " + targetPkg + " permission to " + uri);
6428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006429 HashMap<Uri, UriPermission> targetUris
6430 = mGrantedUriPermissions.get(targetUid);
6431 if (targetUris == null) {
6432 targetUris = new HashMap<Uri, UriPermission>();
6433 mGrantedUriPermissions.put(targetUid, targetUris);
6434 }
6435
6436 UriPermission perm = targetUris.get(uri);
6437 if (perm == null) {
6438 perm = new UriPermission(targetUid, uri);
6439 targetUris.put(uri, perm);
6440
6441 }
6442 perm.modeFlags |= modeFlags;
6443 if (activity == null) {
6444 perm.globalModeFlags |= modeFlags;
6445 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6446 perm.readActivities.add(activity);
6447 if (activity.readUriPermissions == null) {
6448 activity.readUriPermissions = new HashSet<UriPermission>();
6449 }
6450 activity.readUriPermissions.add(perm);
6451 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6452 perm.writeActivities.add(activity);
6453 if (activity.writeUriPermissions == null) {
6454 activity.writeUriPermissions = new HashSet<UriPermission>();
6455 }
6456 activity.writeUriPermissions.add(perm);
6457 }
6458 }
6459
6460 private void grantUriPermissionFromIntentLocked(int callingUid,
6461 String targetPkg, Intent intent, HistoryRecord activity) {
6462 if (intent == null) {
6463 return;
6464 }
6465 Uri data = intent.getData();
6466 if (data == null) {
6467 return;
6468 }
6469 grantUriPermissionLocked(callingUid, targetPkg, data,
6470 intent.getFlags(), activity);
6471 }
6472
6473 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6474 Uri uri, int modeFlags) {
6475 synchronized(this) {
6476 final ProcessRecord r = getRecordForAppLocked(caller);
6477 if (r == null) {
6478 throw new SecurityException("Unable to find app for caller "
6479 + caller
6480 + " when granting permission to uri " + uri);
6481 }
6482 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006483 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006484 return;
6485 }
6486 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006487 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006488 return;
6489 }
6490
6491 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6492 null);
6493 }
6494 }
6495
6496 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6497 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6498 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6499 HashMap<Uri, UriPermission> perms
6500 = mGrantedUriPermissions.get(perm.uid);
6501 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006502 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006503 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006504 perms.remove(perm.uri);
6505 if (perms.size() == 0) {
6506 mGrantedUriPermissions.remove(perm.uid);
6507 }
6508 }
6509 }
6510 }
6511
6512 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6513 if (activity.readUriPermissions != null) {
6514 for (UriPermission perm : activity.readUriPermissions) {
6515 perm.readActivities.remove(activity);
6516 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6517 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6518 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6519 removeUriPermissionIfNeededLocked(perm);
6520 }
6521 }
6522 }
6523 if (activity.writeUriPermissions != null) {
6524 for (UriPermission perm : activity.writeUriPermissions) {
6525 perm.writeActivities.remove(activity);
6526 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6527 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6528 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6529 removeUriPermissionIfNeededLocked(perm);
6530 }
6531 }
6532 }
6533 }
6534
6535 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6536 int modeFlags) {
6537 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6538 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6539 if (modeFlags == 0) {
6540 return;
6541 }
6542
Joe Onorato8a9b2202010-02-26 18:56:32 -08006543 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006544 "Revoking all granted permissions to " + uri);
6545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006546 final IPackageManager pm = ActivityThread.getPackageManager();
6547
6548 final String authority = uri.getAuthority();
6549 ProviderInfo pi = null;
6550 ContentProviderRecord cpr
6551 = (ContentProviderRecord)mProvidersByName.get(authority);
6552 if (cpr != null) {
6553 pi = cpr.info;
6554 } else {
6555 try {
6556 pi = pm.resolveContentProvider(authority,
6557 PackageManager.GET_URI_PERMISSION_PATTERNS);
6558 } catch (RemoteException ex) {
6559 }
6560 }
6561 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006562 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006563 return;
6564 }
6565
6566 // Does the caller have this permission on the URI?
6567 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6568 // Right now, if you are not the original owner of the permission,
6569 // you are not allowed to revoke it.
6570 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6571 throw new SecurityException("Uid " + callingUid
6572 + " does not have permission to uri " + uri);
6573 //}
6574 }
6575
6576 // Go through all of the permissions and remove any that match.
6577 final List<String> SEGMENTS = uri.getPathSegments();
6578 if (SEGMENTS != null) {
6579 final int NS = SEGMENTS.size();
6580 int N = mGrantedUriPermissions.size();
6581 for (int i=0; i<N; i++) {
6582 HashMap<Uri, UriPermission> perms
6583 = mGrantedUriPermissions.valueAt(i);
6584 Iterator<UriPermission> it = perms.values().iterator();
6585 toploop:
6586 while (it.hasNext()) {
6587 UriPermission perm = it.next();
6588 Uri targetUri = perm.uri;
6589 if (!authority.equals(targetUri.getAuthority())) {
6590 continue;
6591 }
6592 List<String> targetSegments = targetUri.getPathSegments();
6593 if (targetSegments == null) {
6594 continue;
6595 }
6596 if (targetSegments.size() < NS) {
6597 continue;
6598 }
6599 for (int j=0; j<NS; j++) {
6600 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6601 continue toploop;
6602 }
6603 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006604 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006605 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006606 perm.clearModes(modeFlags);
6607 if (perm.modeFlags == 0) {
6608 it.remove();
6609 }
6610 }
6611 if (perms.size() == 0) {
6612 mGrantedUriPermissions.remove(
6613 mGrantedUriPermissions.keyAt(i));
6614 N--;
6615 i--;
6616 }
6617 }
6618 }
6619 }
6620
6621 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6622 int modeFlags) {
6623 synchronized(this) {
6624 final ProcessRecord r = getRecordForAppLocked(caller);
6625 if (r == null) {
6626 throw new SecurityException("Unable to find app for caller "
6627 + caller
6628 + " when revoking permission to uri " + uri);
6629 }
6630 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006631 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006632 return;
6633 }
6634
6635 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6636 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6637 if (modeFlags == 0) {
6638 return;
6639 }
6640
6641 final IPackageManager pm = ActivityThread.getPackageManager();
6642
6643 final String authority = uri.getAuthority();
6644 ProviderInfo pi = null;
6645 ContentProviderRecord cpr
6646 = (ContentProviderRecord)mProvidersByName.get(authority);
6647 if (cpr != null) {
6648 pi = cpr.info;
6649 } else {
6650 try {
6651 pi = pm.resolveContentProvider(authority,
6652 PackageManager.GET_URI_PERMISSION_PATTERNS);
6653 } catch (RemoteException ex) {
6654 }
6655 }
6656 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006657 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 return;
6659 }
6660
6661 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6662 }
6663 }
6664
6665 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6666 synchronized (this) {
6667 ProcessRecord app =
6668 who != null ? getRecordForAppLocked(who) : null;
6669 if (app == null) return;
6670
6671 Message msg = Message.obtain();
6672 msg.what = WAIT_FOR_DEBUGGER_MSG;
6673 msg.obj = app;
6674 msg.arg1 = waiting ? 1 : 0;
6675 mHandler.sendMessage(msg);
6676 }
6677 }
6678
6679 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6680 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006681 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006682 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006683 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006684 }
6685
6686 // =========================================================
6687 // TASK MANAGEMENT
6688 // =========================================================
6689
6690 public List getTasks(int maxNum, int flags,
6691 IThumbnailReceiver receiver) {
6692 ArrayList list = new ArrayList();
6693
6694 PendingThumbnailsRecord pending = null;
6695 IApplicationThread topThumbnail = null;
6696 HistoryRecord topRecord = null;
6697
6698 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006699 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006700 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6701 + ", receiver=" + receiver);
6702
6703 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6704 != PackageManager.PERMISSION_GRANTED) {
6705 if (receiver != null) {
6706 // If the caller wants to wait for pending thumbnails,
6707 // it ain't gonna get them.
6708 try {
6709 receiver.finished();
6710 } catch (RemoteException ex) {
6711 }
6712 }
6713 String msg = "Permission Denial: getTasks() from pid="
6714 + Binder.getCallingPid()
6715 + ", uid=" + Binder.getCallingUid()
6716 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006717 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006718 throw new SecurityException(msg);
6719 }
6720
6721 int pos = mHistory.size()-1;
6722 HistoryRecord next =
6723 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6724 HistoryRecord top = null;
6725 CharSequence topDescription = null;
6726 TaskRecord curTask = null;
6727 int numActivities = 0;
6728 int numRunning = 0;
6729 while (pos >= 0 && maxNum > 0) {
6730 final HistoryRecord r = next;
6731 pos--;
6732 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6733
6734 // Initialize state for next task if needed.
6735 if (top == null ||
6736 (top.state == ActivityState.INITIALIZING
6737 && top.task == r.task)) {
6738 top = r;
6739 topDescription = r.description;
6740 curTask = r.task;
6741 numActivities = numRunning = 0;
6742 }
6743
6744 // Add 'r' into the current task.
6745 numActivities++;
6746 if (r.app != null && r.app.thread != null) {
6747 numRunning++;
6748 }
6749 if (topDescription == null) {
6750 topDescription = r.description;
6751 }
6752
Joe Onorato8a9b2202010-02-26 18:56:32 -08006753 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006754 TAG, r.intent.getComponent().flattenToShortString()
6755 + ": task=" + r.task);
6756
6757 // If the next one is a different task, generate a new
6758 // TaskInfo entry for what we have.
6759 if (next == null || next.task != curTask) {
6760 ActivityManager.RunningTaskInfo ci
6761 = new ActivityManager.RunningTaskInfo();
6762 ci.id = curTask.taskId;
6763 ci.baseActivity = r.intent.getComponent();
6764 ci.topActivity = top.intent.getComponent();
6765 ci.thumbnail = top.thumbnail;
6766 ci.description = topDescription;
6767 ci.numActivities = numActivities;
6768 ci.numRunning = numRunning;
6769 //System.out.println(
6770 // "#" + maxNum + ": " + " descr=" + ci.description);
6771 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006772 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006773 TAG, "State=" + top.state + "Idle=" + top.idle
6774 + " app=" + top.app
6775 + " thr=" + (top.app != null ? top.app.thread : null));
6776 if (top.state == ActivityState.RESUMED
6777 || top.state == ActivityState.PAUSING) {
6778 if (top.idle && top.app != null
6779 && top.app.thread != null) {
6780 topRecord = top;
6781 topThumbnail = top.app.thread;
6782 } else {
6783 top.thumbnailNeeded = true;
6784 }
6785 }
6786 if (pending == null) {
6787 pending = new PendingThumbnailsRecord(receiver);
6788 }
6789 pending.pendingRecords.add(top);
6790 }
6791 list.add(ci);
6792 maxNum--;
6793 top = null;
6794 }
6795 }
6796
6797 if (pending != null) {
6798 mPendingThumbnails.add(pending);
6799 }
6800 }
6801
Joe Onorato8a9b2202010-02-26 18:56:32 -08006802 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006803
6804 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006805 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006806 try {
6807 topThumbnail.requestThumbnail(topRecord);
6808 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006809 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006810 sendPendingThumbnail(null, topRecord, null, null, true);
6811 }
6812 }
6813
6814 if (pending == null && receiver != null) {
6815 // In this case all thumbnails were available and the client
6816 // is being asked to be told when the remaining ones come in...
6817 // which is unusually, since the top-most currently running
6818 // activity should never have a canned thumbnail! Oh well.
6819 try {
6820 receiver.finished();
6821 } catch (RemoteException ex) {
6822 }
6823 }
6824
6825 return list;
6826 }
6827
6828 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6829 int flags) {
6830 synchronized (this) {
6831 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6832 "getRecentTasks()");
6833
6834 final int N = mRecentTasks.size();
6835 ArrayList<ActivityManager.RecentTaskInfo> res
6836 = new ArrayList<ActivityManager.RecentTaskInfo>(
6837 maxNum < N ? maxNum : N);
6838 for (int i=0; i<N && maxNum > 0; i++) {
6839 TaskRecord tr = mRecentTasks.get(i);
6840 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6841 || (tr.intent == null)
6842 || ((tr.intent.getFlags()
6843 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6844 ActivityManager.RecentTaskInfo rti
6845 = new ActivityManager.RecentTaskInfo();
6846 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6847 rti.baseIntent = new Intent(
6848 tr.intent != null ? tr.intent : tr.affinityIntent);
6849 rti.origActivity = tr.origActivity;
6850 res.add(rti);
6851 maxNum--;
6852 }
6853 }
6854 return res;
6855 }
6856 }
6857
6858 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6859 int j;
6860 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6861 TaskRecord jt = startTask;
6862
6863 // First look backwards
6864 for (j=startIndex-1; j>=0; j--) {
6865 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6866 if (r.task != jt) {
6867 jt = r.task;
6868 if (affinity.equals(jt.affinity)) {
6869 return j;
6870 }
6871 }
6872 }
6873
6874 // Now look forwards
6875 final int N = mHistory.size();
6876 jt = startTask;
6877 for (j=startIndex+1; j<N; j++) {
6878 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6879 if (r.task != jt) {
6880 if (affinity.equals(jt.affinity)) {
6881 return j;
6882 }
6883 jt = r.task;
6884 }
6885 }
6886
6887 // Might it be at the top?
6888 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6889 return N-1;
6890 }
6891
6892 return -1;
6893 }
6894
6895 /**
6896 * Perform a reset of the given task, if needed as part of launching it.
6897 * Returns the new HistoryRecord at the top of the task.
6898 */
6899 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6900 HistoryRecord newActivity) {
6901 boolean forceReset = (newActivity.info.flags
6902 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6903 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6904 if ((newActivity.info.flags
6905 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6906 forceReset = true;
6907 }
6908 }
6909
6910 final TaskRecord task = taskTop.task;
6911
6912 // We are going to move through the history list so that we can look
6913 // at each activity 'target' with 'below' either the interesting
6914 // activity immediately below it in the stack or null.
6915 HistoryRecord target = null;
6916 int targetI = 0;
6917 int taskTopI = -1;
6918 int replyChainEnd = -1;
6919 int lastReparentPos = -1;
6920 for (int i=mHistory.size()-1; i>=-1; i--) {
6921 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6922
6923 if (below != null && below.finishing) {
6924 continue;
6925 }
6926 if (target == null) {
6927 target = below;
6928 targetI = i;
6929 // If we were in the middle of a reply chain before this
6930 // task, it doesn't appear like the root of the chain wants
6931 // anything interesting, so drop it.
6932 replyChainEnd = -1;
6933 continue;
6934 }
6935
6936 final int flags = target.info.flags;
6937
6938 final boolean finishOnTaskLaunch =
6939 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6940 final boolean allowTaskReparenting =
6941 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6942
6943 if (target.task == task) {
6944 // We are inside of the task being reset... we'll either
6945 // finish this activity, push it out for another task,
6946 // or leave it as-is. We only do this
6947 // for activities that are not the root of the task (since
6948 // if we finish the root, we may no longer have the task!).
6949 if (taskTopI < 0) {
6950 taskTopI = targetI;
6951 }
6952 if (below != null && below.task == task) {
6953 final boolean clearWhenTaskReset =
6954 (target.intent.getFlags()
6955 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006956 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006957 // If this activity is sending a reply to a previous
6958 // activity, we can't do anything with it now until
6959 // we reach the start of the reply chain.
6960 // XXX note that we are assuming the result is always
6961 // to the previous activity, which is almost always
6962 // the case but we really shouldn't count on.
6963 if (replyChainEnd < 0) {
6964 replyChainEnd = targetI;
6965 }
Ed Heyl73798232009-03-24 21:32:21 -07006966 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006967 && target.taskAffinity != null
6968 && !target.taskAffinity.equals(task.affinity)) {
6969 // If this activity has an affinity for another
6970 // task, then we need to move it out of here. We will
6971 // move it as far out of the way as possible, to the
6972 // bottom of the activity stack. This also keeps it
6973 // correctly ordered with any activities we previously
6974 // moved.
6975 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6976 if (target.taskAffinity != null
6977 && target.taskAffinity.equals(p.task.affinity)) {
6978 // If the activity currently at the bottom has the
6979 // same task affinity as the one we are moving,
6980 // then merge it into the same task.
6981 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006982 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006983 + " out to bottom task " + p.task);
6984 } else {
6985 mCurTask++;
6986 if (mCurTask <= 0) {
6987 mCurTask = 1;
6988 }
6989 target.task = new TaskRecord(mCurTask, target.info, null,
6990 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6991 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006992 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993 + " out to new task " + target.task);
6994 }
6995 mWindowManager.setAppGroupId(target, task.taskId);
6996 if (replyChainEnd < 0) {
6997 replyChainEnd = targetI;
6998 }
6999 int dstPos = 0;
7000 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7001 p = (HistoryRecord)mHistory.get(srcPos);
7002 if (p.finishing) {
7003 continue;
7004 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007005 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006 + " out to target's task " + target.task);
7007 task.numActivities--;
7008 p.task = target.task;
7009 target.task.numActivities++;
7010 mHistory.remove(srcPos);
7011 mHistory.add(dstPos, p);
7012 mWindowManager.moveAppToken(dstPos, p);
7013 mWindowManager.setAppGroupId(p, p.task.taskId);
7014 dstPos++;
7015 if (VALIDATE_TOKENS) {
7016 mWindowManager.validateAppTokens(mHistory);
7017 }
7018 i++;
7019 }
7020 if (taskTop == p) {
7021 taskTop = below;
7022 }
7023 if (taskTopI == replyChainEnd) {
7024 taskTopI = -1;
7025 }
7026 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007027 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007028 } else if (forceReset || finishOnTaskLaunch
7029 || clearWhenTaskReset) {
7030 // If the activity should just be removed -- either
7031 // because it asks for it, or the task should be
7032 // cleared -- then finish it and anything that is
7033 // part of its reply chain.
7034 if (clearWhenTaskReset) {
7035 // In this case, we want to finish this activity
7036 // and everything above it, so be sneaky and pretend
7037 // like these are all in the reply chain.
7038 replyChainEnd = targetI+1;
7039 while (replyChainEnd < mHistory.size() &&
7040 ((HistoryRecord)mHistory.get(
7041 replyChainEnd)).task == task) {
7042 replyChainEnd++;
7043 }
7044 replyChainEnd--;
7045 } else if (replyChainEnd < 0) {
7046 replyChainEnd = targetI;
7047 }
7048 HistoryRecord p = null;
7049 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7050 p = (HistoryRecord)mHistory.get(srcPos);
7051 if (p.finishing) {
7052 continue;
7053 }
7054 if (finishActivityLocked(p, srcPos,
7055 Activity.RESULT_CANCELED, null, "reset")) {
7056 replyChainEnd--;
7057 srcPos--;
7058 }
7059 }
7060 if (taskTop == p) {
7061 taskTop = below;
7062 }
7063 if (taskTopI == replyChainEnd) {
7064 taskTopI = -1;
7065 }
7066 replyChainEnd = -1;
7067 } else {
7068 // If we were in the middle of a chain, well the
7069 // activity that started it all doesn't want anything
7070 // special, so leave it all as-is.
7071 replyChainEnd = -1;
7072 }
7073 } else {
7074 // Reached the bottom of the task -- any reply chain
7075 // should be left as-is.
7076 replyChainEnd = -1;
7077 }
7078
7079 } else if (target.resultTo != null) {
7080 // If this activity is sending a reply to a previous
7081 // activity, we can't do anything with it now until
7082 // we reach the start of the reply chain.
7083 // XXX note that we are assuming the result is always
7084 // to the previous activity, which is almost always
7085 // the case but we really shouldn't count on.
7086 if (replyChainEnd < 0) {
7087 replyChainEnd = targetI;
7088 }
7089
7090 } else if (taskTopI >= 0 && allowTaskReparenting
7091 && task.affinity != null
7092 && task.affinity.equals(target.taskAffinity)) {
7093 // We are inside of another task... if this activity has
7094 // an affinity for our task, then either remove it if we are
7095 // clearing or move it over to our task. Note that
7096 // we currently punt on the case where we are resetting a
7097 // task that is not at the top but who has activities above
7098 // with an affinity to it... this is really not a normal
7099 // case, and we will need to later pull that task to the front
7100 // and usually at that point we will do the reset and pick
7101 // up those remaining activities. (This only happens if
7102 // someone starts an activity in a new task from an activity
7103 // in a task that is not currently on top.)
7104 if (forceReset || finishOnTaskLaunch) {
7105 if (replyChainEnd < 0) {
7106 replyChainEnd = targetI;
7107 }
7108 HistoryRecord p = null;
7109 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7110 p = (HistoryRecord)mHistory.get(srcPos);
7111 if (p.finishing) {
7112 continue;
7113 }
7114 if (finishActivityLocked(p, srcPos,
7115 Activity.RESULT_CANCELED, null, "reset")) {
7116 taskTopI--;
7117 lastReparentPos--;
7118 replyChainEnd--;
7119 srcPos--;
7120 }
7121 }
7122 replyChainEnd = -1;
7123 } else {
7124 if (replyChainEnd < 0) {
7125 replyChainEnd = targetI;
7126 }
7127 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7128 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7129 if (p.finishing) {
7130 continue;
7131 }
7132 if (lastReparentPos < 0) {
7133 lastReparentPos = taskTopI;
7134 taskTop = p;
7135 } else {
7136 lastReparentPos--;
7137 }
7138 mHistory.remove(srcPos);
7139 p.task.numActivities--;
7140 p.task = task;
7141 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007142 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007143 + " in to resetting task " + task);
7144 task.numActivities++;
7145 mWindowManager.moveAppToken(lastReparentPos, p);
7146 mWindowManager.setAppGroupId(p, p.task.taskId);
7147 if (VALIDATE_TOKENS) {
7148 mWindowManager.validateAppTokens(mHistory);
7149 }
7150 }
7151 replyChainEnd = -1;
7152
7153 // Now we've moved it in to place... but what if this is
7154 // a singleTop activity and we have put it on top of another
7155 // instance of the same activity? Then we drop the instance
7156 // below so it remains singleTop.
7157 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7158 for (int j=lastReparentPos-1; j>=0; j--) {
7159 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7160 if (p.finishing) {
7161 continue;
7162 }
7163 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7164 if (finishActivityLocked(p, j,
7165 Activity.RESULT_CANCELED, null, "replace")) {
7166 taskTopI--;
7167 lastReparentPos--;
7168 }
7169 }
7170 }
7171 }
7172 }
7173 }
7174
7175 target = below;
7176 targetI = i;
7177 }
7178
7179 return taskTop;
7180 }
7181
7182 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007183 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007184 */
7185 public void moveTaskToFront(int task) {
7186 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7187 "moveTaskToFront()");
7188
7189 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007190 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7191 Binder.getCallingUid(), "Task to front")) {
7192 return;
7193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194 final long origId = Binder.clearCallingIdentity();
7195 try {
7196 int N = mRecentTasks.size();
7197 for (int i=0; i<N; i++) {
7198 TaskRecord tr = mRecentTasks.get(i);
7199 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007200 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007201 return;
7202 }
7203 }
7204 for (int i=mHistory.size()-1; i>=0; i--) {
7205 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7206 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007207 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007208 return;
7209 }
7210 }
7211 } finally {
7212 Binder.restoreCallingIdentity(origId);
7213 }
7214 }
7215 }
7216
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007217 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007218 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007219
7220 final int task = tr.taskId;
7221 int top = mHistory.size()-1;
7222
7223 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7224 // nothing to do!
7225 return;
7226 }
7227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 ArrayList moved = new ArrayList();
7229
7230 // Applying the affinities may have removed entries from the history,
7231 // so get the size again.
7232 top = mHistory.size()-1;
7233 int pos = top;
7234
7235 // Shift all activities with this task up to the top
7236 // of the stack, keeping them in the same internal order.
7237 while (pos >= 0) {
7238 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007239 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007240 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7241 boolean first = true;
7242 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007243 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007244 mHistory.remove(pos);
7245 mHistory.add(top, r);
7246 moved.add(0, r);
7247 top--;
7248 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007249 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 first = false;
7251 }
7252 }
7253 pos--;
7254 }
7255
Joe Onorato8a9b2202010-02-26 18:56:32 -08007256 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007257 "Prepare to front transition: task=" + tr);
7258 if (reason != null &&
7259 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7260 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7261 HistoryRecord r = topRunningActivityLocked(null);
7262 if (r != null) {
7263 mNoAnimActivities.add(r);
7264 }
7265 } else {
7266 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7267 }
7268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007269 mWindowManager.moveAppTokensToTop(moved);
7270 if (VALIDATE_TOKENS) {
7271 mWindowManager.validateAppTokens(mHistory);
7272 }
7273
Josh Bartel7f208742010-02-25 11:01:44 -06007274 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007275 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007276 }
7277
Josh Bartel7f208742010-02-25 11:01:44 -06007278 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007279 resumeTopActivityLocked(null);
7280 }
7281
7282 public void moveTaskToBack(int task) {
7283 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7284 "moveTaskToBack()");
7285
7286 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007287 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7288 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7289 Binder.getCallingUid(), "Task to back")) {
7290 return;
7291 }
7292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007293 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007294 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295 Binder.restoreCallingIdentity(origId);
7296 }
7297 }
7298
7299 /**
7300 * Moves an activity, and all of the other activities within the same task, to the bottom
7301 * of the history stack. The activity's order within the task is unchanged.
7302 *
7303 * @param token A reference to the activity we wish to move
7304 * @param nonRoot If false then this only works if the activity is the root
7305 * of a task; if true it will work for any activity in a task.
7306 * @return Returns true if the move completed, false if not.
7307 */
7308 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7309 synchronized(this) {
7310 final long origId = Binder.clearCallingIdentity();
7311 int taskId = getTaskForActivityLocked(token, !nonRoot);
7312 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007313 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007314 }
7315 Binder.restoreCallingIdentity(origId);
7316 }
7317 return false;
7318 }
7319
7320 /**
7321 * Worker method for rearranging history stack. Implements the function of moving all
7322 * activities for a specific task (gathering them if disjoint) into a single group at the
7323 * bottom of the stack.
7324 *
7325 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7326 * to premeptively cancel the move.
7327 *
7328 * @param task The taskId to collect and move to the bottom.
7329 * @return Returns true if the move completed, false if not.
7330 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007331 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007332 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007333
7334 // If we have a watcher, preflight the move before committing to it. First check
7335 // for *other* available tasks, but if none are available, then try again allowing the
7336 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007337 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007338 HistoryRecord next = topRunningActivityLocked(null, task);
7339 if (next == null) {
7340 next = topRunningActivityLocked(null, 0);
7341 }
7342 if (next != null) {
7343 // ask watcher if this is allowed
7344 boolean moveOK = true;
7345 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007346 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007347 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007348 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007349 }
7350 if (!moveOK) {
7351 return false;
7352 }
7353 }
7354 }
7355
7356 ArrayList moved = new ArrayList();
7357
Joe Onorato8a9b2202010-02-26 18:56:32 -08007358 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007359 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360
7361 final int N = mHistory.size();
7362 int bottom = 0;
7363 int pos = 0;
7364
7365 // Shift all activities with this task down to the bottom
7366 // of the stack, keeping them in the same internal order.
7367 while (pos < N) {
7368 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007369 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007370 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7371 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007372 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007373 mHistory.remove(pos);
7374 mHistory.add(bottom, r);
7375 moved.add(r);
7376 bottom++;
7377 }
7378 pos++;
7379 }
7380
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007381 if (reason != null &&
7382 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7383 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7384 HistoryRecord r = topRunningActivityLocked(null);
7385 if (r != null) {
7386 mNoAnimActivities.add(r);
7387 }
7388 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007389 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007390 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 mWindowManager.moveAppTokensToBottom(moved);
7392 if (VALIDATE_TOKENS) {
7393 mWindowManager.validateAppTokens(mHistory);
7394 }
7395
Josh Bartel7f208742010-02-25 11:01:44 -06007396 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007397 return true;
7398 }
7399
7400 public void moveTaskBackwards(int task) {
7401 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7402 "moveTaskBackwards()");
7403
7404 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007405 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7406 Binder.getCallingUid(), "Task backwards")) {
7407 return;
7408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409 final long origId = Binder.clearCallingIdentity();
7410 moveTaskBackwardsLocked(task);
7411 Binder.restoreCallingIdentity(origId);
7412 }
7413 }
7414
7415 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007416 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417 }
7418
7419 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7420 synchronized(this) {
7421 return getTaskForActivityLocked(token, onlyRoot);
7422 }
7423 }
7424
7425 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7426 final int N = mHistory.size();
7427 TaskRecord lastTask = null;
7428 for (int i=0; i<N; i++) {
7429 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7430 if (r == token) {
7431 if (!onlyRoot || lastTask != r.task) {
7432 return r.task.taskId;
7433 }
7434 return -1;
7435 }
7436 lastTask = r.task;
7437 }
7438
7439 return -1;
7440 }
7441
7442 /**
7443 * Returns the top activity in any existing task matching the given
7444 * Intent. Returns null if no such task is found.
7445 */
7446 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7447 ComponentName cls = intent.getComponent();
7448 if (info.targetActivity != null) {
7449 cls = new ComponentName(info.packageName, info.targetActivity);
7450 }
7451
7452 TaskRecord cp = null;
7453
7454 final int N = mHistory.size();
7455 for (int i=(N-1); i>=0; i--) {
7456 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7457 if (!r.finishing && r.task != cp
7458 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7459 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007460 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 // + "/aff=" + r.task.affinity + " to new cls="
7462 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7463 if (r.task.affinity != null) {
7464 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007465 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007466 return r;
7467 }
7468 } else if (r.task.intent != null
7469 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007470 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007472 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007473 return r;
7474 } else if (r.task.affinityIntent != null
7475 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007476 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007477 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007478 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007479 return r;
7480 }
7481 }
7482 }
7483
7484 return null;
7485 }
7486
7487 /**
7488 * Returns the first activity (starting from the top of the stack) that
7489 * is the same as the given activity. Returns null if no such activity
7490 * is found.
7491 */
7492 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7493 ComponentName cls = intent.getComponent();
7494 if (info.targetActivity != null) {
7495 cls = new ComponentName(info.packageName, info.targetActivity);
7496 }
7497
7498 final int N = mHistory.size();
7499 for (int i=(N-1); i>=0; i--) {
7500 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7501 if (!r.finishing) {
7502 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007503 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007504 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007505 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007506 return r;
7507 }
7508 }
7509 }
7510
7511 return null;
7512 }
7513
7514 public void finishOtherInstances(IBinder token, ComponentName className) {
7515 synchronized(this) {
7516 final long origId = Binder.clearCallingIdentity();
7517
7518 int N = mHistory.size();
7519 TaskRecord lastTask = null;
7520 for (int i=0; i<N; i++) {
7521 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7522 if (r.realActivity.equals(className)
7523 && r != token && lastTask != r.task) {
7524 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7525 null, "others")) {
7526 i--;
7527 N--;
7528 }
7529 }
7530 lastTask = r.task;
7531 }
7532
7533 Binder.restoreCallingIdentity(origId);
7534 }
7535 }
7536
7537 // =========================================================
7538 // THUMBNAILS
7539 // =========================================================
7540
7541 public void reportThumbnail(IBinder token,
7542 Bitmap thumbnail, CharSequence description) {
7543 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7544 final long origId = Binder.clearCallingIdentity();
7545 sendPendingThumbnail(null, token, thumbnail, description, true);
7546 Binder.restoreCallingIdentity(origId);
7547 }
7548
7549 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7550 Bitmap thumbnail, CharSequence description, boolean always) {
7551 TaskRecord task = null;
7552 ArrayList receivers = null;
7553
7554 //System.out.println("Send pending thumbnail: " + r);
7555
7556 synchronized(this) {
7557 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007558 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559 if (index < 0) {
7560 return;
7561 }
7562 r = (HistoryRecord)mHistory.get(index);
7563 }
7564 if (thumbnail == null) {
7565 thumbnail = r.thumbnail;
7566 description = r.description;
7567 }
7568 if (thumbnail == null && !always) {
7569 // If there is no thumbnail, and this entry is not actually
7570 // going away, then abort for now and pick up the next
7571 // thumbnail we get.
7572 return;
7573 }
7574 task = r.task;
7575
7576 int N = mPendingThumbnails.size();
7577 int i=0;
7578 while (i<N) {
7579 PendingThumbnailsRecord pr =
7580 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7581 //System.out.println("Looking in " + pr.pendingRecords);
7582 if (pr.pendingRecords.remove(r)) {
7583 if (receivers == null) {
7584 receivers = new ArrayList();
7585 }
7586 receivers.add(pr);
7587 if (pr.pendingRecords.size() == 0) {
7588 pr.finished = true;
7589 mPendingThumbnails.remove(i);
7590 N--;
7591 continue;
7592 }
7593 }
7594 i++;
7595 }
7596 }
7597
7598 if (receivers != null) {
7599 final int N = receivers.size();
7600 for (int i=0; i<N; i++) {
7601 try {
7602 PendingThumbnailsRecord pr =
7603 (PendingThumbnailsRecord)receivers.get(i);
7604 pr.receiver.newThumbnail(
7605 task != null ? task.taskId : -1, thumbnail, description);
7606 if (pr.finished) {
7607 pr.receiver.finished();
7608 }
7609 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007610 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007611 }
7612 }
7613 }
7614 }
7615
7616 // =========================================================
7617 // CONTENT PROVIDERS
7618 // =========================================================
7619
7620 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7621 List providers = null;
7622 try {
7623 providers = ActivityThread.getPackageManager().
7624 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007625 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626 } catch (RemoteException ex) {
7627 }
7628 if (providers != null) {
7629 final int N = providers.size();
7630 for (int i=0; i<N; i++) {
7631 ProviderInfo cpi =
7632 (ProviderInfo)providers.get(i);
7633 ContentProviderRecord cpr =
7634 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7635 if (cpr == null) {
7636 cpr = new ContentProviderRecord(cpi, app.info);
7637 mProvidersByClass.put(cpi.name, cpr);
7638 }
7639 app.pubProviders.put(cpi.name, cpr);
7640 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007641 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007642 }
7643 }
7644 return providers;
7645 }
7646
7647 private final String checkContentProviderPermissionLocked(
7648 ProviderInfo cpi, ProcessRecord r, int mode) {
7649 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7650 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7651 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7652 cpi.exported ? -1 : cpi.applicationInfo.uid)
7653 == PackageManager.PERMISSION_GRANTED
7654 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7655 return null;
7656 }
7657 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7658 cpi.exported ? -1 : cpi.applicationInfo.uid)
7659 == PackageManager.PERMISSION_GRANTED) {
7660 return null;
7661 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007662
7663 PathPermission[] pps = cpi.pathPermissions;
7664 if (pps != null) {
7665 int i = pps.length;
7666 while (i > 0) {
7667 i--;
7668 PathPermission pp = pps[i];
7669 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7670 cpi.exported ? -1 : cpi.applicationInfo.uid)
7671 == PackageManager.PERMISSION_GRANTED
7672 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7673 return null;
7674 }
7675 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7676 cpi.exported ? -1 : cpi.applicationInfo.uid)
7677 == PackageManager.PERMISSION_GRANTED) {
7678 return null;
7679 }
7680 }
7681 }
7682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683 String msg = "Permission Denial: opening provider " + cpi.name
7684 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7685 + ", uid=" + callingUid + ") requires "
7686 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007687 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007688 return msg;
7689 }
7690
7691 private final ContentProviderHolder getContentProviderImpl(
7692 IApplicationThread caller, String name) {
7693 ContentProviderRecord cpr;
7694 ProviderInfo cpi = null;
7695
7696 synchronized(this) {
7697 ProcessRecord r = null;
7698 if (caller != null) {
7699 r = getRecordForAppLocked(caller);
7700 if (r == null) {
7701 throw new SecurityException(
7702 "Unable to find app for caller " + caller
7703 + " (pid=" + Binder.getCallingPid()
7704 + ") when getting content provider " + name);
7705 }
7706 }
7707
7708 // First check if this content provider has been published...
7709 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7710 if (cpr != null) {
7711 cpi = cpr.info;
7712 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7713 return new ContentProviderHolder(cpi,
7714 cpi.readPermission != null
7715 ? cpi.readPermission : cpi.writePermission);
7716 }
7717
7718 if (r != null && cpr.canRunHere(r)) {
7719 // This provider has been published or is in the process
7720 // of being published... but it is also allowed to run
7721 // in the caller's process, so don't make a connection
7722 // and just let the caller instantiate its own instance.
7723 if (cpr.provider != null) {
7724 // don't give caller the provider object, it needs
7725 // to make its own.
7726 cpr = new ContentProviderRecord(cpr);
7727 }
7728 return cpr;
7729 }
7730
7731 final long origId = Binder.clearCallingIdentity();
7732
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007733 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734 // return it right away.
7735 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007736 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007737 "Adding provider requested by "
7738 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007739 + cpr.info.processName);
7740 Integer cnt = r.conProviders.get(cpr);
7741 if (cnt == null) {
7742 r.conProviders.put(cpr, new Integer(1));
7743 } else {
7744 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746 cpr.clients.add(r);
7747 } else {
7748 cpr.externals++;
7749 }
7750
7751 if (cpr.app != null) {
7752 updateOomAdjLocked(cpr.app);
7753 }
7754
7755 Binder.restoreCallingIdentity(origId);
7756
7757 } else {
7758 try {
7759 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007760 resolveContentProvider(name,
7761 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762 } catch (RemoteException ex) {
7763 }
7764 if (cpi == null) {
7765 return null;
7766 }
7767
7768 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7769 return new ContentProviderHolder(cpi,
7770 cpi.readPermission != null
7771 ? cpi.readPermission : cpi.writePermission);
7772 }
7773
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007774 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7775 && !cpi.processName.equals("system")) {
7776 // If this content provider does not run in the system
7777 // process, and the system is not yet ready to run other
7778 // processes, then fail fast instead of hanging.
7779 throw new IllegalArgumentException(
7780 "Attempt to launch content provider before system ready");
7781 }
7782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007783 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7784 final boolean firstClass = cpr == null;
7785 if (firstClass) {
7786 try {
7787 ApplicationInfo ai =
7788 ActivityThread.getPackageManager().
7789 getApplicationInfo(
7790 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007791 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007793 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 + cpi.name);
7795 return null;
7796 }
7797 cpr = new ContentProviderRecord(cpi, ai);
7798 } catch (RemoteException ex) {
7799 // pm is in same process, this will never happen.
7800 }
7801 }
7802
7803 if (r != null && cpr.canRunHere(r)) {
7804 // If this is a multiprocess provider, then just return its
7805 // info and allow the caller to instantiate it. Only do
7806 // this if the provider is the same user as the caller's
7807 // process, or can run as root (so can be in any process).
7808 return cpr;
7809 }
7810
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007811 if (DEBUG_PROVIDER) {
7812 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007813 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007814 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007815 }
7816
7817 // This is single process, and our app is now connecting to it.
7818 // See if we are already in the process of launching this
7819 // provider.
7820 final int N = mLaunchingProviders.size();
7821 int i;
7822 for (i=0; i<N; i++) {
7823 if (mLaunchingProviders.get(i) == cpr) {
7824 break;
7825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007826 }
7827
7828 // If the provider is not already being launched, then get it
7829 // started.
7830 if (i >= N) {
7831 final long origId = Binder.clearCallingIdentity();
7832 ProcessRecord proc = startProcessLocked(cpi.processName,
7833 cpr.appInfo, false, 0, "content provider",
7834 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007835 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007836 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007837 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 + cpi.applicationInfo.packageName + "/"
7839 + cpi.applicationInfo.uid + " for provider "
7840 + name + ": process is bad");
7841 return null;
7842 }
7843 cpr.launchingApp = proc;
7844 mLaunchingProviders.add(cpr);
7845 Binder.restoreCallingIdentity(origId);
7846 }
7847
7848 // Make sure the provider is published (the same provider class
7849 // may be published under multiple names).
7850 if (firstClass) {
7851 mProvidersByClass.put(cpi.name, cpr);
7852 }
7853 mProvidersByName.put(name, cpr);
7854
7855 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007856 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007857 "Adding provider requested by "
7858 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007859 + cpr.info.processName);
7860 Integer cnt = r.conProviders.get(cpr);
7861 if (cnt == null) {
7862 r.conProviders.put(cpr, new Integer(1));
7863 } else {
7864 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7865 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007866 cpr.clients.add(r);
7867 } else {
7868 cpr.externals++;
7869 }
7870 }
7871 }
7872
7873 // Wait for the provider to be published...
7874 synchronized (cpr) {
7875 while (cpr.provider == null) {
7876 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007877 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007878 + cpi.applicationInfo.packageName + "/"
7879 + cpi.applicationInfo.uid + " for provider "
7880 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007881 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 cpi.applicationInfo.packageName,
7883 cpi.applicationInfo.uid, name);
7884 return null;
7885 }
7886 try {
7887 cpr.wait();
7888 } catch (InterruptedException ex) {
7889 }
7890 }
7891 }
7892 return cpr;
7893 }
7894
7895 public final ContentProviderHolder getContentProvider(
7896 IApplicationThread caller, String name) {
7897 if (caller == null) {
7898 String msg = "null IApplicationThread when getting content provider "
7899 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007900 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 throw new SecurityException(msg);
7902 }
7903
7904 return getContentProviderImpl(caller, name);
7905 }
7906
7907 private ContentProviderHolder getContentProviderExternal(String name) {
7908 return getContentProviderImpl(null, name);
7909 }
7910
7911 /**
7912 * Drop a content provider from a ProcessRecord's bookkeeping
7913 * @param cpr
7914 */
7915 public void removeContentProvider(IApplicationThread caller, String name) {
7916 synchronized (this) {
7917 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7918 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007919 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007920 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007921 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007922 return;
7923 }
7924 final ProcessRecord r = getRecordForAppLocked(caller);
7925 if (r == null) {
7926 throw new SecurityException(
7927 "Unable to find app for caller " + caller +
7928 " when removing content provider " + name);
7929 }
7930 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007931 ContentProviderRecord localCpr = (ContentProviderRecord)
7932 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007933 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007934 + r.info.processName + " from process "
7935 + localCpr.appInfo.processName);
7936 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007937 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007938 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007939 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007940 return;
7941 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007942 Integer cnt = r.conProviders.get(localCpr);
7943 if (cnt == null || cnt.intValue() <= 1) {
7944 localCpr.clients.remove(r);
7945 r.conProviders.remove(localCpr);
7946 } else {
7947 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7948 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007949 }
7950 updateOomAdjLocked();
7951 }
7952 }
7953
7954 private void removeContentProviderExternal(String name) {
7955 synchronized (this) {
7956 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7957 if(cpr == null) {
7958 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007959 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007960 return;
7961 }
7962
7963 //update content provider record entry info
7964 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7965 localCpr.externals--;
7966 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007967 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007968 }
7969 updateOomAdjLocked();
7970 }
7971 }
7972
7973 public final void publishContentProviders(IApplicationThread caller,
7974 List<ContentProviderHolder> providers) {
7975 if (providers == null) {
7976 return;
7977 }
7978
7979 synchronized(this) {
7980 final ProcessRecord r = getRecordForAppLocked(caller);
7981 if (r == null) {
7982 throw new SecurityException(
7983 "Unable to find app for caller " + caller
7984 + " (pid=" + Binder.getCallingPid()
7985 + ") when publishing content providers");
7986 }
7987
7988 final long origId = Binder.clearCallingIdentity();
7989
7990 final int N = providers.size();
7991 for (int i=0; i<N; i++) {
7992 ContentProviderHolder src = providers.get(i);
7993 if (src == null || src.info == null || src.provider == null) {
7994 continue;
7995 }
7996 ContentProviderRecord dst =
7997 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7998 if (dst != null) {
7999 mProvidersByClass.put(dst.info.name, dst);
8000 String names[] = dst.info.authority.split(";");
8001 for (int j = 0; j < names.length; j++) {
8002 mProvidersByName.put(names[j], dst);
8003 }
8004
8005 int NL = mLaunchingProviders.size();
8006 int j;
8007 for (j=0; j<NL; j++) {
8008 if (mLaunchingProviders.get(j) == dst) {
8009 mLaunchingProviders.remove(j);
8010 j--;
8011 NL--;
8012 }
8013 }
8014 synchronized (dst) {
8015 dst.provider = src.provider;
8016 dst.app = r;
8017 dst.notifyAll();
8018 }
8019 updateOomAdjLocked(r);
8020 }
8021 }
8022
8023 Binder.restoreCallingIdentity(origId);
8024 }
8025 }
8026
8027 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008028 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008029 synchronized (mSelf) {
8030 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8031 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008032 if (providers != null) {
8033 for (int i=providers.size()-1; i>=0; i--) {
8034 ProviderInfo pi = (ProviderInfo)providers.get(i);
8035 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8036 Slog.w(TAG, "Not installing system proc provider " + pi.name
8037 + ": not system .apk");
8038 providers.remove(i);
8039 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008040 }
8041 }
8042 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008043 if (providers != null) {
8044 mSystemThread.installSystemProviders(providers);
8045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008046 }
8047
8048 // =========================================================
8049 // GLOBAL MANAGEMENT
8050 // =========================================================
8051
8052 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8053 ApplicationInfo info, String customProcess) {
8054 String proc = customProcess != null ? customProcess : info.processName;
8055 BatteryStatsImpl.Uid.Proc ps = null;
8056 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8057 synchronized (stats) {
8058 ps = stats.getProcessStatsLocked(info.uid, proc);
8059 }
8060 return new ProcessRecord(ps, thread, info, proc);
8061 }
8062
8063 final ProcessRecord addAppLocked(ApplicationInfo info) {
8064 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8065
8066 if (app == null) {
8067 app = newProcessRecordLocked(null, info, null);
8068 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008069 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008070 }
8071
8072 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8073 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8074 app.persistent = true;
8075 app.maxAdj = CORE_SERVER_ADJ;
8076 }
8077 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8078 mPersistentStartingProcesses.add(app);
8079 startProcessLocked(app, "added application", app.processName);
8080 }
8081
8082 return app;
8083 }
8084
8085 public void unhandledBack() {
8086 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8087 "unhandledBack()");
8088
8089 synchronized(this) {
8090 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008091 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008092 TAG, "Performing unhandledBack(): stack size = " + count);
8093 if (count > 1) {
8094 final long origId = Binder.clearCallingIdentity();
8095 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8096 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8097 Binder.restoreCallingIdentity(origId);
8098 }
8099 }
8100 }
8101
8102 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8103 String name = uri.getAuthority();
8104 ContentProviderHolder cph = getContentProviderExternal(name);
8105 ParcelFileDescriptor pfd = null;
8106 if (cph != null) {
8107 // We record the binder invoker's uid in thread-local storage before
8108 // going to the content provider to open the file. Later, in the code
8109 // that handles all permissions checks, we look for this uid and use
8110 // that rather than the Activity Manager's own uid. The effect is that
8111 // we do the check against the caller's permissions even though it looks
8112 // to the content provider like the Activity Manager itself is making
8113 // the request.
8114 sCallerIdentity.set(new Identity(
8115 Binder.getCallingPid(), Binder.getCallingUid()));
8116 try {
8117 pfd = cph.provider.openFile(uri, "r");
8118 } catch (FileNotFoundException e) {
8119 // do nothing; pfd will be returned null
8120 } finally {
8121 // Ensure that whatever happens, we clean up the identity state
8122 sCallerIdentity.remove();
8123 }
8124
8125 // We've got the fd now, so we're done with the provider.
8126 removeContentProviderExternal(name);
8127 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008128 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008129 }
8130 return pfd;
8131 }
8132
8133 public void goingToSleep() {
8134 synchronized(this) {
8135 mSleeping = true;
8136 mWindowManager.setEventDispatching(false);
8137
8138 if (mResumedActivity != null) {
8139 pauseIfSleepingLocked();
8140 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008141 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008142 }
8143 }
8144 }
8145
Dianne Hackborn55280a92009-05-07 15:53:46 -07008146 public boolean shutdown(int timeout) {
8147 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8148 != PackageManager.PERMISSION_GRANTED) {
8149 throw new SecurityException("Requires permission "
8150 + android.Manifest.permission.SHUTDOWN);
8151 }
8152
8153 boolean timedout = false;
8154
8155 synchronized(this) {
8156 mShuttingDown = true;
8157 mWindowManager.setEventDispatching(false);
8158
8159 if (mResumedActivity != null) {
8160 pauseIfSleepingLocked();
8161 final long endTime = System.currentTimeMillis() + timeout;
8162 while (mResumedActivity != null || mPausingActivity != null) {
8163 long delay = endTime - System.currentTimeMillis();
8164 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008165 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008166 timedout = true;
8167 break;
8168 }
8169 try {
8170 this.wait();
8171 } catch (InterruptedException e) {
8172 }
8173 }
8174 }
8175 }
8176
8177 mUsageStatsService.shutdown();
8178 mBatteryStatsService.shutdown();
8179
8180 return timedout;
8181 }
8182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008184 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 if (!mGoingToSleep.isHeld()) {
8186 mGoingToSleep.acquire();
8187 if (mLaunchingActivity.isHeld()) {
8188 mLaunchingActivity.release();
8189 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8190 }
8191 }
8192
8193 // If we are not currently pausing an activity, get the current
8194 // one to pause. If we are pausing one, we will just let that stuff
8195 // run and release the wake lock when all done.
8196 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008197 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8198 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008199 startPausingLocked(false, true);
8200 }
8201 }
8202 }
8203
8204 public void wakingUp() {
8205 synchronized(this) {
8206 if (mGoingToSleep.isHeld()) {
8207 mGoingToSleep.release();
8208 }
8209 mWindowManager.setEventDispatching(true);
8210 mSleeping = false;
8211 resumeTopActivityLocked(null);
8212 }
8213 }
8214
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008215 public void stopAppSwitches() {
8216 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8217 != PackageManager.PERMISSION_GRANTED) {
8218 throw new SecurityException("Requires permission "
8219 + android.Manifest.permission.STOP_APP_SWITCHES);
8220 }
8221
8222 synchronized(this) {
8223 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8224 + APP_SWITCH_DELAY_TIME;
8225 mDidAppSwitch = false;
8226 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8227 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8228 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8229 }
8230 }
8231
8232 public void resumeAppSwitches() {
8233 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8234 != PackageManager.PERMISSION_GRANTED) {
8235 throw new SecurityException("Requires permission "
8236 + android.Manifest.permission.STOP_APP_SWITCHES);
8237 }
8238
8239 synchronized(this) {
8240 // Note that we don't execute any pending app switches... we will
8241 // let those wait until either the timeout, or the next start
8242 // activity request.
8243 mAppSwitchesAllowedTime = 0;
8244 }
8245 }
8246
8247 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8248 String name) {
8249 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8250 return true;
8251 }
8252
8253 final int perm = checkComponentPermission(
8254 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8255 callingUid, -1);
8256 if (perm == PackageManager.PERMISSION_GRANTED) {
8257 return true;
8258 }
8259
Joe Onorato8a9b2202010-02-26 18:56:32 -08008260 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008261 return false;
8262 }
8263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008264 public void setDebugApp(String packageName, boolean waitForDebugger,
8265 boolean persistent) {
8266 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8267 "setDebugApp()");
8268
8269 // Note that this is not really thread safe if there are multiple
8270 // callers into it at the same time, but that's not a situation we
8271 // care about.
8272 if (persistent) {
8273 final ContentResolver resolver = mContext.getContentResolver();
8274 Settings.System.putString(
8275 resolver, Settings.System.DEBUG_APP,
8276 packageName);
8277 Settings.System.putInt(
8278 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8279 waitForDebugger ? 1 : 0);
8280 }
8281
8282 synchronized (this) {
8283 if (!persistent) {
8284 mOrigDebugApp = mDebugApp;
8285 mOrigWaitForDebugger = mWaitForDebugger;
8286 }
8287 mDebugApp = packageName;
8288 mWaitForDebugger = waitForDebugger;
8289 mDebugTransient = !persistent;
8290 if (packageName != null) {
8291 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008292 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008293 Binder.restoreCallingIdentity(origId);
8294 }
8295 }
8296 }
8297
8298 public void setAlwaysFinish(boolean enabled) {
8299 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8300 "setAlwaysFinish()");
8301
8302 Settings.System.putInt(
8303 mContext.getContentResolver(),
8304 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8305
8306 synchronized (this) {
8307 mAlwaysFinishActivities = enabled;
8308 }
8309 }
8310
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008311 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008313 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008314 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008315 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008316 }
8317 }
8318
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008319 public boolean isUserAMonkey() {
8320 // For now the fact that there is a controller implies
8321 // we have a monkey.
8322 synchronized (this) {
8323 return mController != null;
8324 }
8325 }
8326
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008327 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008328 synchronized (this) {
8329 mWatchers.register(watcher);
8330 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008331 }
8332
8333 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008334 synchronized (this) {
8335 mWatchers.unregister(watcher);
8336 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008337 }
8338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339 public final void enterSafeMode() {
8340 synchronized(this) {
8341 // It only makes sense to do this before the system is ready
8342 // and started launching other packages.
8343 if (!mSystemReady) {
8344 try {
8345 ActivityThread.getPackageManager().enterSafeMode();
8346 } catch (RemoteException e) {
8347 }
8348
8349 View v = LayoutInflater.from(mContext).inflate(
8350 com.android.internal.R.layout.safe_mode, null);
8351 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8352 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8353 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8354 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8355 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8356 lp.format = v.getBackground().getOpacity();
8357 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8358 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8359 ((WindowManager)mContext.getSystemService(
8360 Context.WINDOW_SERVICE)).addView(v, lp);
8361 }
8362 }
8363 }
8364
8365 public void noteWakeupAlarm(IIntentSender sender) {
8366 if (!(sender instanceof PendingIntentRecord)) {
8367 return;
8368 }
8369 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8370 synchronized (stats) {
8371 if (mBatteryStatsService.isOnBattery()) {
8372 mBatteryStatsService.enforceCallingPermission();
8373 PendingIntentRecord rec = (PendingIntentRecord)sender;
8374 int MY_UID = Binder.getCallingUid();
8375 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8376 BatteryStatsImpl.Uid.Pkg pkg =
8377 stats.getPackageStatsLocked(uid, rec.key.packageName);
8378 pkg.incWakeupsLocked();
8379 }
8380 }
8381 }
8382
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008383 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008385 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008386 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008387 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008388 // XXX Note: don't acquire main activity lock here, because the window
8389 // manager calls in with its locks held.
8390
8391 boolean killed = false;
8392 synchronized (mPidsSelfLocked) {
8393 int[] types = new int[pids.length];
8394 int worstType = 0;
8395 for (int i=0; i<pids.length; i++) {
8396 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8397 if (proc != null) {
8398 int type = proc.setAdj;
8399 types[i] = type;
8400 if (type > worstType) {
8401 worstType = type;
8402 }
8403 }
8404 }
8405
8406 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8407 // then constrain it so we will kill all hidden procs.
8408 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8409 worstType = HIDDEN_APP_MIN_ADJ;
8410 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008411 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008412 for (int i=0; i<pids.length; i++) {
8413 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8414 if (proc == null) {
8415 continue;
8416 }
8417 int adj = proc.setAdj;
8418 if (adj >= worstType) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008419 Slog.w(TAG, "Killing " + reason + " : " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008420 + adj + ")");
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008421 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8422 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008423 killed = true;
8424 Process.killProcess(pids[i]);
8425 }
8426 }
8427 }
8428 return killed;
8429 }
8430
8431 public void reportPss(IApplicationThread caller, int pss) {
8432 Watchdog.PssRequestor req;
8433 String name;
8434 ProcessRecord callerApp;
8435 synchronized (this) {
8436 if (caller == null) {
8437 return;
8438 }
8439 callerApp = getRecordForAppLocked(caller);
8440 if (callerApp == null) {
8441 return;
8442 }
8443 callerApp.lastPss = pss;
8444 req = callerApp;
8445 name = callerApp.processName;
8446 }
8447 Watchdog.getInstance().reportPss(req, name, pss);
8448 if (!callerApp.persistent) {
8449 removeRequestedPss(callerApp);
8450 }
8451 }
8452
8453 public void requestPss(Runnable completeCallback) {
8454 ArrayList<ProcessRecord> procs;
8455 synchronized (this) {
8456 mRequestPssCallback = completeCallback;
8457 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008458 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8459 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008460 if (!proc.persistent) {
8461 mRequestPssList.add(proc);
8462 }
8463 }
8464 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8465 }
8466
8467 int oldPri = Process.getThreadPriority(Process.myTid());
8468 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8469 for (int i=procs.size()-1; i>=0; i--) {
8470 ProcessRecord proc = procs.get(i);
8471 proc.lastPss = 0;
8472 proc.requestPss();
8473 }
8474 Process.setThreadPriority(oldPri);
8475 }
8476
8477 void removeRequestedPss(ProcessRecord proc) {
8478 Runnable callback = null;
8479 synchronized (this) {
8480 if (mRequestPssList.remove(proc)) {
8481 if (mRequestPssList.size() == 0) {
8482 callback = mRequestPssCallback;
8483 mRequestPssCallback = null;
8484 }
8485 }
8486 }
8487
8488 if (callback != null) {
8489 callback.run();
8490 }
8491 }
8492
8493 public void collectPss(Watchdog.PssStats stats) {
8494 stats.mEmptyPss = 0;
8495 stats.mEmptyCount = 0;
8496 stats.mBackgroundPss = 0;
8497 stats.mBackgroundCount = 0;
8498 stats.mServicePss = 0;
8499 stats.mServiceCount = 0;
8500 stats.mVisiblePss = 0;
8501 stats.mVisibleCount = 0;
8502 stats.mForegroundPss = 0;
8503 stats.mForegroundCount = 0;
8504 stats.mNoPssCount = 0;
8505 synchronized (this) {
8506 int i;
8507 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8508 ? mProcDeaths.length : stats.mProcDeaths.length;
8509 int aggr = 0;
8510 for (i=0; i<NPD; i++) {
8511 aggr += mProcDeaths[i];
8512 stats.mProcDeaths[i] = aggr;
8513 }
8514 while (i<stats.mProcDeaths.length) {
8515 stats.mProcDeaths[i] = 0;
8516 i++;
8517 }
8518
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008519 for (i=mLruProcesses.size()-1; i>=0; i--) {
8520 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008521 if (proc.persistent) {
8522 continue;
8523 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008524 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008525 if (proc.lastPss == 0) {
8526 stats.mNoPssCount++;
8527 continue;
8528 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008529 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8530 if (proc.empty) {
8531 stats.mEmptyPss += proc.lastPss;
8532 stats.mEmptyCount++;
8533 } else {
8534 stats.mBackgroundPss += proc.lastPss;
8535 stats.mBackgroundCount++;
8536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8538 stats.mVisiblePss += proc.lastPss;
8539 stats.mVisibleCount++;
8540 } else {
8541 stats.mForegroundPss += proc.lastPss;
8542 stats.mForegroundCount++;
8543 }
8544 }
8545 }
8546 }
8547
8548 public final void startRunning(String pkg, String cls, String action,
8549 String data) {
8550 synchronized(this) {
8551 if (mStartRunning) {
8552 return;
8553 }
8554 mStartRunning = true;
8555 mTopComponent = pkg != null && cls != null
8556 ? new ComponentName(pkg, cls) : null;
8557 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8558 mTopData = data;
8559 if (!mSystemReady) {
8560 return;
8561 }
8562 }
8563
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008564 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008565 }
8566
8567 private void retrieveSettings() {
8568 final ContentResolver resolver = mContext.getContentResolver();
8569 String debugApp = Settings.System.getString(
8570 resolver, Settings.System.DEBUG_APP);
8571 boolean waitForDebugger = Settings.System.getInt(
8572 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8573 boolean alwaysFinishActivities = Settings.System.getInt(
8574 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8575
8576 Configuration configuration = new Configuration();
8577 Settings.System.getConfiguration(resolver, configuration);
8578
8579 synchronized (this) {
8580 mDebugApp = mOrigDebugApp = debugApp;
8581 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8582 mAlwaysFinishActivities = alwaysFinishActivities;
8583 // This happens before any activities are started, so we can
8584 // change mConfiguration in-place.
8585 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008586 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008587 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008588 }
8589 }
8590
8591 public boolean testIsSystemReady() {
8592 // no need to synchronize(this) just to read & return the value
8593 return mSystemReady;
8594 }
8595
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008596 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008597 // In the simulator, startRunning will never have been called, which
8598 // normally sets a few crucial variables. Do it here instead.
8599 if (!Process.supportsProcesses()) {
8600 mStartRunning = true;
8601 mTopAction = Intent.ACTION_MAIN;
8602 }
8603
8604 synchronized(this) {
8605 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008606 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008607 return;
8608 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008609
8610 // Check to see if there are any update receivers to run.
8611 if (!mDidUpdate) {
8612 if (mWaitingUpdate) {
8613 return;
8614 }
8615 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8616 List<ResolveInfo> ris = null;
8617 try {
8618 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8619 intent, null, 0);
8620 } catch (RemoteException e) {
8621 }
8622 if (ris != null) {
8623 for (int i=ris.size()-1; i>=0; i--) {
8624 if ((ris.get(i).activityInfo.applicationInfo.flags
8625 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8626 ris.remove(i);
8627 }
8628 }
8629 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8630 for (int i=0; i<ris.size(); i++) {
8631 ActivityInfo ai = ris.get(i).activityInfo;
8632 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8633 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008634 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008635 finisher = new IIntentReceiver.Stub() {
8636 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008637 String data, Bundle extras, boolean ordered,
8638 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008639 throws RemoteException {
8640 synchronized (ActivityManagerService.this) {
8641 mDidUpdate = true;
8642 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008643 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008644 }
8645 };
8646 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008647 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008648 broadcastIntentLocked(null, null, intent, null, finisher,
8649 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008650 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008651 mWaitingUpdate = true;
8652 }
8653 }
8654 }
8655 if (mWaitingUpdate) {
8656 return;
8657 }
8658 mDidUpdate = true;
8659 }
8660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008661 mSystemReady = true;
8662 if (!mStartRunning) {
8663 return;
8664 }
8665 }
8666
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008667 ArrayList<ProcessRecord> procsToKill = null;
8668 synchronized(mPidsSelfLocked) {
8669 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8670 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8671 if (!isAllowedWhileBooting(proc.info)){
8672 if (procsToKill == null) {
8673 procsToKill = new ArrayList<ProcessRecord>();
8674 }
8675 procsToKill.add(proc);
8676 }
8677 }
8678 }
8679
8680 if (procsToKill != null) {
8681 synchronized(this) {
8682 for (int i=procsToKill.size()-1; i>=0; i--) {
8683 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008684 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008685 removeProcessLocked(proc, true);
8686 }
8687 }
8688 }
8689
Joe Onorato8a9b2202010-02-26 18:56:32 -08008690 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008691 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008692 SystemClock.uptimeMillis());
8693
8694 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008695 // Make sure we have no pre-ready processes sitting around.
8696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008697 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8698 ResolveInfo ri = mContext.getPackageManager()
8699 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008700 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008701 CharSequence errorMsg = null;
8702 if (ri != null) {
8703 ActivityInfo ai = ri.activityInfo;
8704 ApplicationInfo app = ai.applicationInfo;
8705 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8706 mTopAction = Intent.ACTION_FACTORY_TEST;
8707 mTopData = null;
8708 mTopComponent = new ComponentName(app.packageName,
8709 ai.name);
8710 } else {
8711 errorMsg = mContext.getResources().getText(
8712 com.android.internal.R.string.factorytest_not_system);
8713 }
8714 } else {
8715 errorMsg = mContext.getResources().getText(
8716 com.android.internal.R.string.factorytest_no_action);
8717 }
8718 if (errorMsg != null) {
8719 mTopAction = null;
8720 mTopData = null;
8721 mTopComponent = null;
8722 Message msg = Message.obtain();
8723 msg.what = SHOW_FACTORY_ERROR_MSG;
8724 msg.getData().putCharSequence("msg", errorMsg);
8725 mHandler.sendMessage(msg);
8726 }
8727 }
8728 }
8729
8730 retrieveSettings();
8731
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008732 if (goingCallback != null) goingCallback.run();
8733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008734 synchronized (this) {
8735 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8736 try {
8737 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008738 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008739 if (apps != null) {
8740 int N = apps.size();
8741 int i;
8742 for (i=0; i<N; i++) {
8743 ApplicationInfo info
8744 = (ApplicationInfo)apps.get(i);
8745 if (info != null &&
8746 !info.packageName.equals("android")) {
8747 addAppLocked(info);
8748 }
8749 }
8750 }
8751 } catch (RemoteException ex) {
8752 // pm is in same process, this will never happen.
8753 }
8754 }
8755
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008756 // Start up initial activity.
8757 mBooting = true;
8758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 try {
8760 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8761 Message msg = Message.obtain();
8762 msg.what = SHOW_UID_ERROR_MSG;
8763 mHandler.sendMessage(msg);
8764 }
8765 } catch (RemoteException e) {
8766 }
8767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008768 resumeTopActivityLocked(null);
8769 }
8770 }
8771
Dan Egnorb7f03672009-12-09 16:22:32 -08008772 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008773 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008774 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008775 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008776 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008777 startAppProblemLocked(app);
8778 app.stopFreezingAllLocked();
8779 return handleAppCrashLocked(app);
8780 }
8781
Dan Egnorb7f03672009-12-09 16:22:32 -08008782 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008783 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008784 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008785 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008786 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8787 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 startAppProblemLocked(app);
8789 app.stopFreezingAllLocked();
8790 }
8791
8792 /**
8793 * Generate a process error record, suitable for attachment to a ProcessRecord.
8794 *
8795 * @param app The ProcessRecord in which the error occurred.
8796 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8797 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008798 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008799 * @param shortMsg Short message describing the crash.
8800 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008801 * @param stackTrace Full crash stack trace, may be null.
8802 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008803 * @return Returns a fully-formed AppErrorStateInfo record.
8804 */
8805 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008806 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008809 report.condition = condition;
8810 report.processName = app.processName;
8811 report.pid = app.pid;
8812 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008813 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008814 report.shortMsg = shortMsg;
8815 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008816 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008817
8818 return report;
8819 }
8820
Dan Egnor42471dd2010-01-07 17:25:22 -08008821 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008822 synchronized (this) {
8823 app.crashing = false;
8824 app.crashingReport = null;
8825 app.notResponding = false;
8826 app.notRespondingReport = null;
8827 if (app.anrDialog == fromDialog) {
8828 app.anrDialog = null;
8829 }
8830 if (app.waitDialog == fromDialog) {
8831 app.waitDialog = null;
8832 }
8833 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008834 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008835 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008836 + app.processName
8837 + " (pid=" + app.pid + ") at user's request");
8838 Process.killProcess(app.pid);
8839 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008840 }
8841 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008842
Dan Egnorb7f03672009-12-09 16:22:32 -08008843 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008844 long now = SystemClock.uptimeMillis();
8845
8846 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8847 app.info.uid);
8848 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8849 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008850 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008851 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008852 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008853 app.info.processName, app.info.uid);
8854 killServicesLocked(app, false);
8855 for (int i=mHistory.size()-1; i>=0; i--) {
8856 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8857 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008858 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008859 + r.intent.getComponent().flattenToShortString());
8860 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8861 }
8862 }
8863 if (!app.persistent) {
8864 // We don't want to start this process again until the user
8865 // explicitly does so... but for persistent process, we really
8866 // need to keep it running. If a persistent process is actually
8867 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008868 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008869 app.info.processName);
8870 mBadProcesses.put(app.info.processName, app.info.uid, now);
8871 app.bad = true;
8872 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8873 app.removed = true;
8874 removeProcessLocked(app, false);
8875 return false;
8876 }
8877 }
8878
8879 // Bump up the crash count of any services currently running in the proc.
8880 if (app.services.size() != 0) {
8881 // Any services running in the application need to be placed
8882 // back in the pending list.
8883 Iterator it = app.services.iterator();
8884 while (it.hasNext()) {
8885 ServiceRecord sr = (ServiceRecord)it.next();
8886 sr.crashCount++;
8887 }
8888 }
8889
8890 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8891 return true;
8892 }
8893
8894 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008895 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8896 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008897 skipCurrentReceiverLocked(app);
8898 }
8899
8900 void skipCurrentReceiverLocked(ProcessRecord app) {
8901 boolean reschedule = false;
8902 BroadcastRecord r = app.curReceiver;
8903 if (r != null) {
8904 // The current broadcast is waiting for this app's receiver
8905 // to be finished. Looks like that's not going to happen, so
8906 // let the broadcast continue.
8907 logBroadcastReceiverDiscard(r);
8908 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8909 r.resultExtras, r.resultAbort, true);
8910 reschedule = true;
8911 }
8912 r = mPendingBroadcast;
8913 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008914 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008915 "skip & discard pending app " + r);
8916 logBroadcastReceiverDiscard(r);
8917 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8918 r.resultExtras, r.resultAbort, true);
8919 reschedule = true;
8920 }
8921 if (reschedule) {
8922 scheduleBroadcastsLocked();
8923 }
8924 }
8925
Dan Egnor60d87622009-12-16 16:32:58 -08008926 /**
8927 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8928 * The application process will exit immediately after this call returns.
8929 * @param app object of the crashing app, null for the system server
8930 * @param crashInfo describing the exception
8931 */
8932 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8933 ProcessRecord r = findAppProcess(app);
8934
8935 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8936 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008937 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008938 crashInfo.exceptionClassName,
8939 crashInfo.exceptionMessage,
8940 crashInfo.throwFileName,
8941 crashInfo.throwLineNumber);
8942
Dan Egnor42471dd2010-01-07 17:25:22 -08008943 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008944
8945 crashApplication(r, crashInfo);
8946 }
8947
8948 /**
8949 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8950 * @param app object of the crashing app, null for the system server
8951 * @param tag reported by the caller
8952 * @param crashInfo describing the context of the error
8953 * @return true if the process should exit immediately (WTF is fatal)
8954 */
8955 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008956 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008957 ProcessRecord r = findAppProcess(app);
8958
8959 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8960 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008961 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008962 tag, crashInfo.exceptionMessage);
8963
Dan Egnor42471dd2010-01-07 17:25:22 -08008964 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008965
Doug Zongker43866e02010-01-07 12:09:54 -08008966 if (Settings.Secure.getInt(mContext.getContentResolver(),
8967 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008968 crashApplication(r, crashInfo);
8969 return true;
8970 } else {
8971 return false;
8972 }
8973 }
8974
8975 /**
8976 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8977 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8978 */
8979 private ProcessRecord findAppProcess(IBinder app) {
8980 if (app == null) {
8981 return null;
8982 }
8983
8984 synchronized (this) {
8985 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8986 final int NA = apps.size();
8987 for (int ia=0; ia<NA; ia++) {
8988 ProcessRecord p = apps.valueAt(ia);
8989 if (p.thread != null && p.thread.asBinder() == app) {
8990 return p;
8991 }
8992 }
8993 }
8994
Joe Onorato8a9b2202010-02-26 18:56:32 -08008995 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008996 return null;
8997 }
8998 }
8999
9000 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009001 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009002 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009003 * @param process which caused the error, null means the system server
9004 * @param activity which triggered the error, null if unknown
9005 * @param parent activity related to the error, null if unknown
9006 * @param subject line related to the error, null if absent
9007 * @param report in long form describing the error, null if absent
9008 * @param logFile to include in the report, null if none
9009 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009010 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009011 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009012 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9013 final String report, final File logFile,
9014 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009015 // NOTE -- this must never acquire the ActivityManagerService lock,
9016 // otherwise the watchdog may be prevented from resetting the system.
9017
Dan Egnora455d192010-03-12 08:52:28 -08009018 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009019 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009020 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009021 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009022 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009023 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009024 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009025 }
9026
Dan Egnora455d192010-03-12 08:52:28 -08009027 final String dropboxTag = prefix + eventType;
9028 final DropBoxManager dbox = (DropBoxManager)
9029 mContext.getSystemService(Context.DROPBOX_SERVICE);
9030
9031 // Exit early if the dropbox isn't configured to accept this report type.
9032 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9033
9034 final StringBuilder sb = new StringBuilder(1024);
9035 if (process == null || process.pid == MY_PID) {
9036 sb.append("Process: system_server\n");
9037 } else {
9038 sb.append("Process: ").append(process.processName).append("\n");
9039 }
9040 if (process != null) {
9041 int flags = process.info.flags;
9042 IPackageManager pm = ActivityThread.getPackageManager();
9043 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9044 for (String pkg : process.pkgList) {
9045 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009046 try {
Dan Egnora455d192010-03-12 08:52:28 -08009047 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9048 if (pi != null) {
9049 sb.append(" v").append(pi.versionCode);
9050 if (pi.versionName != null) {
9051 sb.append(" (").append(pi.versionName).append(")");
9052 }
9053 }
9054 } catch (RemoteException e) {
9055 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009056 }
Dan Egnora455d192010-03-12 08:52:28 -08009057 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009058 }
Dan Egnora455d192010-03-12 08:52:28 -08009059 }
9060 if (activity != null) {
9061 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9062 }
9063 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9064 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9065 }
9066 if (parent != null && parent != activity) {
9067 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9068 }
9069 if (subject != null) {
9070 sb.append("Subject: ").append(subject).append("\n");
9071 }
9072 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9073 sb.append("\n");
9074
9075 // Do the rest in a worker thread to avoid blocking the caller on I/O
9076 // (After this point, we shouldn't access AMS internal data structures.)
9077 Thread worker = new Thread("Error dump: " + dropboxTag) {
9078 @Override
9079 public void run() {
9080 if (report != null) {
9081 sb.append(report);
9082 }
9083 if (logFile != null) {
9084 try {
9085 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9086 } catch (IOException e) {
9087 Slog.e(TAG, "Error reading " + logFile, e);
9088 }
9089 }
9090 if (crashInfo != null && crashInfo.stackTrace != null) {
9091 sb.append(crashInfo.stackTrace);
9092 }
9093
9094 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9095 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9096 if (lines > 0) {
9097 sb.append("\n");
9098
9099 // Merge several logcat streams, and take the last N lines
9100 InputStreamReader input = null;
9101 try {
9102 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9103 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9104 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9105
9106 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9107 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9108 input = new InputStreamReader(logcat.getInputStream());
9109
9110 int num;
9111 char[] buf = new char[8192];
9112 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9113 } catch (IOException e) {
9114 Slog.e(TAG, "Error running logcat", e);
9115 } finally {
9116 if (input != null) try { input.close(); } catch (IOException e) {}
9117 }
9118 }
9119
9120 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009121 }
Dan Egnora455d192010-03-12 08:52:28 -08009122 };
9123
9124 if (process == null || process.pid == MY_PID) {
9125 worker.run(); // We may be about to die -- need to run this synchronously
9126 } else {
9127 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009128 }
9129 }
9130
9131 /**
9132 * Bring up the "unexpected error" dialog box for a crashing app.
9133 * Deal with edge cases (intercepts from instrumented applications,
9134 * ActivityController, error intent receivers, that sort of thing).
9135 * @param r the application crashing
9136 * @param crashInfo describing the failure
9137 */
9138 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009139 long timeMillis = System.currentTimeMillis();
9140 String shortMsg = crashInfo.exceptionClassName;
9141 String longMsg = crashInfo.exceptionMessage;
9142 String stackTrace = crashInfo.stackTrace;
9143 if (shortMsg != null && longMsg != null) {
9144 longMsg = shortMsg + ": " + longMsg;
9145 } else if (shortMsg != null) {
9146 longMsg = shortMsg;
9147 }
9148
Dan Egnor60d87622009-12-16 16:32:58 -08009149 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009150 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009151 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009152 try {
9153 String name = r != null ? r.processName : null;
9154 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009155 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009156 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009157 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 + " at watcher's request");
9159 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009160 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009161 }
9162 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009163 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009164 }
9165 }
9166
9167 final long origId = Binder.clearCallingIdentity();
9168
9169 // If this process is running instrumentation, finish it.
9170 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009171 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009172 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009173 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9174 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009175 Bundle info = new Bundle();
9176 info.putString("shortMsg", shortMsg);
9177 info.putString("longMsg", longMsg);
9178 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9179 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009180 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 }
9182
Dan Egnor60d87622009-12-16 16:32:58 -08009183 // If we can't identify the process or it's already exceeded its crash quota,
9184 // quit right away without showing a crash dialog.
9185 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009187 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009188 }
9189
9190 Message msg = Message.obtain();
9191 msg.what = SHOW_ERROR_MSG;
9192 HashMap data = new HashMap();
9193 data.put("result", result);
9194 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009195 msg.obj = data;
9196 mHandler.sendMessage(msg);
9197
9198 Binder.restoreCallingIdentity(origId);
9199 }
9200
9201 int res = result.get();
9202
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009203 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009204 synchronized (this) {
9205 if (r != null) {
9206 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9207 SystemClock.uptimeMillis());
9208 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009209 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009210 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009211 }
9212 }
9213
9214 if (appErrorIntent != null) {
9215 try {
9216 mContext.startActivity(appErrorIntent);
9217 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009218 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009222
9223 Intent createAppErrorIntentLocked(ProcessRecord r,
9224 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9225 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009226 if (report == null) {
9227 return null;
9228 }
9229 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9230 result.setComponent(r.errorReportReceiver);
9231 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9232 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9233 return result;
9234 }
9235
Dan Egnorb7f03672009-12-09 16:22:32 -08009236 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9237 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009238 if (r.errorReportReceiver == null) {
9239 return null;
9240 }
9241
9242 if (!r.crashing && !r.notResponding) {
9243 return null;
9244 }
9245
Dan Egnorb7f03672009-12-09 16:22:32 -08009246 ApplicationErrorReport report = new ApplicationErrorReport();
9247 report.packageName = r.info.packageName;
9248 report.installerPackageName = r.errorReportReceiver.getPackageName();
9249 report.processName = r.processName;
9250 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009251 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009252
Dan Egnorb7f03672009-12-09 16:22:32 -08009253 if (r.crashing) {
9254 report.type = ApplicationErrorReport.TYPE_CRASH;
9255 report.crashInfo = crashInfo;
9256 } else if (r.notResponding) {
9257 report.type = ApplicationErrorReport.TYPE_ANR;
9258 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009259
Dan Egnorb7f03672009-12-09 16:22:32 -08009260 report.anrInfo.activity = r.notRespondingReport.tag;
9261 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9262 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009263 }
9264
Dan Egnorb7f03672009-12-09 16:22:32 -08009265 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009266 }
9267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009268 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9269 // assume our apps are happy - lazy create the list
9270 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9271
9272 synchronized (this) {
9273
9274 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009275 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9276 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009277 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9278 // This one's in trouble, so we'll generate a report for it
9279 // crashes are higher priority (in case there's a crash *and* an anr)
9280 ActivityManager.ProcessErrorStateInfo report = null;
9281 if (app.crashing) {
9282 report = app.crashingReport;
9283 } else if (app.notResponding) {
9284 report = app.notRespondingReport;
9285 }
9286
9287 if (report != null) {
9288 if (errList == null) {
9289 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9290 }
9291 errList.add(report);
9292 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009293 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009294 " crashing = " + app.crashing +
9295 " notResponding = " + app.notResponding);
9296 }
9297 }
9298 }
9299 }
9300
9301 return errList;
9302 }
9303
9304 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9305 // Lazy instantiation of list
9306 List<ActivityManager.RunningAppProcessInfo> runList = null;
9307 synchronized (this) {
9308 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009309 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9310 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009311 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9312 // Generate process state info for running application
9313 ActivityManager.RunningAppProcessInfo currApp =
9314 new ActivityManager.RunningAppProcessInfo(app.processName,
9315 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009316 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009317 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009318 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009319 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9320 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9321 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009322 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9323 } else if (adj >= HOME_APP_ADJ) {
9324 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9325 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 } else if (adj >= SECONDARY_SERVER_ADJ) {
9327 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9328 } else if (adj >= VISIBLE_APP_ADJ) {
9329 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9330 } else {
9331 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9332 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009333 currApp.importanceReasonCode = app.adjTypeCode;
9334 if (app.adjSource instanceof ProcessRecord) {
9335 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9336 } else if (app.adjSource instanceof HistoryRecord) {
9337 HistoryRecord r = (HistoryRecord)app.adjSource;
9338 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9339 }
9340 if (app.adjTarget instanceof ComponentName) {
9341 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9342 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009343 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009344 // + " lru=" + currApp.lru);
9345 if (runList == null) {
9346 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9347 }
9348 runList.add(currApp);
9349 }
9350 }
9351 }
9352 return runList;
9353 }
9354
9355 @Override
9356 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009357 if (checkCallingPermission(android.Manifest.permission.DUMP)
9358 != PackageManager.PERMISSION_GRANTED) {
9359 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9360 + Binder.getCallingPid()
9361 + ", uid=" + Binder.getCallingUid()
9362 + " without permission "
9363 + android.Manifest.permission.DUMP);
9364 return;
9365 }
9366
9367 boolean dumpAll = false;
9368
9369 int opti = 0;
9370 while (opti < args.length) {
9371 String opt = args[opti];
9372 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9373 break;
9374 }
9375 opti++;
9376 if ("-a".equals(opt)) {
9377 dumpAll = true;
9378 } else if ("-h".equals(opt)) {
9379 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009380 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009381 pw.println(" cmd may be one of:");
9382 pw.println(" activities: activity stack state");
9383 pw.println(" broadcasts: broadcast state");
9384 pw.println(" intents: pending intent state");
9385 pw.println(" processes: process state");
9386 pw.println(" providers: content provider state");
9387 pw.println(" services: service state");
9388 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009389 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009390 } else {
9391 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009392 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009393 }
9394
9395 // Is the caller requesting to dump a particular piece of data?
9396 if (opti < args.length) {
9397 String cmd = args[opti];
9398 opti++;
9399 if ("activities".equals(cmd) || "a".equals(cmd)) {
9400 synchronized (this) {
9401 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009402 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009403 return;
9404 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9405 synchronized (this) {
9406 dumpBroadcastsLocked(fd, pw, args, opti, true);
9407 }
9408 return;
9409 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9410 synchronized (this) {
9411 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9412 }
9413 return;
9414 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9415 synchronized (this) {
9416 dumpProcessesLocked(fd, pw, args, opti, true);
9417 }
9418 return;
9419 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9420 synchronized (this) {
9421 dumpProvidersLocked(fd, pw, args, opti, true);
9422 }
9423 return;
9424 } else if ("service".equals(cmd)) {
9425 dumpService(fd, pw, args, opti, true);
9426 return;
9427 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9428 synchronized (this) {
9429 dumpServicesLocked(fd, pw, args, opti, true);
9430 }
9431 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009432 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009433 }
9434
9435 // No piece of data specified, dump everything.
9436 synchronized (this) {
9437 boolean needSep;
9438 if (dumpAll) {
9439 pw.println("Providers in Current Activity Manager State:");
9440 }
9441 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9442 if (needSep) {
9443 pw.println(" ");
9444 }
9445 if (dumpAll) {
9446 pw.println("-------------------------------------------------------------------------------");
9447 pw.println("Broadcasts in Current Activity Manager State:");
9448 }
9449 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9450 if (needSep) {
9451 pw.println(" ");
9452 }
9453 if (dumpAll) {
9454 pw.println("-------------------------------------------------------------------------------");
9455 pw.println("Services in Current Activity Manager State:");
9456 }
9457 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9458 if (needSep) {
9459 pw.println(" ");
9460 }
9461 if (dumpAll) {
9462 pw.println("-------------------------------------------------------------------------------");
9463 pw.println("PendingIntents in Current Activity Manager State:");
9464 }
9465 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9466 if (needSep) {
9467 pw.println(" ");
9468 }
9469 if (dumpAll) {
9470 pw.println("-------------------------------------------------------------------------------");
9471 pw.println("Activities in Current Activity Manager State:");
9472 }
9473 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9474 if (needSep) {
9475 pw.println(" ");
9476 }
9477 if (dumpAll) {
9478 pw.println("-------------------------------------------------------------------------------");
9479 pw.println("Processes in Current Activity Manager State:");
9480 }
9481 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9482 }
9483 }
9484
9485 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9486 int opti, boolean dumpAll, boolean needHeader) {
9487 if (needHeader) {
9488 pw.println(" Activity stack:");
9489 }
9490 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9491 pw.println(" ");
9492 pw.println(" Running activities (most recent first):");
9493 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9494 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009495 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009496 pw.println(" Activities waiting for another to become visible:");
9497 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9498 }
9499 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009500 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009501 pw.println(" Activities waiting to stop:");
9502 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9503 }
9504 if (mFinishingActivities.size() > 0) {
9505 pw.println(" ");
9506 pw.println(" Activities waiting to finish:");
9507 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009509
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009510 pw.println(" ");
9511 pw.println(" mPausingActivity: " + mPausingActivity);
9512 pw.println(" mResumedActivity: " + mResumedActivity);
9513 pw.println(" mFocusedActivity: " + mFocusedActivity);
9514 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009515
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009516 if (dumpAll && mRecentTasks.size() > 0) {
9517 pw.println(" ");
9518 pw.println("Recent tasks in Current Activity Manager State:");
9519
9520 final int N = mRecentTasks.size();
9521 for (int i=0; i<N; i++) {
9522 TaskRecord tr = mRecentTasks.get(i);
9523 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9524 pw.println(tr);
9525 mRecentTasks.get(i).dump(pw, " ");
9526 }
9527 }
9528
9529 pw.println(" ");
9530 pw.println(" mCurTask: " + mCurTask);
9531
9532 return true;
9533 }
9534
9535 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9536 int opti, boolean dumpAll) {
9537 boolean needSep = false;
9538 int numPers = 0;
9539
9540 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009541 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9542 final int NA = procs.size();
9543 for (int ia=0; ia<NA; ia++) {
9544 if (!needSep) {
9545 pw.println(" All known processes:");
9546 needSep = true;
9547 }
9548 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009549 pw.print(r.persistent ? " *PERS*" : " *APP*");
9550 pw.print(" UID "); pw.print(procs.keyAt(ia));
9551 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009552 r.dump(pw, " ");
9553 if (r.persistent) {
9554 numPers++;
9555 }
9556 }
9557 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009558 }
9559
9560 if (mLruProcesses.size() > 0) {
9561 if (needSep) pw.println(" ");
9562 needSep = true;
9563 pw.println(" Running processes (most recent first):");
9564 dumpProcessList(pw, this, mLruProcesses, " ",
9565 "App ", "PERS", true);
9566 needSep = true;
9567 }
9568
9569 synchronized (mPidsSelfLocked) {
9570 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009571 if (needSep) pw.println(" ");
9572 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009573 pw.println(" PID mappings:");
9574 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9575 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9576 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577 }
9578 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009579 }
9580
9581 if (mForegroundProcesses.size() > 0) {
9582 if (needSep) pw.println(" ");
9583 needSep = true;
9584 pw.println(" Foreground Processes:");
9585 for (int i=0; i<mForegroundProcesses.size(); i++) {
9586 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9587 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009588 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009589 }
9590
9591 if (mPersistentStartingProcesses.size() > 0) {
9592 if (needSep) pw.println(" ");
9593 needSep = true;
9594 pw.println(" Persisent processes that are starting:");
9595 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9596 "Starting Norm", "Restarting PERS", false);
9597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009599 if (mStartingProcesses.size() > 0) {
9600 if (needSep) pw.println(" ");
9601 needSep = true;
9602 pw.println(" Processes that are starting:");
9603 dumpProcessList(pw, this, mStartingProcesses, " ",
9604 "Starting Norm", "Starting PERS", false);
9605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009606
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009607 if (mRemovedProcesses.size() > 0) {
9608 if (needSep) pw.println(" ");
9609 needSep = true;
9610 pw.println(" Processes that are being removed:");
9611 dumpProcessList(pw, this, mRemovedProcesses, " ",
9612 "Removed Norm", "Removed PERS", false);
9613 }
9614
9615 if (mProcessesOnHold.size() > 0) {
9616 if (needSep) pw.println(" ");
9617 needSep = true;
9618 pw.println(" Processes that are on old until the system is ready:");
9619 dumpProcessList(pw, this, mProcessesOnHold, " ",
9620 "OnHold Norm", "OnHold PERS", false);
9621 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009622
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009623 if (mProcessesToGc.size() > 0) {
9624 if (needSep) pw.println(" ");
9625 needSep = true;
9626 pw.println(" Processes that are waiting to GC:");
9627 long now = SystemClock.uptimeMillis();
9628 for (int i=0; i<mProcessesToGc.size(); i++) {
9629 ProcessRecord proc = mProcessesToGc.get(i);
9630 pw.print(" Process "); pw.println(proc);
9631 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9632 pw.print(", last gced=");
9633 pw.print(now-proc.lastRequestedGc);
9634 pw.print(" ms ago, last lowMem=");
9635 pw.print(now-proc.lastLowMemory);
9636 pw.println(" ms ago");
9637
9638 }
9639 }
9640
9641 if (mProcessCrashTimes.getMap().size() > 0) {
9642 if (needSep) pw.println(" ");
9643 needSep = true;
9644 pw.println(" Time since processes crashed:");
9645 long now = SystemClock.uptimeMillis();
9646 for (Map.Entry<String, SparseArray<Long>> procs
9647 : mProcessCrashTimes.getMap().entrySet()) {
9648 SparseArray<Long> uids = procs.getValue();
9649 final int N = uids.size();
9650 for (int i=0; i<N; i++) {
9651 pw.print(" Process "); pw.print(procs.getKey());
9652 pw.print(" uid "); pw.print(uids.keyAt(i));
9653 pw.print(": last crashed ");
9654 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009655 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009656 }
9657 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009659
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009660 if (mBadProcesses.getMap().size() > 0) {
9661 if (needSep) pw.println(" ");
9662 needSep = true;
9663 pw.println(" Bad processes:");
9664 for (Map.Entry<String, SparseArray<Long>> procs
9665 : mBadProcesses.getMap().entrySet()) {
9666 SparseArray<Long> uids = procs.getValue();
9667 final int N = uids.size();
9668 for (int i=0; i<N; i++) {
9669 pw.print(" Bad process "); pw.print(procs.getKey());
9670 pw.print(" uid "); pw.print(uids.keyAt(i));
9671 pw.print(": crashed at time ");
9672 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009673 }
9674 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009677 pw.println(" ");
9678 pw.println(" mHomeProcess: " + mHomeProcess);
9679 pw.println(" mConfiguration: " + mConfiguration);
9680 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9681 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9682 || mOrigWaitForDebugger) {
9683 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9684 + " mDebugTransient=" + mDebugTransient
9685 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9686 }
9687 if (mAlwaysFinishActivities || mController != null) {
9688 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9689 + " mController=" + mController);
9690 }
9691 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009693 pw.println(" mStartRunning=" + mStartRunning
9694 + " mSystemReady=" + mSystemReady
9695 + " mBooting=" + mBooting
9696 + " mBooted=" + mBooted
9697 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698 pw.println(" mGoingToSleep=" + mGoingToSleep);
9699 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009701
9702 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009703 }
9704
9705 /**
9706 * There are three ways to call this:
9707 * - no service specified: dump all the services
9708 * - a flattened component name that matched an existing service was specified as the
9709 * first arg: dump that one service
9710 * - the first arg isn't the flattened component name of an existing service:
9711 * dump all services whose component contains the first arg as a substring
9712 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009713 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9714 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009715 String[] newArgs;
9716 String componentNameString;
9717 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009718 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009719 componentNameString = null;
9720 newArgs = EMPTY_STRING_ARRAY;
9721 r = null;
9722 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009723 componentNameString = args[opti];
9724 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009725 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9726 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009727 newArgs = new String[args.length - opti];
9728 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009729 }
9730
9731 if (r != null) {
9732 dumpService(fd, pw, r, newArgs);
9733 } else {
9734 for (ServiceRecord r1 : mServices.values()) {
9735 if (componentNameString == null
9736 || r1.name.flattenToString().contains(componentNameString)) {
9737 dumpService(fd, pw, r1, newArgs);
9738 }
9739 }
9740 }
9741 }
9742
9743 /**
9744 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9745 * there is a thread associated with the service.
9746 */
9747 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9748 pw.println(" Service " + r.name.flattenToString());
9749 if (r.app != null && r.app.thread != null) {
9750 try {
9751 // flush anything that is already in the PrintWriter since the thread is going
9752 // to write to the file descriptor directly
9753 pw.flush();
9754 r.app.thread.dumpService(fd, r, args);
9755 pw.print("\n");
9756 } catch (RemoteException e) {
9757 pw.println("got a RemoteException while dumping the service");
9758 }
9759 }
9760 }
9761
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009762 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9763 int opti, boolean dumpAll) {
9764 boolean needSep = false;
9765
9766 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009767 if (mRegisteredReceivers.size() > 0) {
9768 pw.println(" ");
9769 pw.println(" Registered Receivers:");
9770 Iterator it = mRegisteredReceivers.values().iterator();
9771 while (it.hasNext()) {
9772 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009773 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009774 r.dump(pw, " ");
9775 }
9776 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009778 pw.println(" ");
9779 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009780 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009781 needSep = true;
9782 }
9783
9784 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9785 || mPendingBroadcast != null) {
9786 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009787 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009788 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009789 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009790 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9791 pw.println(" Broadcast #" + i + ":");
9792 mParallelBroadcasts.get(i).dump(pw, " ");
9793 }
9794 if (mOrderedBroadcasts.size() > 0) {
9795 pw.println(" ");
9796 pw.println(" Active serialized broadcasts:");
9797 }
9798 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9799 pw.println(" Serialized Broadcast #" + i + ":");
9800 mOrderedBroadcasts.get(i).dump(pw, " ");
9801 }
9802 pw.println(" ");
9803 pw.println(" Pending broadcast:");
9804 if (mPendingBroadcast != null) {
9805 mPendingBroadcast.dump(pw, " ");
9806 } else {
9807 pw.println(" (null)");
9808 }
9809 needSep = true;
9810 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009811
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009812 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009814 pw.println(" Historical broadcasts:");
9815 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9816 BroadcastRecord r = mBroadcastHistory[i];
9817 if (r == null) {
9818 break;
9819 }
9820 pw.println(" Historical Broadcast #" + i + ":");
9821 r.dump(pw, " ");
9822 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009823 needSep = true;
9824 }
9825
9826 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009827 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009828 pw.println(" Sticky broadcasts:");
9829 StringBuilder sb = new StringBuilder(128);
9830 for (Map.Entry<String, ArrayList<Intent>> ent
9831 : mStickyBroadcasts.entrySet()) {
9832 pw.print(" * Sticky action "); pw.print(ent.getKey());
9833 pw.println(":");
9834 ArrayList<Intent> intents = ent.getValue();
9835 final int N = intents.size();
9836 for (int i=0; i<N; i++) {
9837 sb.setLength(0);
9838 sb.append(" Intent: ");
9839 intents.get(i).toShortString(sb, true, false);
9840 pw.println(sb.toString());
9841 Bundle bundle = intents.get(i).getExtras();
9842 if (bundle != null) {
9843 pw.print(" ");
9844 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009845 }
9846 }
9847 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009848 needSep = true;
9849 }
9850
9851 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009852 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009853 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009854 pw.println(" mHandler:");
9855 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009856 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009857 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009858
9859 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860 }
9861
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009862 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9863 int opti, boolean dumpAll) {
9864 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009866 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009867 if (mServices.size() > 0) {
9868 pw.println(" Active services:");
9869 Iterator<ServiceRecord> it = mServices.values().iterator();
9870 while (it.hasNext()) {
9871 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009872 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009873 r.dump(pw, " ");
9874 }
9875 needSep = true;
9876 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009877 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009878
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009879 if (mPendingServices.size() > 0) {
9880 if (needSep) pw.println(" ");
9881 pw.println(" Pending services:");
9882 for (int i=0; i<mPendingServices.size(); i++) {
9883 ServiceRecord r = mPendingServices.get(i);
9884 pw.print(" * Pending "); pw.println(r);
9885 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009886 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009887 needSep = true;
9888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009889
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009890 if (mRestartingServices.size() > 0) {
9891 if (needSep) pw.println(" ");
9892 pw.println(" Restarting services:");
9893 for (int i=0; i<mRestartingServices.size(); i++) {
9894 ServiceRecord r = mRestartingServices.get(i);
9895 pw.print(" * Restarting "); pw.println(r);
9896 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009897 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009898 needSep = true;
9899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009900
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009901 if (mStoppingServices.size() > 0) {
9902 if (needSep) pw.println(" ");
9903 pw.println(" Stopping services:");
9904 for (int i=0; i<mStoppingServices.size(); i++) {
9905 ServiceRecord r = mStoppingServices.get(i);
9906 pw.print(" * Stopping "); pw.println(r);
9907 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009908 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009909 needSep = true;
9910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009911
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009912 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009913 if (mServiceConnections.size() > 0) {
9914 if (needSep) pw.println(" ");
9915 pw.println(" Connection bindings to services:");
9916 Iterator<ConnectionRecord> it
9917 = mServiceConnections.values().iterator();
9918 while (it.hasNext()) {
9919 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009920 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009921 r.dump(pw, " ");
9922 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009923 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009924 }
9925 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009926
9927 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009928 }
9929
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009930 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9931 int opti, boolean dumpAll) {
9932 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009933
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009934 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009935 if (mProvidersByClass.size() > 0) {
9936 if (needSep) pw.println(" ");
9937 pw.println(" Published content providers (by class):");
9938 Iterator it = mProvidersByClass.entrySet().iterator();
9939 while (it.hasNext()) {
9940 Map.Entry e = (Map.Entry)it.next();
9941 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009942 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 r.dump(pw, " ");
9944 }
9945 needSep = true;
9946 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009947
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009948 if (mProvidersByName.size() > 0) {
9949 pw.println(" ");
9950 pw.println(" Authority to provider mappings:");
9951 Iterator it = mProvidersByName.entrySet().iterator();
9952 while (it.hasNext()) {
9953 Map.Entry e = (Map.Entry)it.next();
9954 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9955 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9956 pw.println(r);
9957 }
9958 needSep = true;
9959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009960 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009961
9962 if (mLaunchingProviders.size() > 0) {
9963 if (needSep) pw.println(" ");
9964 pw.println(" Launching content providers:");
9965 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9966 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9967 pw.println(mLaunchingProviders.get(i));
9968 }
9969 needSep = true;
9970 }
9971
9972 if (mGrantedUriPermissions.size() > 0) {
9973 pw.println();
9974 pw.println("Granted Uri Permissions:");
9975 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9976 int uid = mGrantedUriPermissions.keyAt(i);
9977 HashMap<Uri, UriPermission> perms
9978 = mGrantedUriPermissions.valueAt(i);
9979 pw.print(" * UID "); pw.print(uid);
9980 pw.println(" holds:");
9981 for (UriPermission perm : perms.values()) {
9982 pw.print(" "); pw.println(perm);
9983 perm.dump(pw, " ");
9984 }
9985 }
9986 needSep = true;
9987 }
9988
9989 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009990 }
9991
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009992 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9993 int opti, boolean dumpAll) {
9994 boolean needSep = false;
9995
9996 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009997 if (this.mIntentSenderRecords.size() > 0) {
9998 Iterator<WeakReference<PendingIntentRecord>> it
9999 = mIntentSenderRecords.values().iterator();
10000 while (it.hasNext()) {
10001 WeakReference<PendingIntentRecord> ref = it.next();
10002 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010003 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010004 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010005 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 rec.dump(pw, " ");
10007 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010008 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010009 }
10010 }
10011 }
10012 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010013
10014 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010015 }
10016
10017 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010018 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010019 TaskRecord lastTask = null;
10020 for (int i=list.size()-1; i>=0; i--) {
10021 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010022 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010023 if (lastTask != r.task) {
10024 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010025 pw.print(prefix);
10026 pw.print(full ? "* " : " ");
10027 pw.println(lastTask);
10028 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010029 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010031 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010032 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10033 pw.print(" #"); pw.print(i); pw.print(": ");
10034 pw.println(r);
10035 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010036 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038 }
10039 }
10040
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010041 private static String buildOomTag(String prefix, String space, int val, int base) {
10042 if (val == base) {
10043 if (space == null) return prefix;
10044 return prefix + " ";
10045 }
10046 return prefix + "+" + Integer.toString(val-base);
10047 }
10048
10049 private static final int dumpProcessList(PrintWriter pw,
10050 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010051 String prefix, String normalLabel, String persistentLabel,
10052 boolean inclOomAdj) {
10053 int numPers = 0;
10054 for (int i=list.size()-1; i>=0; i--) {
10055 ProcessRecord r = (ProcessRecord)list.get(i);
10056 if (false) {
10057 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10058 + " #" + i + ":");
10059 r.dump(pw, prefix + " ");
10060 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010061 String oomAdj;
10062 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010063 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010064 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010065 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10066 } else if (r.setAdj >= HOME_APP_ADJ) {
10067 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10068 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10069 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10070 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10071 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10072 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10073 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10074 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10075 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010076 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010077 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010078 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010079 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010080 } else {
10081 oomAdj = Integer.toString(r.setAdj);
10082 }
10083 String schedGroup;
10084 switch (r.setSchedGroup) {
10085 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10086 schedGroup = "B";
10087 break;
10088 case Process.THREAD_GROUP_DEFAULT:
10089 schedGroup = "F";
10090 break;
10091 default:
10092 schedGroup = Integer.toString(r.setSchedGroup);
10093 break;
10094 }
10095 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010096 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010097 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010098 if (r.adjSource != null || r.adjTarget != null) {
10099 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010100 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010102 } else {
10103 pw.println(String.format("%s%s #%2d: %s",
10104 prefix, (r.persistent ? persistentLabel : normalLabel),
10105 i, r.toString()));
10106 }
10107 if (r.persistent) {
10108 numPers++;
10109 }
10110 }
10111 return numPers;
10112 }
10113
10114 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
10115 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010116 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010117 long uptime = SystemClock.uptimeMillis();
10118 long realtime = SystemClock.elapsedRealtime();
10119
10120 if (isCheckinRequest) {
10121 // short checkin version
10122 pw.println(uptime + "," + realtime);
10123 pw.flush();
10124 } else {
10125 pw.println("Applications Memory Usage (kB):");
10126 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10127 }
10128 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10129 ProcessRecord r = (ProcessRecord)list.get(i);
10130 if (r.thread != null) {
10131 if (!isCheckinRequest) {
10132 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10133 pw.flush();
10134 }
10135 try {
10136 r.thread.asBinder().dump(fd, args);
10137 } catch (RemoteException e) {
10138 if (!isCheckinRequest) {
10139 pw.println("Got RemoteException!");
10140 pw.flush();
10141 }
10142 }
10143 }
10144 }
10145 }
10146
10147 /**
10148 * Searches array of arguments for the specified string
10149 * @param args array of argument strings
10150 * @param value value to search for
10151 * @return true if the value is contained in the array
10152 */
10153 private static boolean scanArgs(String[] args, String value) {
10154 if (args != null) {
10155 for (String arg : args) {
10156 if (value.equals(arg)) {
10157 return true;
10158 }
10159 }
10160 }
10161 return false;
10162 }
10163
Dianne Hackborn75b03852009-06-12 15:43:26 -070010164 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010165 int count = mHistory.size();
10166
10167 // convert the token to an entry in the history.
10168 HistoryRecord r = null;
10169 int index = -1;
10170 for (int i=count-1; i>=0; i--) {
10171 Object o = mHistory.get(i);
10172 if (o == token) {
10173 r = (HistoryRecord)o;
10174 index = i;
10175 break;
10176 }
10177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010178
10179 return index;
10180 }
10181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 private final void killServicesLocked(ProcessRecord app,
10183 boolean allowRestart) {
10184 // Report disconnected services.
10185 if (false) {
10186 // XXX we are letting the client link to the service for
10187 // death notifications.
10188 if (app.services.size() > 0) {
10189 Iterator it = app.services.iterator();
10190 while (it.hasNext()) {
10191 ServiceRecord r = (ServiceRecord)it.next();
10192 if (r.connections.size() > 0) {
10193 Iterator<ConnectionRecord> jt
10194 = r.connections.values().iterator();
10195 while (jt.hasNext()) {
10196 ConnectionRecord c = jt.next();
10197 if (c.binding.client != app) {
10198 try {
10199 //c.conn.connected(r.className, null);
10200 } catch (Exception e) {
10201 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010202 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 + r.shortName
10204 + " from app " + app.processName, e);
10205 }
10206 }
10207 }
10208 }
10209 }
10210 }
10211 }
10212
10213 // Clean up any connections this application has to other services.
10214 if (app.connections.size() > 0) {
10215 Iterator<ConnectionRecord> it = app.connections.iterator();
10216 while (it.hasNext()) {
10217 ConnectionRecord r = it.next();
10218 removeConnectionLocked(r, app, null);
10219 }
10220 }
10221 app.connections.clear();
10222
10223 if (app.services.size() != 0) {
10224 // Any services running in the application need to be placed
10225 // back in the pending list.
10226 Iterator it = app.services.iterator();
10227 while (it.hasNext()) {
10228 ServiceRecord sr = (ServiceRecord)it.next();
10229 synchronized (sr.stats.getBatteryStats()) {
10230 sr.stats.stopLaunchedLocked();
10231 }
10232 sr.app = null;
10233 sr.executeNesting = 0;
10234 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010235
10236 boolean hasClients = sr.bindings.size() > 0;
10237 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 Iterator<IntentBindRecord> bindings
10239 = sr.bindings.values().iterator();
10240 while (bindings.hasNext()) {
10241 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010242 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010243 + ": shouldUnbind=" + b.hasBound);
10244 b.binder = null;
10245 b.requested = b.received = b.hasBound = false;
10246 }
10247 }
10248
10249 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010250 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010252 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010253 sr.crashCount, sr.shortName, app.pid);
10254 bringDownServiceLocked(sr, true);
10255 } else if (!allowRestart) {
10256 bringDownServiceLocked(sr, true);
10257 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010258 boolean canceled = scheduleServiceRestartLocked(sr, true);
10259
10260 // Should the service remain running? Note that in the
10261 // extreme case of so many attempts to deliver a command
10262 // that it failed, that we also will stop it here.
10263 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10264 if (sr.pendingStarts.size() == 0) {
10265 sr.startRequested = false;
10266 if (!hasClients) {
10267 // Whoops, no reason to restart!
10268 bringDownServiceLocked(sr, true);
10269 }
10270 }
10271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010272 }
10273 }
10274
10275 if (!allowRestart) {
10276 app.services.clear();
10277 }
10278 }
10279
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010280 // Make sure we have no more records on the stopping list.
10281 int i = mStoppingServices.size();
10282 while (i > 0) {
10283 i--;
10284 ServiceRecord sr = mStoppingServices.get(i);
10285 if (sr.app == app) {
10286 mStoppingServices.remove(i);
10287 }
10288 }
10289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010290 app.executingServices.clear();
10291 }
10292
10293 private final void removeDyingProviderLocked(ProcessRecord proc,
10294 ContentProviderRecord cpr) {
10295 synchronized (cpr) {
10296 cpr.launchingApp = null;
10297 cpr.notifyAll();
10298 }
10299
10300 mProvidersByClass.remove(cpr.info.name);
10301 String names[] = cpr.info.authority.split(";");
10302 for (int j = 0; j < names.length; j++) {
10303 mProvidersByName.remove(names[j]);
10304 }
10305
10306 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10307 while (cit.hasNext()) {
10308 ProcessRecord capp = cit.next();
10309 if (!capp.persistent && capp.thread != null
10310 && capp.pid != 0
10311 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010312 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010313 + " (pid " + capp.pid
10314 + ") because provider " + cpr.info.name
10315 + " is in dying process " + proc.processName);
10316 Process.killProcess(capp.pid);
10317 }
10318 }
10319
10320 mLaunchingProviders.remove(cpr);
10321 }
10322
10323 /**
10324 * Main code for cleaning up a process when it has gone away. This is
10325 * called both as a result of the process dying, or directly when stopping
10326 * a process when running in single process mode.
10327 */
10328 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10329 boolean restarting, int index) {
10330 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010331 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332 }
10333
Dianne Hackborn36124872009-10-08 16:22:03 -070010334 mProcessesToGc.remove(app);
10335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010336 // Dismiss any open dialogs.
10337 if (app.crashDialog != null) {
10338 app.crashDialog.dismiss();
10339 app.crashDialog = null;
10340 }
10341 if (app.anrDialog != null) {
10342 app.anrDialog.dismiss();
10343 app.anrDialog = null;
10344 }
10345 if (app.waitDialog != null) {
10346 app.waitDialog.dismiss();
10347 app.waitDialog = null;
10348 }
10349
10350 app.crashing = false;
10351 app.notResponding = false;
10352
10353 app.resetPackageList();
10354 app.thread = null;
10355 app.forcingToForeground = null;
10356 app.foregroundServices = false;
10357
10358 killServicesLocked(app, true);
10359
10360 boolean restart = false;
10361
10362 int NL = mLaunchingProviders.size();
10363
10364 // Remove published content providers.
10365 if (!app.pubProviders.isEmpty()) {
10366 Iterator it = app.pubProviders.values().iterator();
10367 while (it.hasNext()) {
10368 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10369 cpr.provider = null;
10370 cpr.app = null;
10371
10372 // See if someone is waiting for this provider... in which
10373 // case we don't remove it, but just let it restart.
10374 int i = 0;
10375 if (!app.bad) {
10376 for (; i<NL; i++) {
10377 if (mLaunchingProviders.get(i) == cpr) {
10378 restart = true;
10379 break;
10380 }
10381 }
10382 } else {
10383 i = NL;
10384 }
10385
10386 if (i >= NL) {
10387 removeDyingProviderLocked(app, cpr);
10388 NL = mLaunchingProviders.size();
10389 }
10390 }
10391 app.pubProviders.clear();
10392 }
10393
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010394 // Take care of any launching providers waiting for this process.
10395 if (checkAppInLaunchingProvidersLocked(app, false)) {
10396 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010397 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010399 // Unregister from connected content providers.
10400 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010401 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 while (it.hasNext()) {
10403 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10404 cpr.clients.remove(app);
10405 }
10406 app.conProviders.clear();
10407 }
10408
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010409 // At this point there may be remaining entries in mLaunchingProviders
10410 // where we were the only one waiting, so they are no longer of use.
10411 // Look for these and clean up if found.
10412 // XXX Commented out for now. Trying to figure out a way to reproduce
10413 // the actual situation to identify what is actually going on.
10414 if (false) {
10415 for (int i=0; i<NL; i++) {
10416 ContentProviderRecord cpr = (ContentProviderRecord)
10417 mLaunchingProviders.get(i);
10418 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10419 synchronized (cpr) {
10420 cpr.launchingApp = null;
10421 cpr.notifyAll();
10422 }
10423 }
10424 }
10425 }
10426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 skipCurrentReceiverLocked(app);
10428
10429 // Unregister any receivers.
10430 if (app.receivers.size() > 0) {
10431 Iterator<ReceiverList> it = app.receivers.iterator();
10432 while (it.hasNext()) {
10433 removeReceiverLocked(it.next());
10434 }
10435 app.receivers.clear();
10436 }
10437
Christopher Tate181fafa2009-05-14 11:12:14 -070010438 // If the app is undergoing backup, tell the backup manager about it
10439 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010440 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010441 try {
10442 IBackupManager bm = IBackupManager.Stub.asInterface(
10443 ServiceManager.getService(Context.BACKUP_SERVICE));
10444 bm.agentDisconnected(app.info.packageName);
10445 } catch (RemoteException e) {
10446 // can't happen; backup manager is local
10447 }
10448 }
10449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010450 // If the caller is restarting this app, then leave it in its
10451 // current lists and let the caller take care of it.
10452 if (restarting) {
10453 return;
10454 }
10455
10456 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010457 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010458 "Removing non-persistent process during cleanup: " + app);
10459 mProcessNames.remove(app.processName, app.info.uid);
10460 } else if (!app.removed) {
10461 // This app is persistent, so we need to keep its record around.
10462 // If it is not already on the pending app list, add it there
10463 // and start a new process for it.
10464 app.thread = null;
10465 app.forcingToForeground = null;
10466 app.foregroundServices = false;
10467 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10468 mPersistentStartingProcesses.add(app);
10469 restart = true;
10470 }
10471 }
10472 mProcessesOnHold.remove(app);
10473
The Android Open Source Project4df24232009-03-05 14:34:35 -080010474 if (app == mHomeProcess) {
10475 mHomeProcess = null;
10476 }
10477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010478 if (restart) {
10479 // We have components that still need to be running in the
10480 // process, so re-launch it.
10481 mProcessNames.put(app.processName, app.info.uid, app);
10482 startProcessLocked(app, "restart", app.processName);
10483 } else if (app.pid > 0 && app.pid != MY_PID) {
10484 // Goodbye!
10485 synchronized (mPidsSelfLocked) {
10486 mPidsSelfLocked.remove(app.pid);
10487 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10488 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010489 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010490 }
10491 }
10492
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010493 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10494 // Look through the content providers we are waiting to have launched,
10495 // and if any run in this process then either schedule a restart of
10496 // the process or kill the client waiting for it if this process has
10497 // gone bad.
10498 int NL = mLaunchingProviders.size();
10499 boolean restart = false;
10500 for (int i=0; i<NL; i++) {
10501 ContentProviderRecord cpr = (ContentProviderRecord)
10502 mLaunchingProviders.get(i);
10503 if (cpr.launchingApp == app) {
10504 if (!alwaysBad && !app.bad) {
10505 restart = true;
10506 } else {
10507 removeDyingProviderLocked(app, cpr);
10508 NL = mLaunchingProviders.size();
10509 }
10510 }
10511 }
10512 return restart;
10513 }
10514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010515 // =========================================================
10516 // SERVICES
10517 // =========================================================
10518
10519 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10520 ActivityManager.RunningServiceInfo info =
10521 new ActivityManager.RunningServiceInfo();
10522 info.service = r.name;
10523 if (r.app != null) {
10524 info.pid = r.app.pid;
10525 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010526 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010527 info.process = r.processName;
10528 info.foreground = r.isForeground;
10529 info.activeSince = r.createTime;
10530 info.started = r.startRequested;
10531 info.clientCount = r.connections.size();
10532 info.crashCount = r.crashCount;
10533 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010534 if (r.isForeground) {
10535 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10536 }
10537 if (r.startRequested) {
10538 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10539 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010540 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010541 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10542 }
10543 if (r.app != null && r.app.persistent) {
10544 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10545 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010546 for (ConnectionRecord conn : r.connections.values()) {
10547 if (conn.clientLabel != 0) {
10548 info.clientPackage = conn.binding.client.info.packageName;
10549 info.clientLabel = conn.clientLabel;
10550 break;
10551 }
10552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010553 return info;
10554 }
10555
10556 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10557 int flags) {
10558 synchronized (this) {
10559 ArrayList<ActivityManager.RunningServiceInfo> res
10560 = new ArrayList<ActivityManager.RunningServiceInfo>();
10561
10562 if (mServices.size() > 0) {
10563 Iterator<ServiceRecord> it = mServices.values().iterator();
10564 while (it.hasNext() && res.size() < maxNum) {
10565 res.add(makeRunningServiceInfoLocked(it.next()));
10566 }
10567 }
10568
10569 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10570 ServiceRecord r = mRestartingServices.get(i);
10571 ActivityManager.RunningServiceInfo info =
10572 makeRunningServiceInfoLocked(r);
10573 info.restarting = r.nextRestartTime;
10574 res.add(info);
10575 }
10576
10577 return res;
10578 }
10579 }
10580
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010581 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10582 synchronized (this) {
10583 ServiceRecord r = mServices.get(name);
10584 if (r != null) {
10585 for (ConnectionRecord conn : r.connections.values()) {
10586 if (conn.clientIntent != null) {
10587 return conn.clientIntent;
10588 }
10589 }
10590 }
10591 }
10592 return null;
10593 }
10594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010595 private final ServiceRecord findServiceLocked(ComponentName name,
10596 IBinder token) {
10597 ServiceRecord r = mServices.get(name);
10598 return r == token ? r : null;
10599 }
10600
10601 private final class ServiceLookupResult {
10602 final ServiceRecord record;
10603 final String permission;
10604
10605 ServiceLookupResult(ServiceRecord _record, String _permission) {
10606 record = _record;
10607 permission = _permission;
10608 }
10609 };
10610
10611 private ServiceLookupResult findServiceLocked(Intent service,
10612 String resolvedType) {
10613 ServiceRecord r = null;
10614 if (service.getComponent() != null) {
10615 r = mServices.get(service.getComponent());
10616 }
10617 if (r == null) {
10618 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10619 r = mServicesByIntent.get(filter);
10620 }
10621
10622 if (r == null) {
10623 try {
10624 ResolveInfo rInfo =
10625 ActivityThread.getPackageManager().resolveService(
10626 service, resolvedType, 0);
10627 ServiceInfo sInfo =
10628 rInfo != null ? rInfo.serviceInfo : null;
10629 if (sInfo == null) {
10630 return null;
10631 }
10632
10633 ComponentName name = new ComponentName(
10634 sInfo.applicationInfo.packageName, sInfo.name);
10635 r = mServices.get(name);
10636 } catch (RemoteException ex) {
10637 // pm is in same process, this will never happen.
10638 }
10639 }
10640 if (r != null) {
10641 int callingPid = Binder.getCallingPid();
10642 int callingUid = Binder.getCallingUid();
10643 if (checkComponentPermission(r.permission,
10644 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10645 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010646 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010647 + " from pid=" + callingPid
10648 + ", uid=" + callingUid
10649 + " requires " + r.permission);
10650 return new ServiceLookupResult(null, r.permission);
10651 }
10652 return new ServiceLookupResult(r, null);
10653 }
10654 return null;
10655 }
10656
10657 private class ServiceRestarter implements Runnable {
10658 private ServiceRecord mService;
10659
10660 void setService(ServiceRecord service) {
10661 mService = service;
10662 }
10663
10664 public void run() {
10665 synchronized(ActivityManagerService.this) {
10666 performServiceRestartLocked(mService);
10667 }
10668 }
10669 }
10670
10671 private ServiceLookupResult retrieveServiceLocked(Intent service,
10672 String resolvedType, int callingPid, int callingUid) {
10673 ServiceRecord r = null;
10674 if (service.getComponent() != null) {
10675 r = mServices.get(service.getComponent());
10676 }
10677 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10678 r = mServicesByIntent.get(filter);
10679 if (r == null) {
10680 try {
10681 ResolveInfo rInfo =
10682 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010683 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010684 ServiceInfo sInfo =
10685 rInfo != null ? rInfo.serviceInfo : null;
10686 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010687 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010688 ": not found");
10689 return null;
10690 }
10691
10692 ComponentName name = new ComponentName(
10693 sInfo.applicationInfo.packageName, sInfo.name);
10694 r = mServices.get(name);
10695 if (r == null) {
10696 filter = new Intent.FilterComparison(service.cloneFilter());
10697 ServiceRestarter res = new ServiceRestarter();
10698 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10699 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10700 synchronized (stats) {
10701 ss = stats.getServiceStatsLocked(
10702 sInfo.applicationInfo.uid, sInfo.packageName,
10703 sInfo.name);
10704 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010705 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010706 res.setService(r);
10707 mServices.put(name, r);
10708 mServicesByIntent.put(filter, r);
10709
10710 // Make sure this component isn't in the pending list.
10711 int N = mPendingServices.size();
10712 for (int i=0; i<N; i++) {
10713 ServiceRecord pr = mPendingServices.get(i);
10714 if (pr.name.equals(name)) {
10715 mPendingServices.remove(i);
10716 i--;
10717 N--;
10718 }
10719 }
10720 }
10721 } catch (RemoteException ex) {
10722 // pm is in same process, this will never happen.
10723 }
10724 }
10725 if (r != null) {
10726 if (checkComponentPermission(r.permission,
10727 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10728 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010729 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010730 + " from pid=" + Binder.getCallingPid()
10731 + ", uid=" + Binder.getCallingUid()
10732 + " requires " + r.permission);
10733 return new ServiceLookupResult(null, r.permission);
10734 }
10735 return new ServiceLookupResult(r, null);
10736 }
10737 return null;
10738 }
10739
10740 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10741 long now = SystemClock.uptimeMillis();
10742 if (r.executeNesting == 0 && r.app != null) {
10743 if (r.app.executingServices.size() == 0) {
10744 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10745 msg.obj = r.app;
10746 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10747 }
10748 r.app.executingServices.add(r);
10749 }
10750 r.executeNesting++;
10751 r.executingStart = now;
10752 }
10753
10754 private final void sendServiceArgsLocked(ServiceRecord r,
10755 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010756 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757 if (N == 0) {
10758 return;
10759 }
10760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761 int i = 0;
10762 while (i < N) {
10763 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010764 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010765 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010766 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010767 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010768 // If somehow we got a dummy start at the front, then
10769 // just drop it here.
10770 i++;
10771 continue;
10772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010773 bumpServiceExecutingLocked(r);
10774 if (!oomAdjusted) {
10775 oomAdjusted = true;
10776 updateOomAdjLocked(r.app);
10777 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010778 int flags = 0;
10779 if (si.deliveryCount > 0) {
10780 flags |= Service.START_FLAG_RETRY;
10781 }
10782 if (si.doneExecutingCount > 0) {
10783 flags |= Service.START_FLAG_REDELIVERY;
10784 }
10785 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10786 si.deliveredTime = SystemClock.uptimeMillis();
10787 r.deliveredStarts.add(si);
10788 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010790 } catch (RemoteException e) {
10791 // Remote process gone... we'll let the normal cleanup take
10792 // care of this.
10793 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010795 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010796 break;
10797 }
10798 }
10799 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010800 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 } else {
10802 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010803 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010804 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 }
10806 }
10807 }
10808
10809 private final boolean requestServiceBindingLocked(ServiceRecord r,
10810 IntentBindRecord i, boolean rebind) {
10811 if (r.app == null || r.app.thread == null) {
10812 // If service is not currently running, can't yet bind.
10813 return false;
10814 }
10815 if ((!i.requested || rebind) && i.apps.size() > 0) {
10816 try {
10817 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010818 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010819 + ": shouldUnbind=" + i.hasBound);
10820 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10821 if (!rebind) {
10822 i.requested = true;
10823 }
10824 i.hasBound = true;
10825 i.doRebind = false;
10826 } catch (RemoteException e) {
10827 return false;
10828 }
10829 }
10830 return true;
10831 }
10832
10833 private final void requestServiceBindingsLocked(ServiceRecord r) {
10834 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10835 while (bindings.hasNext()) {
10836 IntentBindRecord i = bindings.next();
10837 if (!requestServiceBindingLocked(r, i, false)) {
10838 break;
10839 }
10840 }
10841 }
10842
10843 private final void realStartServiceLocked(ServiceRecord r,
10844 ProcessRecord app) throws RemoteException {
10845 if (app.thread == null) {
10846 throw new RemoteException();
10847 }
10848
10849 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010850 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010851
10852 app.services.add(r);
10853 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010854 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010855
10856 boolean created = false;
10857 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010858 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010860 mStringBuilder.setLength(0);
10861 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010862 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010863 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010864 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010865 synchronized (r.stats.getBatteryStats()) {
10866 r.stats.startLaunchedLocked();
10867 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010868 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010869 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010870 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010871 created = true;
10872 } finally {
10873 if (!created) {
10874 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010875 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010876 }
10877 }
10878
10879 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010880
10881 // If the service is in the started state, and there are no
10882 // pending arguments, then fake up one so its onStartCommand() will
10883 // be called.
10884 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10885 r.lastStartId++;
10886 if (r.lastStartId < 1) {
10887 r.lastStartId = 1;
10888 }
10889 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10890 }
10891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010892 sendServiceArgsLocked(r, true);
10893 }
10894
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010895 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10896 boolean allowCancel) {
10897 boolean canceled = false;
10898
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010899 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010900 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010901 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010902
10903 // Any delivered but not yet finished starts should be put back
10904 // on the pending list.
10905 final int N = r.deliveredStarts.size();
10906 if (N > 0) {
10907 for (int i=N-1; i>=0; i--) {
10908 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10909 if (si.intent == null) {
10910 // We'll generate this again if needed.
10911 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10912 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10913 r.pendingStarts.add(0, si);
10914 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10915 dur *= 2;
10916 if (minDuration < dur) minDuration = dur;
10917 if (resetTime < dur) resetTime = dur;
10918 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010919 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010920 + r.name);
10921 canceled = true;
10922 }
10923 }
10924 r.deliveredStarts.clear();
10925 }
10926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927 r.totalRestartCount++;
10928 if (r.restartDelay == 0) {
10929 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010930 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010931 } else {
10932 // If it has been a "reasonably long time" since the service
10933 // was started, then reset our restart duration back to
10934 // the beginning, so we don't infinitely increase the duration
10935 // on a service that just occasionally gets killed (which is
10936 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010937 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010939 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010940 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010941 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010942 if (r.restartDelay < minDuration) {
10943 r.restartDelay = minDuration;
10944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010945 }
10946 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010947
10948 r.nextRestartTime = now + r.restartDelay;
10949
10950 // Make sure that we don't end up restarting a bunch of services
10951 // all at the same time.
10952 boolean repeat;
10953 do {
10954 repeat = false;
10955 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10956 ServiceRecord r2 = mRestartingServices.get(i);
10957 if (r2 != r && r.nextRestartTime
10958 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10959 && r.nextRestartTime
10960 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10961 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10962 r.restartDelay = r.nextRestartTime - now;
10963 repeat = true;
10964 break;
10965 }
10966 }
10967 } while (repeat);
10968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 if (!mRestartingServices.contains(r)) {
10970 mRestartingServices.add(r);
10971 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010972
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010973 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010975 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010976 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010977 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010978 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010980 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010981 r.shortName, r.restartDelay);
10982
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010983 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010984 }
10985
10986 final void performServiceRestartLocked(ServiceRecord r) {
10987 if (!mRestartingServices.contains(r)) {
10988 return;
10989 }
10990 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10991 }
10992
10993 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10994 if (r.restartDelay == 0) {
10995 return false;
10996 }
10997 r.resetRestartCounter();
10998 mRestartingServices.remove(r);
10999 mHandler.removeCallbacks(r.restarter);
11000 return true;
11001 }
11002
11003 private final boolean bringUpServiceLocked(ServiceRecord r,
11004 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011005 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011006 //r.dump(" ");
11007
Dianne Hackborn36124872009-10-08 16:22:03 -070011008 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011009 sendServiceArgsLocked(r, false);
11010 return true;
11011 }
11012
11013 if (!whileRestarting && r.restartDelay > 0) {
11014 // If waiting for a restart, then do nothing.
11015 return true;
11016 }
11017
Joe Onorato8a9b2202010-02-26 18:56:32 -080011018 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011019 + " " + r.intent);
11020
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011021 // We are now bringing the service up, so no longer in the
11022 // restarting state.
11023 mRestartingServices.remove(r);
11024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011025 final String appName = r.processName;
11026 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11027 if (app != null && app.thread != null) {
11028 try {
11029 realStartServiceLocked(r, app);
11030 return true;
11031 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011032 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 }
11034
11035 // If a dead object exception was thrown -- fall through to
11036 // restart the application.
11037 }
11038
Dianne Hackborn36124872009-10-08 16:22:03 -070011039 // Not running -- get it started, and enqueue this service record
11040 // to be executed when the app comes up.
11041 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11042 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011043 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011044 + r.appInfo.packageName + "/"
11045 + r.appInfo.uid + " for service "
11046 + r.intent.getIntent() + ": process is bad");
11047 bringDownServiceLocked(r, true);
11048 return false;
11049 }
11050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011051 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 mPendingServices.add(r);
11053 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011055 return true;
11056 }
11057
11058 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011059 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011060 //r.dump(" ");
11061
11062 // Does it still need to run?
11063 if (!force && r.startRequested) {
11064 return;
11065 }
11066 if (r.connections.size() > 0) {
11067 if (!force) {
11068 // XXX should probably keep a count of the number of auto-create
11069 // connections directly in the service.
11070 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11071 while (it.hasNext()) {
11072 ConnectionRecord cr = it.next();
11073 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11074 return;
11075 }
11076 }
11077 }
11078
11079 // Report to all of the connections that the service is no longer
11080 // available.
11081 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11082 while (it.hasNext()) {
11083 ConnectionRecord c = it.next();
11084 try {
11085 // todo: shouldn't be a synchronous call!
11086 c.conn.connected(r.name, null);
11087 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011088 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089 " to connection " + c.conn.asBinder() +
11090 " (in " + c.binding.client.processName + ")", e);
11091 }
11092 }
11093 }
11094
11095 // Tell the service that it has been unbound.
11096 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11097 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11098 while (it.hasNext()) {
11099 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011100 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011101 + ": hasBound=" + ibr.hasBound);
11102 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11103 try {
11104 bumpServiceExecutingLocked(r);
11105 updateOomAdjLocked(r.app);
11106 ibr.hasBound = false;
11107 r.app.thread.scheduleUnbindService(r,
11108 ibr.intent.getIntent());
11109 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011110 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011111 + r.shortName, e);
11112 serviceDoneExecutingLocked(r, true);
11113 }
11114 }
11115 }
11116 }
11117
Joe Onorato8a9b2202010-02-26 18:56:32 -080011118 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011119 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011120 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011121 System.identityHashCode(r), r.shortName,
11122 (r.app != null) ? r.app.pid : -1);
11123
11124 mServices.remove(r.name);
11125 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011126 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011127 r.totalRestartCount = 0;
11128 unscheduleServiceRestartLocked(r);
11129
11130 // Also make sure it is not on the pending list.
11131 int N = mPendingServices.size();
11132 for (int i=0; i<N; i++) {
11133 if (mPendingServices.get(i) == r) {
11134 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011135 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011136 TAG, "Removed pending service: " + r.shortName);
11137 i--;
11138 N--;
11139 }
11140 }
11141
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011142 r.cancelNotification();
11143 r.isForeground = false;
11144 r.foregroundId = 0;
11145 r.foregroundNoti = null;
11146
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011147 // Clear start entries.
11148 r.deliveredStarts.clear();
11149 r.pendingStarts.clear();
11150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 if (r.app != null) {
11152 synchronized (r.stats.getBatteryStats()) {
11153 r.stats.stopLaunchedLocked();
11154 }
11155 r.app.services.remove(r);
11156 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011157 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011158 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011159 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011160 bumpServiceExecutingLocked(r);
11161 mStoppingServices.add(r);
11162 updateOomAdjLocked(r.app);
11163 r.app.thread.scheduleStopService(r);
11164 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011165 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011166 + r.shortName, e);
11167 serviceDoneExecutingLocked(r, true);
11168 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011169 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011170 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011171 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011172 TAG, "Removed service that has no process: " + r.shortName);
11173 }
11174 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011175 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011176 TAG, "Removed service that is not running: " + r.shortName);
11177 }
11178 }
11179
11180 ComponentName startServiceLocked(IApplicationThread caller,
11181 Intent service, String resolvedType,
11182 int callingPid, int callingUid) {
11183 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011184 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 + " type=" + resolvedType + " args=" + service.getExtras());
11186
11187 if (caller != null) {
11188 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11189 if (callerApp == null) {
11190 throw new SecurityException(
11191 "Unable to find app for caller " + caller
11192 + " (pid=" + Binder.getCallingPid()
11193 + ") when starting service " + service);
11194 }
11195 }
11196
11197 ServiceLookupResult res =
11198 retrieveServiceLocked(service, resolvedType,
11199 callingPid, callingUid);
11200 if (res == null) {
11201 return null;
11202 }
11203 if (res.record == null) {
11204 return new ComponentName("!", res.permission != null
11205 ? res.permission : "private to package");
11206 }
11207 ServiceRecord r = res.record;
11208 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011209 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 + r.shortName);
11211 }
11212 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011213 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 r.lastStartId++;
11215 if (r.lastStartId < 1) {
11216 r.lastStartId = 1;
11217 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011218 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011219 r.lastActivity = SystemClock.uptimeMillis();
11220 synchronized (r.stats.getBatteryStats()) {
11221 r.stats.startRunningLocked();
11222 }
11223 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11224 return new ComponentName("!", "Service process is bad");
11225 }
11226 return r.name;
11227 }
11228 }
11229
11230 public ComponentName startService(IApplicationThread caller, Intent service,
11231 String resolvedType) {
11232 // Refuse possible leaked file descriptors
11233 if (service != null && service.hasFileDescriptors() == true) {
11234 throw new IllegalArgumentException("File descriptors passed in Intent");
11235 }
11236
11237 synchronized(this) {
11238 final int callingPid = Binder.getCallingPid();
11239 final int callingUid = Binder.getCallingUid();
11240 final long origId = Binder.clearCallingIdentity();
11241 ComponentName res = startServiceLocked(caller, service,
11242 resolvedType, callingPid, callingUid);
11243 Binder.restoreCallingIdentity(origId);
11244 return res;
11245 }
11246 }
11247
11248 ComponentName startServiceInPackage(int uid,
11249 Intent service, String resolvedType) {
11250 synchronized(this) {
11251 final long origId = Binder.clearCallingIdentity();
11252 ComponentName res = startServiceLocked(null, service,
11253 resolvedType, -1, uid);
11254 Binder.restoreCallingIdentity(origId);
11255 return res;
11256 }
11257 }
11258
11259 public int stopService(IApplicationThread caller, Intent service,
11260 String resolvedType) {
11261 // Refuse possible leaked file descriptors
11262 if (service != null && service.hasFileDescriptors() == true) {
11263 throw new IllegalArgumentException("File descriptors passed in Intent");
11264 }
11265
11266 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011267 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011268 + " type=" + resolvedType);
11269
11270 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11271 if (caller != null && callerApp == null) {
11272 throw new SecurityException(
11273 "Unable to find app for caller " + caller
11274 + " (pid=" + Binder.getCallingPid()
11275 + ") when stopping service " + service);
11276 }
11277
11278 // If this service is active, make sure it is stopped.
11279 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11280 if (r != null) {
11281 if (r.record != null) {
11282 synchronized (r.record.stats.getBatteryStats()) {
11283 r.record.stats.stopRunningLocked();
11284 }
11285 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011286 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011287 final long origId = Binder.clearCallingIdentity();
11288 bringDownServiceLocked(r.record, false);
11289 Binder.restoreCallingIdentity(origId);
11290 return 1;
11291 }
11292 return -1;
11293 }
11294 }
11295
11296 return 0;
11297 }
11298
11299 public IBinder peekService(Intent service, String resolvedType) {
11300 // Refuse possible leaked file descriptors
11301 if (service != null && service.hasFileDescriptors() == true) {
11302 throw new IllegalArgumentException("File descriptors passed in Intent");
11303 }
11304
11305 IBinder ret = null;
11306
11307 synchronized(this) {
11308 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11309
11310 if (r != null) {
11311 // r.record is null if findServiceLocked() failed the caller permission check
11312 if (r.record == null) {
11313 throw new SecurityException(
11314 "Permission Denial: Accessing service " + r.record.name
11315 + " from pid=" + Binder.getCallingPid()
11316 + ", uid=" + Binder.getCallingUid()
11317 + " requires " + r.permission);
11318 }
11319 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11320 if (ib != null) {
11321 ret = ib.binder;
11322 }
11323 }
11324 }
11325
11326 return ret;
11327 }
11328
11329 public boolean stopServiceToken(ComponentName className, IBinder token,
11330 int startId) {
11331 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011332 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011333 + " " + token + " startId=" + startId);
11334 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011335 if (r != null) {
11336 if (startId >= 0) {
11337 // Asked to only stop if done with all work. Note that
11338 // to avoid leaks, we will take this as dropping all
11339 // start items up to and including this one.
11340 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11341 if (si != null) {
11342 while (r.deliveredStarts.size() > 0) {
11343 if (r.deliveredStarts.remove(0) == si) {
11344 break;
11345 }
11346 }
11347 }
11348
11349 if (r.lastStartId != startId) {
11350 return false;
11351 }
11352
11353 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011354 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011355 + " is last, but have " + r.deliveredStarts.size()
11356 + " remaining args");
11357 }
11358 }
11359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 synchronized (r.stats.getBatteryStats()) {
11361 r.stats.stopRunningLocked();
11362 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011363 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364 }
11365 final long origId = Binder.clearCallingIdentity();
11366 bringDownServiceLocked(r, false);
11367 Binder.restoreCallingIdentity(origId);
11368 return true;
11369 }
11370 }
11371 return false;
11372 }
11373
11374 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011375 int id, Notification notification, boolean removeNotification) {
11376 final long origId = Binder.clearCallingIdentity();
11377 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011378 synchronized(this) {
11379 ServiceRecord r = findServiceLocked(className, token);
11380 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011381 if (id != 0) {
11382 if (notification == null) {
11383 throw new IllegalArgumentException("null notification");
11384 }
11385 if (r.foregroundId != id) {
11386 r.cancelNotification();
11387 r.foregroundId = id;
11388 }
11389 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11390 r.foregroundNoti = notification;
11391 r.isForeground = true;
11392 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011393 if (r.app != null) {
11394 updateServiceForegroundLocked(r.app, true);
11395 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011396 } else {
11397 if (r.isForeground) {
11398 r.isForeground = false;
11399 if (r.app != null) {
11400 updateServiceForegroundLocked(r.app, true);
11401 }
11402 }
11403 if (removeNotification) {
11404 r.cancelNotification();
11405 r.foregroundId = 0;
11406 r.foregroundNoti = null;
11407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408 }
11409 }
11410 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011411 } finally {
11412 Binder.restoreCallingIdentity(origId);
11413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 }
11415
11416 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11417 boolean anyForeground = false;
11418 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11419 if (sr.isForeground) {
11420 anyForeground = true;
11421 break;
11422 }
11423 }
11424 if (anyForeground != proc.foregroundServices) {
11425 proc.foregroundServices = anyForeground;
11426 if (oomAdj) {
11427 updateOomAdjLocked();
11428 }
11429 }
11430 }
11431
11432 public int bindService(IApplicationThread caller, IBinder token,
11433 Intent service, String resolvedType,
11434 IServiceConnection connection, int flags) {
11435 // Refuse possible leaked file descriptors
11436 if (service != null && service.hasFileDescriptors() == true) {
11437 throw new IllegalArgumentException("File descriptors passed in Intent");
11438 }
11439
11440 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011441 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011442 + " type=" + resolvedType + " conn=" + connection.asBinder()
11443 + " flags=0x" + Integer.toHexString(flags));
11444 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11445 if (callerApp == null) {
11446 throw new SecurityException(
11447 "Unable to find app for caller " + caller
11448 + " (pid=" + Binder.getCallingPid()
11449 + ") when binding service " + service);
11450 }
11451
11452 HistoryRecord activity = null;
11453 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011454 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011455 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011456 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011457 return 0;
11458 }
11459 activity = (HistoryRecord)mHistory.get(aindex);
11460 }
11461
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011462 int clientLabel = 0;
11463 PendingIntent clientIntent = null;
11464
11465 if (callerApp.info.uid == Process.SYSTEM_UID) {
11466 // Hacky kind of thing -- allow system stuff to tell us
11467 // what they are, so we can report this elsewhere for
11468 // others to know why certain services are running.
11469 try {
11470 clientIntent = (PendingIntent)service.getParcelableExtra(
11471 Intent.EXTRA_CLIENT_INTENT);
11472 } catch (RuntimeException e) {
11473 }
11474 if (clientIntent != null) {
11475 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11476 if (clientLabel != 0) {
11477 // There are no useful extras in the intent, trash them.
11478 // System code calling with this stuff just needs to know
11479 // this will happen.
11480 service = service.cloneFilter();
11481 }
11482 }
11483 }
11484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 ServiceLookupResult res =
11486 retrieveServiceLocked(service, resolvedType,
11487 Binder.getCallingPid(), Binder.getCallingUid());
11488 if (res == null) {
11489 return 0;
11490 }
11491 if (res.record == null) {
11492 return -1;
11493 }
11494 ServiceRecord s = res.record;
11495
11496 final long origId = Binder.clearCallingIdentity();
11497
11498 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011499 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 + s.shortName);
11501 }
11502
11503 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11504 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011505 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011506
11507 IBinder binder = connection.asBinder();
11508 s.connections.put(binder, c);
11509 b.connections.add(c);
11510 if (activity != null) {
11511 if (activity.connections == null) {
11512 activity.connections = new HashSet<ConnectionRecord>();
11513 }
11514 activity.connections.add(c);
11515 }
11516 b.client.connections.add(c);
11517 mServiceConnections.put(binder, c);
11518
11519 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11520 s.lastActivity = SystemClock.uptimeMillis();
11521 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11522 return 0;
11523 }
11524 }
11525
11526 if (s.app != null) {
11527 // This could have made the service more important.
11528 updateOomAdjLocked(s.app);
11529 }
11530
Joe Onorato8a9b2202010-02-26 18:56:32 -080011531 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011532 + ": received=" + b.intent.received
11533 + " apps=" + b.intent.apps.size()
11534 + " doRebind=" + b.intent.doRebind);
11535
11536 if (s.app != null && b.intent.received) {
11537 // Service is already running, so we can immediately
11538 // publish the connection.
11539 try {
11540 c.conn.connected(s.name, b.intent.binder);
11541 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011542 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011543 + " to connection " + c.conn.asBinder()
11544 + " (in " + c.binding.client.processName + ")", e);
11545 }
11546
11547 // If this is the first app connected back to this binding,
11548 // and the service had previously asked to be told when
11549 // rebound, then do so.
11550 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11551 requestServiceBindingLocked(s, b.intent, true);
11552 }
11553 } else if (!b.intent.requested) {
11554 requestServiceBindingLocked(s, b.intent, false);
11555 }
11556
11557 Binder.restoreCallingIdentity(origId);
11558 }
11559
11560 return 1;
11561 }
11562
11563 private void removeConnectionLocked(
11564 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11565 IBinder binder = c.conn.asBinder();
11566 AppBindRecord b = c.binding;
11567 ServiceRecord s = b.service;
11568 s.connections.remove(binder);
11569 b.connections.remove(c);
11570 if (c.activity != null && c.activity != skipAct) {
11571 if (c.activity.connections != null) {
11572 c.activity.connections.remove(c);
11573 }
11574 }
11575 if (b.client != skipApp) {
11576 b.client.connections.remove(c);
11577 }
11578 mServiceConnections.remove(binder);
11579
11580 if (b.connections.size() == 0) {
11581 b.intent.apps.remove(b.client);
11582 }
11583
Joe Onorato8a9b2202010-02-26 18:56:32 -080011584 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011585 + ": shouldUnbind=" + b.intent.hasBound);
11586 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11587 && b.intent.hasBound) {
11588 try {
11589 bumpServiceExecutingLocked(s);
11590 updateOomAdjLocked(s.app);
11591 b.intent.hasBound = false;
11592 // Assume the client doesn't want to know about a rebind;
11593 // we will deal with that later if it asks for one.
11594 b.intent.doRebind = false;
11595 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11596 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011597 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 serviceDoneExecutingLocked(s, true);
11599 }
11600 }
11601
11602 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11603 bringDownServiceLocked(s, false);
11604 }
11605 }
11606
11607 public boolean unbindService(IServiceConnection connection) {
11608 synchronized (this) {
11609 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011610 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011611 ConnectionRecord r = mServiceConnections.get(binder);
11612 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011613 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 + connection.asBinder());
11615 return false;
11616 }
11617
11618 final long origId = Binder.clearCallingIdentity();
11619
11620 removeConnectionLocked(r, null, null);
11621
11622 if (r.binding.service.app != null) {
11623 // This could have made the service less important.
11624 updateOomAdjLocked(r.binding.service.app);
11625 }
11626
11627 Binder.restoreCallingIdentity(origId);
11628 }
11629
11630 return true;
11631 }
11632
11633 public void publishService(IBinder token, Intent intent, IBinder service) {
11634 // Refuse possible leaked file descriptors
11635 if (intent != null && intent.hasFileDescriptors() == true) {
11636 throw new IllegalArgumentException("File descriptors passed in Intent");
11637 }
11638
11639 synchronized(this) {
11640 if (!(token instanceof ServiceRecord)) {
11641 throw new IllegalArgumentException("Invalid service token");
11642 }
11643 ServiceRecord r = (ServiceRecord)token;
11644
11645 final long origId = Binder.clearCallingIdentity();
11646
Joe Onorato8a9b2202010-02-26 18:56:32 -080011647 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011648 + " " + intent + ": " + service);
11649 if (r != null) {
11650 Intent.FilterComparison filter
11651 = new Intent.FilterComparison(intent);
11652 IntentBindRecord b = r.bindings.get(filter);
11653 if (b != null && !b.received) {
11654 b.binder = service;
11655 b.requested = true;
11656 b.received = true;
11657 if (r.connections.size() > 0) {
11658 Iterator<ConnectionRecord> it
11659 = r.connections.values().iterator();
11660 while (it.hasNext()) {
11661 ConnectionRecord c = it.next();
11662 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011663 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011664 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011665 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011667 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011668 TAG, "Published intent: " + intent);
11669 continue;
11670 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011671 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672 try {
11673 c.conn.connected(r.name, service);
11674 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011675 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676 " to connection " + c.conn.asBinder() +
11677 " (in " + c.binding.client.processName + ")", e);
11678 }
11679 }
11680 }
11681 }
11682
11683 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11684
11685 Binder.restoreCallingIdentity(origId);
11686 }
11687 }
11688 }
11689
11690 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11691 // Refuse possible leaked file descriptors
11692 if (intent != null && intent.hasFileDescriptors() == true) {
11693 throw new IllegalArgumentException("File descriptors passed in Intent");
11694 }
11695
11696 synchronized(this) {
11697 if (!(token instanceof ServiceRecord)) {
11698 throw new IllegalArgumentException("Invalid service token");
11699 }
11700 ServiceRecord r = (ServiceRecord)token;
11701
11702 final long origId = Binder.clearCallingIdentity();
11703
11704 if (r != null) {
11705 Intent.FilterComparison filter
11706 = new Intent.FilterComparison(intent);
11707 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011708 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011709 + " at " + b + ": apps="
11710 + (b != null ? b.apps.size() : 0));
11711 if (b != null) {
11712 if (b.apps.size() > 0) {
11713 // Applications have already bound since the last
11714 // unbind, so just rebind right here.
11715 requestServiceBindingLocked(r, b, true);
11716 } else {
11717 // Note to tell the service the next time there is
11718 // a new client.
11719 b.doRebind = true;
11720 }
11721 }
11722
11723 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11724
11725 Binder.restoreCallingIdentity(origId);
11726 }
11727 }
11728 }
11729
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011730 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731 synchronized(this) {
11732 if (!(token instanceof ServiceRecord)) {
11733 throw new IllegalArgumentException("Invalid service token");
11734 }
11735 ServiceRecord r = (ServiceRecord)token;
11736 boolean inStopping = mStoppingServices.contains(token);
11737 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011738 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011739 + ": nesting=" + r.executeNesting
11740 + ", inStopping=" + inStopping);
11741 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011742 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011743 + " with incorrect token: given " + token
11744 + ", expected " + r);
11745 return;
11746 }
11747
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011748 if (type == 1) {
11749 // This is a call from a service start... take care of
11750 // book-keeping.
11751 r.callStart = true;
11752 switch (res) {
11753 case Service.START_STICKY_COMPATIBILITY:
11754 case Service.START_STICKY: {
11755 // We are done with the associated start arguments.
11756 r.findDeliveredStart(startId, true);
11757 // Don't stop if killed.
11758 r.stopIfKilled = false;
11759 break;
11760 }
11761 case Service.START_NOT_STICKY: {
11762 // We are done with the associated start arguments.
11763 r.findDeliveredStart(startId, true);
11764 if (r.lastStartId == startId) {
11765 // There is no more work, and this service
11766 // doesn't want to hang around if killed.
11767 r.stopIfKilled = true;
11768 }
11769 break;
11770 }
11771 case Service.START_REDELIVER_INTENT: {
11772 // We'll keep this item until they explicitly
11773 // call stop for it, but keep track of the fact
11774 // that it was delivered.
11775 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11776 if (si != null) {
11777 si.deliveryCount = 0;
11778 si.doneExecutingCount++;
11779 // Don't stop if killed.
11780 r.stopIfKilled = true;
11781 }
11782 break;
11783 }
11784 default:
11785 throw new IllegalArgumentException(
11786 "Unknown service start result: " + res);
11787 }
11788 if (res == Service.START_STICKY_COMPATIBILITY) {
11789 r.callStart = false;
11790 }
11791 }
11792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011793 final long origId = Binder.clearCallingIdentity();
11794 serviceDoneExecutingLocked(r, inStopping);
11795 Binder.restoreCallingIdentity(origId);
11796 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011797 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011798 + " with token " + token);
11799 }
11800 }
11801 }
11802
11803 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11804 r.executeNesting--;
11805 if (r.executeNesting <= 0 && r.app != null) {
11806 r.app.executingServices.remove(r);
11807 if (r.app.executingServices.size() == 0) {
11808 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11809 }
11810 if (inStopping) {
11811 mStoppingServices.remove(r);
11812 }
11813 updateOomAdjLocked(r.app);
11814 }
11815 }
11816
11817 void serviceTimeout(ProcessRecord proc) {
11818 synchronized(this) {
11819 if (proc.executingServices.size() == 0 || proc.thread == null) {
11820 return;
11821 }
11822 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11823 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11824 ServiceRecord timeout = null;
11825 long nextTime = 0;
11826 while (it.hasNext()) {
11827 ServiceRecord sr = it.next();
11828 if (sr.executingStart < maxTime) {
11829 timeout = sr;
11830 break;
11831 }
11832 if (sr.executingStart > nextTime) {
11833 nextTime = sr.executingStart;
11834 }
11835 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011836 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011837 Slog.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011838 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011839 } else {
11840 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11841 msg.obj = proc;
11842 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11843 }
11844 }
11845 }
11846
11847 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011848 // BACKUP AND RESTORE
11849 // =========================================================
11850
11851 // Cause the target app to be launched if necessary and its backup agent
11852 // instantiated. The backup agent will invoke backupAgentCreated() on the
11853 // activity manager to announce its creation.
11854 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011855 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011856 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11857
11858 synchronized(this) {
11859 // !!! TODO: currently no check here that we're already bound
11860 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11861 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11862 synchronized (stats) {
11863 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11864 }
11865
11866 BackupRecord r = new BackupRecord(ss, app, backupMode);
11867 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11868 // startProcessLocked() returns existing proc's record if it's already running
11869 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011870 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011871 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011872 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011873 return false;
11874 }
11875
11876 r.app = proc;
11877 mBackupTarget = r;
11878 mBackupAppName = app.packageName;
11879
Christopher Tate6fa95972009-06-05 18:43:55 -070011880 // Try not to kill the process during backup
11881 updateOomAdjLocked(proc);
11882
Christopher Tate181fafa2009-05-14 11:12:14 -070011883 // If the process is already attached, schedule the creation of the backup agent now.
11884 // If it is not yet live, this will be done when it attaches to the framework.
11885 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011886 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011887 try {
11888 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11889 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011890 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011891 }
11892 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011893 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011894 }
11895 // Invariants: at this point, the target app process exists and the application
11896 // is either already running or in the process of coming up. mBackupTarget and
11897 // mBackupAppName describe the app, so that when it binds back to the AM we
11898 // know that it's scheduled for a backup-agent operation.
11899 }
11900
11901 return true;
11902 }
11903
11904 // A backup agent has just come up
11905 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011906 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011907 + " = " + agent);
11908
11909 synchronized(this) {
11910 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011911 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011912 return;
11913 }
11914
Christopher Tate043dadc2009-06-02 16:11:00 -070011915 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011916 try {
11917 IBackupManager bm = IBackupManager.Stub.asInterface(
11918 ServiceManager.getService(Context.BACKUP_SERVICE));
11919 bm.agentConnected(agentPackageName, agent);
11920 } catch (RemoteException e) {
11921 // can't happen; the backup manager service is local
11922 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011923 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070011924 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011925 } finally {
11926 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011927 }
11928 }
11929 }
11930
11931 // done with this agent
11932 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011933 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011934 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011935 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011936 return;
11937 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011938
11939 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011940 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011941 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011942 return;
11943 }
11944
Christopher Tate181fafa2009-05-14 11:12:14 -070011945 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011946 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011947 return;
11948 }
11949
Christopher Tate6fa95972009-06-05 18:43:55 -070011950 ProcessRecord proc = mBackupTarget.app;
11951 mBackupTarget = null;
11952 mBackupAppName = null;
11953
11954 // Not backing this app up any more; reset its OOM adjustment
11955 updateOomAdjLocked(proc);
11956
Christopher Tatec7b31e32009-06-10 15:49:30 -070011957 // If the app crashed during backup, 'thread' will be null here
11958 if (proc.thread != null) {
11959 try {
11960 proc.thread.scheduleDestroyBackupAgent(appInfo);
11961 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011962 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070011963 e.printStackTrace();
11964 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011965 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011966 }
11967 }
11968 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011969 // BROADCASTS
11970 // =========================================================
11971
Josh Bartel7f208742010-02-25 11:01:44 -060011972 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011973 List cur) {
11974 final ContentResolver resolver = mContext.getContentResolver();
11975 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11976 if (list == null) {
11977 return cur;
11978 }
11979 int N = list.size();
11980 for (int i=0; i<N; i++) {
11981 Intent intent = list.get(i);
11982 if (filter.match(resolver, intent, true, TAG) >= 0) {
11983 if (cur == null) {
11984 cur = new ArrayList<Intent>();
11985 }
11986 cur.add(intent);
11987 }
11988 }
11989 return cur;
11990 }
11991
11992 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011993 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011994 + mBroadcastsScheduled);
11995
11996 if (mBroadcastsScheduled) {
11997 return;
11998 }
11999 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12000 mBroadcastsScheduled = true;
12001 }
12002
12003 public Intent registerReceiver(IApplicationThread caller,
12004 IIntentReceiver receiver, IntentFilter filter, String permission) {
12005 synchronized(this) {
12006 ProcessRecord callerApp = null;
12007 if (caller != null) {
12008 callerApp = getRecordForAppLocked(caller);
12009 if (callerApp == null) {
12010 throw new SecurityException(
12011 "Unable to find app for caller " + caller
12012 + " (pid=" + Binder.getCallingPid()
12013 + ") when registering receiver " + receiver);
12014 }
12015 }
12016
12017 List allSticky = null;
12018
12019 // Look for any matching sticky broadcasts...
12020 Iterator actions = filter.actionsIterator();
12021 if (actions != null) {
12022 while (actions.hasNext()) {
12023 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012024 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012025 }
12026 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012027 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012028 }
12029
12030 // The first sticky in the list is returned directly back to
12031 // the client.
12032 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12033
Joe Onorato8a9b2202010-02-26 18:56:32 -080012034 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012035 + ": " + sticky);
12036
12037 if (receiver == null) {
12038 return sticky;
12039 }
12040
12041 ReceiverList rl
12042 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12043 if (rl == null) {
12044 rl = new ReceiverList(this, callerApp,
12045 Binder.getCallingPid(),
12046 Binder.getCallingUid(), receiver);
12047 if (rl.app != null) {
12048 rl.app.receivers.add(rl);
12049 } else {
12050 try {
12051 receiver.asBinder().linkToDeath(rl, 0);
12052 } catch (RemoteException e) {
12053 return sticky;
12054 }
12055 rl.linkedToDeath = true;
12056 }
12057 mRegisteredReceivers.put(receiver.asBinder(), rl);
12058 }
12059 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12060 rl.add(bf);
12061 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012062 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012063 }
12064 mReceiverResolver.addFilter(bf);
12065
12066 // Enqueue broadcasts for all existing stickies that match
12067 // this filter.
12068 if (allSticky != null) {
12069 ArrayList receivers = new ArrayList();
12070 receivers.add(bf);
12071
12072 int N = allSticky.size();
12073 for (int i=0; i<N; i++) {
12074 Intent intent = (Intent)allSticky.get(i);
12075 BroadcastRecord r = new BroadcastRecord(intent, null,
12076 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012077 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012078 if (mParallelBroadcasts.size() == 0) {
12079 scheduleBroadcastsLocked();
12080 }
12081 mParallelBroadcasts.add(r);
12082 }
12083 }
12084
12085 return sticky;
12086 }
12087 }
12088
12089 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012090 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012091
12092 boolean doNext = false;
12093
12094 synchronized(this) {
12095 ReceiverList rl
12096 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12097 if (rl != null) {
12098 if (rl.curBroadcast != null) {
12099 BroadcastRecord r = rl.curBroadcast;
12100 doNext = finishReceiverLocked(
12101 receiver.asBinder(), r.resultCode, r.resultData,
12102 r.resultExtras, r.resultAbort, true);
12103 }
12104
12105 if (rl.app != null) {
12106 rl.app.receivers.remove(rl);
12107 }
12108 removeReceiverLocked(rl);
12109 if (rl.linkedToDeath) {
12110 rl.linkedToDeath = false;
12111 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12112 }
12113 }
12114 }
12115
12116 if (!doNext) {
12117 return;
12118 }
12119
12120 final long origId = Binder.clearCallingIdentity();
12121 processNextBroadcast(false);
12122 trimApplications();
12123 Binder.restoreCallingIdentity(origId);
12124 }
12125
12126 void removeReceiverLocked(ReceiverList rl) {
12127 mRegisteredReceivers.remove(rl.receiver.asBinder());
12128 int N = rl.size();
12129 for (int i=0; i<N; i++) {
12130 mReceiverResolver.removeFilter(rl.get(i));
12131 }
12132 }
12133
12134 private final int broadcastIntentLocked(ProcessRecord callerApp,
12135 String callerPackage, Intent intent, String resolvedType,
12136 IIntentReceiver resultTo, int resultCode, String resultData,
12137 Bundle map, String requiredPermission,
12138 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12139 intent = new Intent(intent);
12140
Joe Onorato8a9b2202010-02-26 18:56:32 -080012141 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012142 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12143 + " ordered=" + ordered);
12144 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012145 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012146 }
12147
12148 // Handle special intents: if this broadcast is from the package
12149 // manager about a package being removed, we need to remove all of
12150 // its activities from the history stack.
12151 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12152 intent.getAction());
12153 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12154 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012155 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012156 || uidRemoved) {
12157 if (checkComponentPermission(
12158 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12159 callingPid, callingUid, -1)
12160 == PackageManager.PERMISSION_GRANTED) {
12161 if (uidRemoved) {
12162 final Bundle intentExtras = intent.getExtras();
12163 final int uid = intentExtras != null
12164 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12165 if (uid >= 0) {
12166 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12167 synchronized (bs) {
12168 bs.removeUidStatsLocked(uid);
12169 }
12170 }
12171 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012172 // If resources are unvailble just force stop all
12173 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012174 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012175 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12176 if (list != null && (list.length > 0)) {
12177 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012178 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012179 }
12180 }
12181 } else {
12182 Uri data = intent.getData();
12183 String ssp;
12184 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12185 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12186 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012187 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012189 }
12190 }
12191 }
12192 } else {
12193 String msg = "Permission Denial: " + intent.getAction()
12194 + " broadcast from " + callerPackage + " (pid=" + callingPid
12195 + ", uid=" + callingUid + ")"
12196 + " requires "
12197 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012198 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012199 throw new SecurityException(msg);
12200 }
12201 }
12202
12203 /*
12204 * If this is the time zone changed action, queue up a message that will reset the timezone
12205 * of all currently running processes. This message will get queued up before the broadcast
12206 * happens.
12207 */
12208 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12209 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12210 }
12211
Dianne Hackborn854060af2009-07-09 18:14:31 -070012212 /*
12213 * Prevent non-system code (defined here to be non-persistent
12214 * processes) from sending protected broadcasts.
12215 */
12216 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12217 || callingUid == Process.SHELL_UID || callingUid == 0) {
12218 // Always okay.
12219 } else if (callerApp == null || !callerApp.persistent) {
12220 try {
12221 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12222 intent.getAction())) {
12223 String msg = "Permission Denial: not allowed to send broadcast "
12224 + intent.getAction() + " from pid="
12225 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012226 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012227 throw new SecurityException(msg);
12228 }
12229 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012230 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012231 return BROADCAST_SUCCESS;
12232 }
12233 }
12234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012235 // Add to the sticky list if requested.
12236 if (sticky) {
12237 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12238 callingPid, callingUid)
12239 != PackageManager.PERMISSION_GRANTED) {
12240 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12241 + callingPid + ", uid=" + callingUid
12242 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012243 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012244 throw new SecurityException(msg);
12245 }
12246 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012247 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012248 + " and enforce permission " + requiredPermission);
12249 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12250 }
12251 if (intent.getComponent() != null) {
12252 throw new SecurityException(
12253 "Sticky broadcasts can't target a specific component");
12254 }
12255 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12256 if (list == null) {
12257 list = new ArrayList<Intent>();
12258 mStickyBroadcasts.put(intent.getAction(), list);
12259 }
12260 int N = list.size();
12261 int i;
12262 for (i=0; i<N; i++) {
12263 if (intent.filterEquals(list.get(i))) {
12264 // This sticky already exists, replace it.
12265 list.set(i, new Intent(intent));
12266 break;
12267 }
12268 }
12269 if (i >= N) {
12270 list.add(new Intent(intent));
12271 }
12272 }
12273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012274 // Figure out who all will receive this broadcast.
12275 List receivers = null;
12276 List<BroadcastFilter> registeredReceivers = null;
12277 try {
12278 if (intent.getComponent() != null) {
12279 // Broadcast is going to one specific receiver class...
12280 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012281 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012282 if (ai != null) {
12283 receivers = new ArrayList();
12284 ResolveInfo ri = new ResolveInfo();
12285 ri.activityInfo = ai;
12286 receivers.add(ri);
12287 }
12288 } else {
12289 // Need to resolve the intent to interested receivers...
12290 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12291 == 0) {
12292 receivers =
12293 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012294 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012295 }
Mihai Preda074edef2009-05-18 17:13:31 +020012296 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012297 }
12298 } catch (RemoteException ex) {
12299 // pm is in same process, this will never happen.
12300 }
12301
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012302 final boolean replacePending =
12303 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12304
Joe Onorato8a9b2202010-02-26 18:56:32 -080012305 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012306 + " replacePending=" + replacePending);
12307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012308 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12309 if (!ordered && NR > 0) {
12310 // If we are not serializing this broadcast, then send the
12311 // registered receivers separately so they don't wait for the
12312 // components to be launched.
12313 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12314 callerPackage, callingPid, callingUid, requiredPermission,
12315 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012316 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012317 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012318 TAG, "Enqueueing parallel broadcast " + r
12319 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012320 boolean replaced = false;
12321 if (replacePending) {
12322 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12323 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012324 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012325 "***** DROPPING PARALLEL: " + intent);
12326 mParallelBroadcasts.set(i, r);
12327 replaced = true;
12328 break;
12329 }
12330 }
12331 }
12332 if (!replaced) {
12333 mParallelBroadcasts.add(r);
12334 scheduleBroadcastsLocked();
12335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012336 registeredReceivers = null;
12337 NR = 0;
12338 }
12339
12340 // Merge into one list.
12341 int ir = 0;
12342 if (receivers != null) {
12343 // A special case for PACKAGE_ADDED: do not allow the package
12344 // being added to see this broadcast. This prevents them from
12345 // using this as a back door to get run as soon as they are
12346 // installed. Maybe in the future we want to have a special install
12347 // broadcast or such for apps, but we'd like to deliberately make
12348 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012349 String skipPackages[] = null;
12350 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12351 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12352 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12353 Uri data = intent.getData();
12354 if (data != null) {
12355 String pkgName = data.getSchemeSpecificPart();
12356 if (pkgName != null) {
12357 skipPackages = new String[] { pkgName };
12358 }
12359 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012360 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012361 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012362 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012363 if (skipPackages != null && (skipPackages.length > 0)) {
12364 for (String skipPackage : skipPackages) {
12365 if (skipPackage != null) {
12366 int NT = receivers.size();
12367 for (int it=0; it<NT; it++) {
12368 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12369 if (curt.activityInfo.packageName.equals(skipPackage)) {
12370 receivers.remove(it);
12371 it--;
12372 NT--;
12373 }
12374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012375 }
12376 }
12377 }
12378
12379 int NT = receivers != null ? receivers.size() : 0;
12380 int it = 0;
12381 ResolveInfo curt = null;
12382 BroadcastFilter curr = null;
12383 while (it < NT && ir < NR) {
12384 if (curt == null) {
12385 curt = (ResolveInfo)receivers.get(it);
12386 }
12387 if (curr == null) {
12388 curr = registeredReceivers.get(ir);
12389 }
12390 if (curr.getPriority() >= curt.priority) {
12391 // Insert this broadcast record into the final list.
12392 receivers.add(it, curr);
12393 ir++;
12394 curr = null;
12395 it++;
12396 NT++;
12397 } else {
12398 // Skip to the next ResolveInfo in the final list.
12399 it++;
12400 curt = null;
12401 }
12402 }
12403 }
12404 while (ir < NR) {
12405 if (receivers == null) {
12406 receivers = new ArrayList();
12407 }
12408 receivers.add(registeredReceivers.get(ir));
12409 ir++;
12410 }
12411
12412 if ((receivers != null && receivers.size() > 0)
12413 || resultTo != null) {
12414 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12415 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012416 receivers, resultTo, resultCode, resultData, map, ordered,
12417 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012418 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012419 TAG, "Enqueueing ordered broadcast " + r
12420 + ": prev had " + mOrderedBroadcasts.size());
12421 if (DEBUG_BROADCAST) {
12422 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012423 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012424 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012425 boolean replaced = false;
12426 if (replacePending) {
12427 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12428 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012429 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012430 "***** DROPPING ORDERED: " + intent);
12431 mOrderedBroadcasts.set(i, r);
12432 replaced = true;
12433 break;
12434 }
12435 }
12436 }
12437 if (!replaced) {
12438 mOrderedBroadcasts.add(r);
12439 scheduleBroadcastsLocked();
12440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012441 }
12442
12443 return BROADCAST_SUCCESS;
12444 }
12445
12446 public final int broadcastIntent(IApplicationThread caller,
12447 Intent intent, String resolvedType, IIntentReceiver resultTo,
12448 int resultCode, String resultData, Bundle map,
12449 String requiredPermission, boolean serialized, boolean sticky) {
12450 // Refuse possible leaked file descriptors
12451 if (intent != null && intent.hasFileDescriptors() == true) {
12452 throw new IllegalArgumentException("File descriptors passed in Intent");
12453 }
12454
12455 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012456 int flags = intent.getFlags();
12457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012458 if (!mSystemReady) {
12459 // if the caller really truly claims to know what they're doing, go
12460 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012461 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12462 intent = new Intent(intent);
12463 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12464 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012465 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012466 + " before boot completion");
12467 throw new IllegalStateException("Cannot broadcast before boot completed");
12468 }
12469 }
12470
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012471 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12472 throw new IllegalArgumentException(
12473 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12474 }
12475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012476 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12477 final int callingPid = Binder.getCallingPid();
12478 final int callingUid = Binder.getCallingUid();
12479 final long origId = Binder.clearCallingIdentity();
12480 int res = broadcastIntentLocked(callerApp,
12481 callerApp != null ? callerApp.info.packageName : null,
12482 intent, resolvedType, resultTo,
12483 resultCode, resultData, map, requiredPermission, serialized,
12484 sticky, callingPid, callingUid);
12485 Binder.restoreCallingIdentity(origId);
12486 return res;
12487 }
12488 }
12489
12490 int broadcastIntentInPackage(String packageName, int uid,
12491 Intent intent, String resolvedType, IIntentReceiver resultTo,
12492 int resultCode, String resultData, Bundle map,
12493 String requiredPermission, boolean serialized, boolean sticky) {
12494 synchronized(this) {
12495 final long origId = Binder.clearCallingIdentity();
12496 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12497 resultTo, resultCode, resultData, map, requiredPermission,
12498 serialized, sticky, -1, uid);
12499 Binder.restoreCallingIdentity(origId);
12500 return res;
12501 }
12502 }
12503
12504 public final void unbroadcastIntent(IApplicationThread caller,
12505 Intent intent) {
12506 // Refuse possible leaked file descriptors
12507 if (intent != null && intent.hasFileDescriptors() == true) {
12508 throw new IllegalArgumentException("File descriptors passed in Intent");
12509 }
12510
12511 synchronized(this) {
12512 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12513 != PackageManager.PERMISSION_GRANTED) {
12514 String msg = "Permission Denial: unbroadcastIntent() from pid="
12515 + Binder.getCallingPid()
12516 + ", uid=" + Binder.getCallingUid()
12517 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012518 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012519 throw new SecurityException(msg);
12520 }
12521 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12522 if (list != null) {
12523 int N = list.size();
12524 int i;
12525 for (i=0; i<N; i++) {
12526 if (intent.filterEquals(list.get(i))) {
12527 list.remove(i);
12528 break;
12529 }
12530 }
12531 }
12532 }
12533 }
12534
12535 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12536 String resultData, Bundle resultExtras, boolean resultAbort,
12537 boolean explicit) {
12538 if (mOrderedBroadcasts.size() == 0) {
12539 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012540 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012541 }
12542 return false;
12543 }
12544 BroadcastRecord r = mOrderedBroadcasts.get(0);
12545 if (r.receiver == null) {
12546 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012547 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012548 }
12549 return false;
12550 }
12551 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012552 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012553 return false;
12554 }
12555 int state = r.state;
12556 r.state = r.IDLE;
12557 if (state == r.IDLE) {
12558 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012559 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012560 }
12561 }
12562 r.receiver = null;
12563 r.intent.setComponent(null);
12564 if (r.curApp != null) {
12565 r.curApp.curReceiver = null;
12566 }
12567 if (r.curFilter != null) {
12568 r.curFilter.receiverList.curBroadcast = null;
12569 }
12570 r.curFilter = null;
12571 r.curApp = null;
12572 r.curComponent = null;
12573 r.curReceiver = null;
12574 mPendingBroadcast = null;
12575
12576 r.resultCode = resultCode;
12577 r.resultData = resultData;
12578 r.resultExtras = resultExtras;
12579 r.resultAbort = resultAbort;
12580
12581 // We will process the next receiver right now if this is finishing
12582 // an app receiver (which is always asynchronous) or after we have
12583 // come back from calling a receiver.
12584 return state == BroadcastRecord.APP_RECEIVE
12585 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12586 }
12587
12588 public void finishReceiver(IBinder who, int resultCode, String resultData,
12589 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012590 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012591
12592 // Refuse possible leaked file descriptors
12593 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12594 throw new IllegalArgumentException("File descriptors passed in Bundle");
12595 }
12596
12597 boolean doNext;
12598
12599 final long origId = Binder.clearCallingIdentity();
12600
12601 synchronized(this) {
12602 doNext = finishReceiverLocked(
12603 who, resultCode, resultData, resultExtras, resultAbort, true);
12604 }
12605
12606 if (doNext) {
12607 processNextBroadcast(false);
12608 }
12609 trimApplications();
12610
12611 Binder.restoreCallingIdentity(origId);
12612 }
12613
12614 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12615 if (r.nextReceiver > 0) {
12616 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12617 if (curReceiver instanceof BroadcastFilter) {
12618 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012619 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012620 System.identityHashCode(r),
12621 r.intent.getAction(),
12622 r.nextReceiver - 1,
12623 System.identityHashCode(bf));
12624 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012625 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012626 System.identityHashCode(r),
12627 r.intent.getAction(),
12628 r.nextReceiver - 1,
12629 ((ResolveInfo)curReceiver).toString());
12630 }
12631 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012632 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012633 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012634 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012635 System.identityHashCode(r),
12636 r.intent.getAction(),
12637 r.nextReceiver,
12638 "NONE");
12639 }
12640 }
12641
12642 private final void broadcastTimeout() {
12643 synchronized (this) {
12644 if (mOrderedBroadcasts.size() == 0) {
12645 return;
12646 }
12647 long now = SystemClock.uptimeMillis();
12648 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012649 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012650 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012651 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012652 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012653 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012654 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012655 return;
12656 }
12657
Joe Onorato8a9b2202010-02-26 18:56:32 -080012658 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012659 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012660 r.anrCount++;
12661
12662 // Current receiver has passed its expiration date.
12663 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012664 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012665 return;
12666 }
12667
12668 ProcessRecord app = null;
12669
12670 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012671 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012672 logBroadcastReceiverDiscard(r);
12673 if (curReceiver instanceof BroadcastFilter) {
12674 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12675 if (bf.receiverList.pid != 0
12676 && bf.receiverList.pid != MY_PID) {
12677 synchronized (this.mPidsSelfLocked) {
12678 app = this.mPidsSelfLocked.get(
12679 bf.receiverList.pid);
12680 }
12681 }
12682 } else {
12683 app = r.curApp;
12684 }
12685
12686 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012687 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012688 }
12689
12690 if (mPendingBroadcast == r) {
12691 mPendingBroadcast = null;
12692 }
12693
12694 // Move on to the next receiver.
12695 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12696 r.resultExtras, r.resultAbort, true);
12697 scheduleBroadcastsLocked();
12698 }
12699 }
12700
12701 private final void processCurBroadcastLocked(BroadcastRecord r,
12702 ProcessRecord app) throws RemoteException {
12703 if (app.thread == null) {
12704 throw new RemoteException();
12705 }
12706 r.receiver = app.thread.asBinder();
12707 r.curApp = app;
12708 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012709 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012710
12711 // Tell the application to launch this receiver.
12712 r.intent.setComponent(r.curComponent);
12713
12714 boolean started = false;
12715 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012716 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012717 "Delivering to component " + r.curComponent
12718 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012719 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012720 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12721 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12722 started = true;
12723 } finally {
12724 if (!started) {
12725 r.receiver = null;
12726 r.curApp = null;
12727 app.curReceiver = null;
12728 }
12729 }
12730
12731 }
12732
12733 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012734 Intent intent, int resultCode, String data, Bundle extras,
12735 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012736 if (app != null && app.thread != null) {
12737 // If we have an app thread, do the call through that so it is
12738 // correctly ordered with other one-way calls.
12739 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012740 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012741 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012742 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012743 }
12744 }
12745
12746 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12747 BroadcastFilter filter, boolean ordered) {
12748 boolean skip = false;
12749 if (filter.requiredPermission != null) {
12750 int perm = checkComponentPermission(filter.requiredPermission,
12751 r.callingPid, r.callingUid, -1);
12752 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012753 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012754 + r.intent.toString()
12755 + " from " + r.callerPackage + " (pid="
12756 + r.callingPid + ", uid=" + r.callingUid + ")"
12757 + " requires " + filter.requiredPermission
12758 + " due to registered receiver " + filter);
12759 skip = true;
12760 }
12761 }
12762 if (r.requiredPermission != null) {
12763 int perm = checkComponentPermission(r.requiredPermission,
12764 filter.receiverList.pid, filter.receiverList.uid, -1);
12765 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012766 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012767 + r.intent.toString()
12768 + " to " + filter.receiverList.app
12769 + " (pid=" + filter.receiverList.pid
12770 + ", uid=" + filter.receiverList.uid + ")"
12771 + " requires " + r.requiredPermission
12772 + " due to sender " + r.callerPackage
12773 + " (uid " + r.callingUid + ")");
12774 skip = true;
12775 }
12776 }
12777
12778 if (!skip) {
12779 // If this is not being sent as an ordered broadcast, then we
12780 // don't want to touch the fields that keep track of the current
12781 // state of ordered broadcasts.
12782 if (ordered) {
12783 r.receiver = filter.receiverList.receiver.asBinder();
12784 r.curFilter = filter;
12785 filter.receiverList.curBroadcast = r;
12786 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012787 if (filter.receiverList.app != null) {
12788 // Bump hosting application to no longer be in background
12789 // scheduling class. Note that we can't do that if there
12790 // isn't an app... but we can only be in that case for
12791 // things that directly call the IActivityManager API, which
12792 // are already core system stuff so don't matter for this.
12793 r.curApp = filter.receiverList.app;
12794 filter.receiverList.app.curReceiver = r;
12795 updateOomAdjLocked();
12796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012797 }
12798 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012799 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012800 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012801 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012802 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012803 }
12804 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12805 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012806 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012807 if (ordered) {
12808 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12809 }
12810 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012811 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012812 if (ordered) {
12813 r.receiver = null;
12814 r.curFilter = null;
12815 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012816 if (filter.receiverList.app != null) {
12817 filter.receiverList.app.curReceiver = null;
12818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012819 }
12820 }
12821 }
12822 }
12823
Dianne Hackborn12527f92009-11-11 17:39:50 -080012824 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12825 if (r.callingUid < 0) {
12826 // This was from a registerReceiver() call; ignore it.
12827 return;
12828 }
12829 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12830 MAX_BROADCAST_HISTORY-1);
12831 r.finishTime = SystemClock.uptimeMillis();
12832 mBroadcastHistory[0] = r;
12833 }
12834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012835 private final void processNextBroadcast(boolean fromMsg) {
12836 synchronized(this) {
12837 BroadcastRecord r;
12838
Joe Onorato8a9b2202010-02-26 18:56:32 -080012839 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012840 + mParallelBroadcasts.size() + " broadcasts, "
12841 + mOrderedBroadcasts.size() + " serialized broadcasts");
12842
12843 updateCpuStats();
12844
12845 if (fromMsg) {
12846 mBroadcastsScheduled = false;
12847 }
12848
12849 // First, deliver any non-serialized broadcasts right away.
12850 while (mParallelBroadcasts.size() > 0) {
12851 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012852 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012853 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012854 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012855 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012856 for (int i=0; i<N; i++) {
12857 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012858 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012859 "Delivering non-serialized to registered "
12860 + target + ": " + r);
12861 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12862 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012863 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012864 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012865 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012866 }
12867
12868 // Now take care of the next serialized one...
12869
12870 // If we are waiting for a process to come up to handle the next
12871 // broadcast, then do nothing at this point. Just in case, we
12872 // check that the process we're waiting for still exists.
12873 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012874 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012875 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012876 + mPendingBroadcast.curApp);
12877 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012878
12879 boolean isDead;
12880 synchronized (mPidsSelfLocked) {
12881 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12882 }
12883 if (!isDead) {
12884 // It's still alive, so keep waiting
12885 return;
12886 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012887 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012888 + " died before responding to broadcast");
12889 mPendingBroadcast = null;
12890 }
12891 }
12892
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012893 boolean looped = false;
12894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012895 do {
12896 if (mOrderedBroadcasts.size() == 0) {
12897 // No more broadcasts pending, so all done!
12898 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012899 if (looped) {
12900 // If we had finished the last ordered broadcast, then
12901 // make sure all processes have correct oom and sched
12902 // adjustments.
12903 updateOomAdjLocked();
12904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012905 return;
12906 }
12907 r = mOrderedBroadcasts.get(0);
12908 boolean forceReceive = false;
12909
12910 // Ensure that even if something goes awry with the timeout
12911 // detection, we catch "hung" broadcasts here, discard them,
12912 // and continue to make progress.
12913 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12914 long now = SystemClock.uptimeMillis();
12915 if (r.dispatchTime > 0) {
12916 if ((numReceivers > 0) &&
12917 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012918 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012919 + " now=" + now
12920 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012921 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012922 + " intent=" + r.intent
12923 + " numReceivers=" + numReceivers
12924 + " nextReceiver=" + r.nextReceiver
12925 + " state=" + r.state);
12926 broadcastTimeout(); // forcibly finish this broadcast
12927 forceReceive = true;
12928 r.state = BroadcastRecord.IDLE;
12929 }
12930 }
12931
12932 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012933 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012934 "processNextBroadcast() called when not idle (state="
12935 + r.state + ")");
12936 return;
12937 }
12938
12939 if (r.receivers == null || r.nextReceiver >= numReceivers
12940 || r.resultAbort || forceReceive) {
12941 // No more receivers for this broadcast! Send the final
12942 // result if requested...
12943 if (r.resultTo != null) {
12944 try {
12945 if (DEBUG_BROADCAST) {
12946 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012947 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012948 + " seq=" + seq + " app=" + r.callerApp);
12949 }
12950 performReceive(r.callerApp, r.resultTo,
12951 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012952 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012953 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012954 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012955 }
12956 }
12957
Joe Onorato8a9b2202010-02-26 18:56:32 -080012958 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012959 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12960
Joe Onorato8a9b2202010-02-26 18:56:32 -080012961 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012962 + r);
12963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012964 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012965 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012966 mOrderedBroadcasts.remove(0);
12967 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012968 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012969 continue;
12970 }
12971 } while (r == null);
12972
12973 // Get the next receiver...
12974 int recIdx = r.nextReceiver++;
12975
12976 // Keep track of when this receiver started, and make sure there
12977 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012978 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012979 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012980 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012981
Joe Onorato8a9b2202010-02-26 18:56:32 -080012982 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012983 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012984 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012985 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012986 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012987 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012988 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012989 }
12990
12991 Object nextReceiver = r.receivers.get(recIdx);
12992 if (nextReceiver instanceof BroadcastFilter) {
12993 // Simple case: this is a registered receiver who gets
12994 // a direct call.
12995 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012996 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012997 "Delivering serialized to registered "
12998 + filter + ": " + r);
12999 deliverToRegisteredReceiver(r, filter, r.ordered);
13000 if (r.receiver == null || !r.ordered) {
13001 // The receiver has already finished, so schedule to
13002 // process the next one.
13003 r.state = BroadcastRecord.IDLE;
13004 scheduleBroadcastsLocked();
13005 }
13006 return;
13007 }
13008
13009 // Hard case: need to instantiate the receiver, possibly
13010 // starting its application process to host it.
13011
13012 ResolveInfo info =
13013 (ResolveInfo)nextReceiver;
13014
13015 boolean skip = false;
13016 int perm = checkComponentPermission(info.activityInfo.permission,
13017 r.callingPid, r.callingUid,
13018 info.activityInfo.exported
13019 ? -1 : info.activityInfo.applicationInfo.uid);
13020 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013021 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013022 + r.intent.toString()
13023 + " from " + r.callerPackage + " (pid=" + r.callingPid
13024 + ", uid=" + r.callingUid + ")"
13025 + " requires " + info.activityInfo.permission
13026 + " due to receiver " + info.activityInfo.packageName
13027 + "/" + info.activityInfo.name);
13028 skip = true;
13029 }
13030 if (r.callingUid != Process.SYSTEM_UID &&
13031 r.requiredPermission != null) {
13032 try {
13033 perm = ActivityThread.getPackageManager().
13034 checkPermission(r.requiredPermission,
13035 info.activityInfo.applicationInfo.packageName);
13036 } catch (RemoteException e) {
13037 perm = PackageManager.PERMISSION_DENIED;
13038 }
13039 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013040 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013041 + r.intent + " to "
13042 + info.activityInfo.applicationInfo.packageName
13043 + " requires " + r.requiredPermission
13044 + " due to sender " + r.callerPackage
13045 + " (uid " + r.callingUid + ")");
13046 skip = true;
13047 }
13048 }
13049 if (r.curApp != null && r.curApp.crashing) {
13050 // If the target process is crashing, just skip it.
13051 skip = true;
13052 }
13053
13054 if (skip) {
13055 r.receiver = null;
13056 r.curFilter = null;
13057 r.state = BroadcastRecord.IDLE;
13058 scheduleBroadcastsLocked();
13059 return;
13060 }
13061
13062 r.state = BroadcastRecord.APP_RECEIVE;
13063 String targetProcess = info.activityInfo.processName;
13064 r.curComponent = new ComponentName(
13065 info.activityInfo.applicationInfo.packageName,
13066 info.activityInfo.name);
13067 r.curReceiver = info.activityInfo;
13068
13069 // Is this receiver's application already running?
13070 ProcessRecord app = getProcessRecordLocked(targetProcess,
13071 info.activityInfo.applicationInfo.uid);
13072 if (app != null && app.thread != null) {
13073 try {
13074 processCurBroadcastLocked(r, app);
13075 return;
13076 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013077 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013078 + r.curComponent, e);
13079 }
13080
13081 // If a dead object exception was thrown -- fall through to
13082 // restart the application.
13083 }
13084
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013085 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013086 if ((r.curApp=startProcessLocked(targetProcess,
13087 info.activityInfo.applicationInfo, true,
13088 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013089 "broadcast", r.curComponent,
13090 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13091 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013092 // Ah, this recipient is unavailable. Finish it if necessary,
13093 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013094 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013095 + info.activityInfo.applicationInfo.packageName + "/"
13096 + info.activityInfo.applicationInfo.uid + " for broadcast "
13097 + r.intent + ": process is bad");
13098 logBroadcastReceiverDiscard(r);
13099 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13100 r.resultExtras, r.resultAbort, true);
13101 scheduleBroadcastsLocked();
13102 r.state = BroadcastRecord.IDLE;
13103 return;
13104 }
13105
13106 mPendingBroadcast = r;
13107 }
13108 }
13109
13110 // =========================================================
13111 // INSTRUMENTATION
13112 // =========================================================
13113
13114 public boolean startInstrumentation(ComponentName className,
13115 String profileFile, int flags, Bundle arguments,
13116 IInstrumentationWatcher watcher) {
13117 // Refuse possible leaked file descriptors
13118 if (arguments != null && arguments.hasFileDescriptors()) {
13119 throw new IllegalArgumentException("File descriptors passed in Bundle");
13120 }
13121
13122 synchronized(this) {
13123 InstrumentationInfo ii = null;
13124 ApplicationInfo ai = null;
13125 try {
13126 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013127 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013128 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013129 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013130 } catch (PackageManager.NameNotFoundException e) {
13131 }
13132 if (ii == null) {
13133 reportStartInstrumentationFailure(watcher, className,
13134 "Unable to find instrumentation info for: " + className);
13135 return false;
13136 }
13137 if (ai == null) {
13138 reportStartInstrumentationFailure(watcher, className,
13139 "Unable to find instrumentation target package: " + ii.targetPackage);
13140 return false;
13141 }
13142
13143 int match = mContext.getPackageManager().checkSignatures(
13144 ii.targetPackage, ii.packageName);
13145 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13146 String msg = "Permission Denial: starting instrumentation "
13147 + className + " from pid="
13148 + Binder.getCallingPid()
13149 + ", uid=" + Binder.getCallingPid()
13150 + " not allowed because package " + ii.packageName
13151 + " does not have a signature matching the target "
13152 + ii.targetPackage;
13153 reportStartInstrumentationFailure(watcher, className, msg);
13154 throw new SecurityException(msg);
13155 }
13156
13157 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013158 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013159 ProcessRecord app = addAppLocked(ai);
13160 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013161 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013162 app.instrumentationProfileFile = profileFile;
13163 app.instrumentationArguments = arguments;
13164 app.instrumentationWatcher = watcher;
13165 app.instrumentationResultClass = className;
13166 Binder.restoreCallingIdentity(origId);
13167 }
13168
13169 return true;
13170 }
13171
13172 /**
13173 * Report errors that occur while attempting to start Instrumentation. Always writes the
13174 * error to the logs, but if somebody is watching, send the report there too. This enables
13175 * the "am" command to report errors with more information.
13176 *
13177 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13178 * @param cn The component name of the instrumentation.
13179 * @param report The error report.
13180 */
13181 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13182 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013183 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013184 try {
13185 if (watcher != null) {
13186 Bundle results = new Bundle();
13187 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13188 results.putString("Error", report);
13189 watcher.instrumentationStatus(cn, -1, results);
13190 }
13191 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013192 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013193 }
13194 }
13195
13196 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13197 if (app.instrumentationWatcher != null) {
13198 try {
13199 // NOTE: IInstrumentationWatcher *must* be oneway here
13200 app.instrumentationWatcher.instrumentationFinished(
13201 app.instrumentationClass,
13202 resultCode,
13203 results);
13204 } catch (RemoteException e) {
13205 }
13206 }
13207 app.instrumentationWatcher = null;
13208 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013209 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013210 app.instrumentationProfileFile = null;
13211 app.instrumentationArguments = null;
13212
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013213 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013214 }
13215
13216 public void finishInstrumentation(IApplicationThread target,
13217 int resultCode, Bundle results) {
13218 // Refuse possible leaked file descriptors
13219 if (results != null && results.hasFileDescriptors()) {
13220 throw new IllegalArgumentException("File descriptors passed in Intent");
13221 }
13222
13223 synchronized(this) {
13224 ProcessRecord app = getRecordForAppLocked(target);
13225 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013226 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013227 return;
13228 }
13229 final long origId = Binder.clearCallingIdentity();
13230 finishInstrumentationLocked(app, resultCode, results);
13231 Binder.restoreCallingIdentity(origId);
13232 }
13233 }
13234
13235 // =========================================================
13236 // CONFIGURATION
13237 // =========================================================
13238
13239 public ConfigurationInfo getDeviceConfigurationInfo() {
13240 ConfigurationInfo config = new ConfigurationInfo();
13241 synchronized (this) {
13242 config.reqTouchScreen = mConfiguration.touchscreen;
13243 config.reqKeyboardType = mConfiguration.keyboard;
13244 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013245 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13246 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013247 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13248 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013249 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13250 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013251 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13252 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013253 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013254 }
13255 return config;
13256 }
13257
13258 public Configuration getConfiguration() {
13259 Configuration ci;
13260 synchronized(this) {
13261 ci = new Configuration(mConfiguration);
13262 }
13263 return ci;
13264 }
13265
13266 public void updateConfiguration(Configuration values) {
13267 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13268 "updateConfiguration()");
13269
13270 synchronized(this) {
13271 if (values == null && mWindowManager != null) {
13272 // sentinel: fetch the current configuration from the window manager
13273 values = mWindowManager.computeNewConfiguration();
13274 }
13275
13276 final long origId = Binder.clearCallingIdentity();
13277 updateConfigurationLocked(values, null);
13278 Binder.restoreCallingIdentity(origId);
13279 }
13280 }
13281
13282 /**
13283 * Do either or both things: (1) change the current configuration, and (2)
13284 * make sure the given activity is running with the (now) current
13285 * configuration. Returns true if the activity has been left running, or
13286 * false if <var>starting</var> is being destroyed to match the new
13287 * configuration.
13288 */
13289 public boolean updateConfigurationLocked(Configuration values,
13290 HistoryRecord starting) {
13291 int changes = 0;
13292
13293 boolean kept = true;
13294
13295 if (values != null) {
13296 Configuration newConfig = new Configuration(mConfiguration);
13297 changes = newConfig.updateFrom(values);
13298 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013299 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013300 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013301 }
13302
Doug Zongker2bec3d42009-12-04 12:52:44 -080013303 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013304
13305 if (values.locale != null) {
13306 saveLocaleLocked(values.locale,
13307 !values.locale.equals(mConfiguration.locale),
13308 values.userSetLocale);
13309 }
13310
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013311 mConfigurationSeq++;
13312 if (mConfigurationSeq <= 0) {
13313 mConfigurationSeq = 1;
13314 }
13315 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013316 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013317 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013318
13319 AttributeCache ac = AttributeCache.instance();
13320 if (ac != null) {
13321 ac.updateConfiguration(mConfiguration);
13322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013323
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013324 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13325 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13326 msg.obj = new Configuration(mConfiguration);
13327 mHandler.sendMessage(msg);
13328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013329
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013330 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13331 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013332 try {
13333 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013334 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013335 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013336 app.thread.scheduleConfigurationChanged(mConfiguration);
13337 }
13338 } catch (Exception e) {
13339 }
13340 }
13341 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013342 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13343 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013344 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13345 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013346 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13347 broadcastIntentLocked(null, null,
13348 new Intent(Intent.ACTION_LOCALE_CHANGED),
13349 null, null, 0, null, null,
13350 null, false, false, MY_PID, Process.SYSTEM_UID);
13351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013352 }
13353 }
13354
13355 if (changes != 0 && starting == null) {
13356 // If the configuration changed, and the caller is not already
13357 // in the process of starting an activity, then find the top
13358 // activity to check if its configuration needs to change.
13359 starting = topRunningActivityLocked(null);
13360 }
13361
13362 if (starting != null) {
13363 kept = ensureActivityConfigurationLocked(starting, changes);
13364 if (kept) {
13365 // If this didn't result in the starting activity being
13366 // destroyed, then we need to make sure at this point that all
13367 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013368 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013369 + ", ensuring others are correct.");
13370 ensureActivitiesVisibleLocked(starting, changes);
13371 }
13372 }
13373
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013374 if (values != null && mWindowManager != null) {
13375 mWindowManager.setNewConfiguration(mConfiguration);
13376 }
13377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013378 return kept;
13379 }
13380
13381 private final boolean relaunchActivityLocked(HistoryRecord r,
13382 int changes, boolean andResume) {
13383 List<ResultInfo> results = null;
13384 List<Intent> newIntents = null;
13385 if (andResume) {
13386 results = r.results;
13387 newIntents = r.newIntents;
13388 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013389 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013390 + " with results=" + results + " newIntents=" + newIntents
13391 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013392 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13393 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013394 r.task.taskId, r.shortComponentName);
13395
13396 r.startFreezingScreenLocked(r.app, 0);
13397
13398 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013399 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013400 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013401 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013402 // Note: don't need to call pauseIfSleepingLocked() here, because
13403 // the caller will only pass in 'andResume' if this activity is
13404 // currently resumed, which implies we aren't sleeping.
13405 } catch (RemoteException e) {
13406 return false;
13407 }
13408
13409 if (andResume) {
13410 r.results = null;
13411 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013412 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013413 }
13414
13415 return true;
13416 }
13417
13418 /**
13419 * Make sure the given activity matches the current configuration. Returns
13420 * false if the activity had to be destroyed. Returns true if the
13421 * configuration is the same, or the activity will remain running as-is
13422 * for whatever reason. Ensures the HistoryRecord is updated with the
13423 * correct configuration and all other bookkeeping is handled.
13424 */
13425 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13426 int globalChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013427 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013428 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013429
13430 // Short circuit: if the two configurations are the exact same
13431 // object (the common case), then there is nothing to do.
13432 Configuration newConfig = mConfiguration;
13433 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013434 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013435 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013436 return true;
13437 }
13438
13439 // We don't worry about activities that are finishing.
13440 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013441 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013442 "Configuration doesn't matter in finishing " + r);
13443 r.stopFreezingScreenLocked(false);
13444 return true;
13445 }
13446
13447 // Okay we now are going to make this activity have the new config.
13448 // But then we need to figure out how it needs to deal with that.
13449 Configuration oldConfig = r.configuration;
13450 r.configuration = newConfig;
13451
13452 // If the activity isn't currently running, just leave the new
13453 // configuration and it will pick that up next time it starts.
13454 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013455 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013456 "Configuration doesn't matter not running " + r);
13457 r.stopFreezingScreenLocked(false);
13458 return true;
13459 }
13460
13461 // If the activity isn't persistent, there is a chance we will
13462 // need to restart it.
13463 if (!r.persistent) {
13464
13465 // Figure out what has changed between the two configurations.
13466 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013467 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013468 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013469 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013470 + Integer.toHexString(r.info.configChanges)
13471 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013472 }
13473 if ((changes&(~r.info.configChanges)) != 0) {
13474 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13475 r.configChangeFlags |= changes;
13476 r.startFreezingScreenLocked(r.app, globalChanges);
13477 if (r.app == null || r.app.thread == null) {
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 destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013480 destroyActivityLocked(r, true);
13481 } else if (r.state == ActivityState.PAUSING) {
13482 // A little annoying: we are waiting for this activity to
13483 // finish pausing. Let's not do anything now, but just
13484 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013485 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013486 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013487 r.configDestroy = true;
13488 return true;
13489 } else if (r.state == ActivityState.RESUMED) {
13490 // Try to optimize this case: the configuration is changing
13491 // and we need to restart the top, resumed activity.
13492 // Instead of doing the normal handshaking, just say
13493 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013494 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013495 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013496 relaunchActivityLocked(r, r.configChangeFlags, true);
13497 r.configChangeFlags = 0;
13498 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013499 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013500 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013501 relaunchActivityLocked(r, r.configChangeFlags, false);
13502 r.configChangeFlags = 0;
13503 }
13504
13505 // All done... tell the caller we weren't able to keep this
13506 // activity around.
13507 return false;
13508 }
13509 }
13510
13511 // Default case: the activity can handle this new configuration, so
13512 // hand it over. Note that we don't need to give it the new
13513 // configuration, since we always send configuration changes to all
13514 // process when they happen so it can just use whatever configuration
13515 // it last got.
13516 if (r.app != null && r.app.thread != null) {
13517 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013518 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013519 r.app.thread.scheduleActivityConfigurationChanged(r);
13520 } catch (RemoteException e) {
13521 // If process died, whatever.
13522 }
13523 }
13524 r.stopFreezingScreenLocked(false);
13525
13526 return true;
13527 }
13528
13529 /**
13530 * Save the locale. You must be inside a synchronized (this) block.
13531 */
13532 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13533 if(isDiff) {
13534 SystemProperties.set("user.language", l.getLanguage());
13535 SystemProperties.set("user.region", l.getCountry());
13536 }
13537
13538 if(isPersist) {
13539 SystemProperties.set("persist.sys.language", l.getLanguage());
13540 SystemProperties.set("persist.sys.country", l.getCountry());
13541 SystemProperties.set("persist.sys.localevar", l.getVariant());
13542 }
13543 }
13544
13545 // =========================================================
13546 // LIFETIME MANAGEMENT
13547 // =========================================================
13548
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013549 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13550 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013551 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013552 // This adjustment has already been computed. If we are calling
13553 // from the top, we may have already computed our adjustment with
13554 // an earlier hidden adjustment that isn't really for us... if
13555 // so, use the new hidden adjustment.
13556 if (!recursed && app.hidden) {
13557 app.curAdj = hiddenAdj;
13558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013559 return app.curAdj;
13560 }
13561
13562 if (app.thread == null) {
13563 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013564 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013565 return (app.curAdj=EMPTY_APP_ADJ);
13566 }
13567
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013568 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13569 // The max adjustment doesn't allow this app to be anything
13570 // below foreground, so it is not worth doing work for it.
13571 app.adjType = "fixed";
13572 app.adjSeq = mAdjSeq;
13573 app.curRawAdj = app.maxAdj;
13574 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13575 return (app.curAdj=app.maxAdj);
13576 }
13577
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013578 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013579 app.adjSource = null;
13580 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013581 app.empty = false;
13582 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013583
The Android Open Source Project4df24232009-03-05 14:34:35 -080013584 // Determine the importance of the process, starting with most
13585 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013586 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013587 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013588 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013589 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013590 // The last app on the list is the foreground app.
13591 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013592 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013593 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013594 } else if (app.instrumentationClass != null) {
13595 // Don't want to kill running instrumentation.
13596 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013597 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013598 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013599 } else if (app.persistentActivities > 0) {
13600 // Special persistent activities... shouldn't be used these days.
13601 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013602 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013603 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013604 } else if (app.curReceiver != null ||
13605 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13606 // An app that is currently receiving a broadcast also
13607 // counts as being in the foreground.
13608 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013609 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013610 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013611 } else if (app.executingServices.size() > 0) {
13612 // An app that is currently executing a service callback also
13613 // counts as being in the foreground.
13614 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013615 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013616 app.adjType = "exec-service";
13617 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013618 // The user is aware of this app, so make it visible.
13619 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013620 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013621 app.adjType = "foreground-service";
13622 } else if (app.forcingToForeground != null) {
13623 // The user is aware of this app, so make it visible.
13624 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 = "force-foreground";
13627 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013628 } else if (app == mHomeProcess) {
13629 // This process is hosting what we currently consider to be the
13630 // home app, so we don't want to let it go into the background.
13631 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013632 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013633 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013634 } else if ((N=app.activities.size()) != 0) {
13635 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013636 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013637 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013638 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013639 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013640 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013641 for (int j=0; j<N; j++) {
13642 if (((HistoryRecord)app.activities.get(j)).visible) {
13643 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013644 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013645 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013646 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013647 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013648 break;
13649 }
13650 }
13651 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013652 // A very not-needed process. If this is lower in the lru list,
13653 // we will push it in to the empty bucket.
13654 app.hidden = true;
13655 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013656 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013657 adj = hiddenAdj;
13658 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013659 }
13660
Joe Onorato8a9b2202010-02-26 18:56:32 -080013661 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013662
The Android Open Source Project4df24232009-03-05 14:34:35 -080013663 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013664 // there are applications dependent on our services or providers, but
13665 // this gives us a baseline and makes sure we don't get into an
13666 // infinite recursion.
13667 app.adjSeq = mAdjSeq;
13668 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013669
Christopher Tate6fa95972009-06-05 18:43:55 -070013670 if (mBackupTarget != null && app == mBackupTarget.app) {
13671 // If possible we want to avoid killing apps while they're being backed up
13672 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013673 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013674 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013675 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013676 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013677 }
13678 }
13679
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013680 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13681 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013682 final long now = SystemClock.uptimeMillis();
13683 // This process is more important if the top activity is
13684 // bound to the service.
13685 Iterator jt = app.services.iterator();
13686 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13687 ServiceRecord s = (ServiceRecord)jt.next();
13688 if (s.startRequested) {
13689 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13690 // This service has seen some activity within
13691 // recent memory, so we will keep its process ahead
13692 // of the background processes.
13693 if (adj > SECONDARY_SERVER_ADJ) {
13694 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013695 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013696 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013697 }
13698 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013699 // If we have let the service slide into the background
13700 // state, still have some text describing what it is doing
13701 // even though the service no longer has an impact.
13702 if (adj > SECONDARY_SERVER_ADJ) {
13703 app.adjType = "started-bg-services";
13704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013705 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013706 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13707 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013708 Iterator<ConnectionRecord> kt
13709 = s.connections.values().iterator();
13710 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13711 // XXX should compute this based on the max of
13712 // all connected clients.
13713 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013714 if (cr.binding.client == app) {
13715 // Binding to ourself is not interesting.
13716 continue;
13717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013718 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13719 ProcessRecord client = cr.binding.client;
13720 int myHiddenAdj = hiddenAdj;
13721 if (myHiddenAdj > client.hiddenAdj) {
13722 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13723 myHiddenAdj = client.hiddenAdj;
13724 } else {
13725 myHiddenAdj = VISIBLE_APP_ADJ;
13726 }
13727 }
13728 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013729 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013730 if (adj > clientAdj) {
13731 adj = clientAdj > VISIBLE_APP_ADJ
13732 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013733 if (!client.hidden) {
13734 app.hidden = false;
13735 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013736 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013737 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13738 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013739 app.adjSource = cr.binding.client;
13740 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013741 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013742 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13743 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13744 schedGroup = Process.THREAD_GROUP_DEFAULT;
13745 }
13746 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013747 }
13748 HistoryRecord a = cr.activity;
13749 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013750 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013751 //}
13752 if (a != null && adj > FOREGROUND_APP_ADJ &&
13753 (a.state == ActivityState.RESUMED
13754 || a.state == ActivityState.PAUSING)) {
13755 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013756 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013757 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013758 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013759 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13760 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013761 app.adjSource = a;
13762 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013763 }
13764 }
13765 }
13766 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013767
13768 // Finally, f this process has active services running in it, we
13769 // would like to avoid killing it unless it would prevent the current
13770 // application from running. By default we put the process in
13771 // with the rest of the background processes; as we scan through
13772 // its services we may bump it up from there.
13773 if (adj > hiddenAdj) {
13774 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013775 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013776 app.adjType = "bg-services";
13777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013778 }
13779
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013780 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13781 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013782 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013783 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13784 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013785 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13786 if (cpr.clients.size() != 0) {
13787 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13788 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13789 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013790 if (client == app) {
13791 // Being our own client is not interesting.
13792 continue;
13793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013794 int myHiddenAdj = hiddenAdj;
13795 if (myHiddenAdj > client.hiddenAdj) {
13796 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13797 myHiddenAdj = client.hiddenAdj;
13798 } else {
13799 myHiddenAdj = FOREGROUND_APP_ADJ;
13800 }
13801 }
13802 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013803 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013804 if (adj > clientAdj) {
13805 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013806 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013807 if (!client.hidden) {
13808 app.hidden = false;
13809 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013810 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013811 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13812 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013813 app.adjSource = client;
13814 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013815 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013816 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13817 schedGroup = Process.THREAD_GROUP_DEFAULT;
13818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013819 }
13820 }
13821 // If the provider has external (non-framework) process
13822 // dependencies, ensure that its adjustment is at least
13823 // FOREGROUND_APP_ADJ.
13824 if (cpr.externals != 0) {
13825 if (adj > FOREGROUND_APP_ADJ) {
13826 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013827 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013828 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013829 app.adjType = "provider";
13830 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013831 }
13832 }
13833 }
13834 }
13835
13836 app.curRawAdj = adj;
13837
Joe Onorato8a9b2202010-02-26 18:56:32 -080013838 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013839 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13840 if (adj > app.maxAdj) {
13841 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013842 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13843 schedGroup = Process.THREAD_GROUP_DEFAULT;
13844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013845 }
13846
13847 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013848 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013850 return adj;
13851 }
13852
13853 /**
13854 * Ask a given process to GC right now.
13855 */
13856 final void performAppGcLocked(ProcessRecord app) {
13857 try {
13858 app.lastRequestedGc = SystemClock.uptimeMillis();
13859 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013860 if (app.reportLowMemory) {
13861 app.reportLowMemory = false;
13862 app.thread.scheduleLowMemory();
13863 } else {
13864 app.thread.processInBackground();
13865 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013866 }
13867 } catch (Exception e) {
13868 // whatever.
13869 }
13870 }
13871
13872 /**
13873 * Returns true if things are idle enough to perform GCs.
13874 */
Josh Bartel7f208742010-02-25 11:01:44 -060013875 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013876 return mParallelBroadcasts.size() == 0
13877 && mOrderedBroadcasts.size() == 0
13878 && (mSleeping || (mResumedActivity != null &&
13879 mResumedActivity.idle));
13880 }
13881
13882 /**
13883 * Perform GCs on all processes that are waiting for it, but only
13884 * if things are idle.
13885 */
13886 final void performAppGcsLocked() {
13887 final int N = mProcessesToGc.size();
13888 if (N <= 0) {
13889 return;
13890 }
Josh Bartel7f208742010-02-25 11:01:44 -060013891 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013892 while (mProcessesToGc.size() > 0) {
13893 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013894 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13895 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13896 <= SystemClock.uptimeMillis()) {
13897 // To avoid spamming the system, we will GC processes one
13898 // at a time, waiting a few seconds between each.
13899 performAppGcLocked(proc);
13900 scheduleAppGcsLocked();
13901 return;
13902 } else {
13903 // It hasn't been long enough since we last GCed this
13904 // process... put it in the list to wait for its time.
13905 addProcessToGcListLocked(proc);
13906 break;
13907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013908 }
13909 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013910
13911 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013912 }
13913 }
13914
13915 /**
13916 * If all looks good, perform GCs on all processes waiting for them.
13917 */
13918 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060013919 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013920 performAppGcsLocked();
13921 return;
13922 }
13923 // Still not idle, wait some more.
13924 scheduleAppGcsLocked();
13925 }
13926
13927 /**
13928 * Schedule the execution of all pending app GCs.
13929 */
13930 final void scheduleAppGcsLocked() {
13931 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013932
13933 if (mProcessesToGc.size() > 0) {
13934 // Schedule a GC for the time to the next process.
13935 ProcessRecord proc = mProcessesToGc.get(0);
13936 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13937
13938 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13939 long now = SystemClock.uptimeMillis();
13940 if (when < (now+GC_TIMEOUT)) {
13941 when = now + GC_TIMEOUT;
13942 }
13943 mHandler.sendMessageAtTime(msg, when);
13944 }
13945 }
13946
13947 /**
13948 * Add a process to the array of processes waiting to be GCed. Keeps the
13949 * list in sorted order by the last GC time. The process can't already be
13950 * on the list.
13951 */
13952 final void addProcessToGcListLocked(ProcessRecord proc) {
13953 boolean added = false;
13954 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13955 if (mProcessesToGc.get(i).lastRequestedGc <
13956 proc.lastRequestedGc) {
13957 added = true;
13958 mProcessesToGc.add(i+1, proc);
13959 break;
13960 }
13961 }
13962 if (!added) {
13963 mProcessesToGc.add(0, proc);
13964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013965 }
13966
13967 /**
13968 * Set up to ask a process to GC itself. This will either do it
13969 * immediately, or put it on the list of processes to gc the next
13970 * time things are idle.
13971 */
13972 final void scheduleAppGcLocked(ProcessRecord app) {
13973 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013974 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013975 return;
13976 }
13977 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013978 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013979 scheduleAppGcsLocked();
13980 }
13981 }
13982
13983 private final boolean updateOomAdjLocked(
13984 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13985 app.hiddenAdj = hiddenAdj;
13986
13987 if (app.thread == null) {
13988 return true;
13989 }
13990
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013991 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013992
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013993 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013994 if (app.curRawAdj != app.setRawAdj) {
13995 if (app.curRawAdj > FOREGROUND_APP_ADJ
13996 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13997 // If this app is transitioning from foreground to
13998 // non-foreground, have it do a gc.
13999 scheduleAppGcLocked(app);
14000 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14001 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14002 // Likewise do a gc when an app is moving in to the
14003 // background (such as a service stopping).
14004 scheduleAppGcLocked(app);
14005 }
14006 app.setRawAdj = app.curRawAdj;
14007 }
14008 if (adj != app.setAdj) {
14009 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014010 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014011 TAG, "Set app " + app.processName +
14012 " oom adj to " + adj);
14013 app.setAdj = adj;
14014 } else {
14015 return false;
14016 }
14017 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014018 if (app.setSchedGroup != app.curSchedGroup) {
14019 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014020 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014021 "Setting process group of " + app.processName
14022 + " to " + app.curSchedGroup);
14023 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014024 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014025 try {
14026 Process.setProcessGroup(app.pid, app.curSchedGroup);
14027 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014028 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014029 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014030 e.printStackTrace();
14031 } finally {
14032 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014033 }
14034 }
14035 if (false) {
14036 if (app.thread != null) {
14037 try {
14038 app.thread.setSchedulingGroup(app.curSchedGroup);
14039 } catch (RemoteException e) {
14040 }
14041 }
14042 }
14043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014044 }
14045
14046 return true;
14047 }
14048
14049 private final HistoryRecord resumedAppLocked() {
14050 HistoryRecord resumedActivity = mResumedActivity;
14051 if (resumedActivity == null || resumedActivity.app == null) {
14052 resumedActivity = mPausingActivity;
14053 if (resumedActivity == null || resumedActivity.app == null) {
14054 resumedActivity = topRunningActivityLocked(null);
14055 }
14056 }
14057 return resumedActivity;
14058 }
14059
14060 private final boolean updateOomAdjLocked(ProcessRecord app) {
14061 final HistoryRecord TOP_ACT = resumedAppLocked();
14062 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14063 int curAdj = app.curAdj;
14064 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14065 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14066
14067 mAdjSeq++;
14068
14069 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14070 if (res) {
14071 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14072 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14073 if (nowHidden != wasHidden) {
14074 // Changed to/from hidden state, so apps after it in the LRU
14075 // list may also be changed.
14076 updateOomAdjLocked();
14077 }
14078 }
14079 return res;
14080 }
14081
14082 private final boolean updateOomAdjLocked() {
14083 boolean didOomAdj = true;
14084 final HistoryRecord TOP_ACT = resumedAppLocked();
14085 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14086
14087 if (false) {
14088 RuntimeException e = new RuntimeException();
14089 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014090 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014091 }
14092
14093 mAdjSeq++;
14094
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014095 // Let's determine how many processes we have running vs.
14096 // how many slots we have for background processes; we may want
14097 // to put multiple processes in a slot of there are enough of
14098 // them.
14099 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14100 int factor = (mLruProcesses.size()-4)/numSlots;
14101 if (factor < 1) factor = 1;
14102 int step = 0;
14103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014104 // First try updating the OOM adjustment for each of the
14105 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014106 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014107 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14108 while (i > 0) {
14109 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014110 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014111 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014112 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014113 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014114 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014115 step++;
14116 if (step >= factor) {
14117 step = 0;
14118 curHiddenAdj++;
14119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014120 }
14121 } else {
14122 didOomAdj = false;
14123 }
14124 }
14125
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014126 // If we return false, we will fall back on killing processes to
14127 // have a fixed limit. Do this if a limit has been requested; else
14128 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014129 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14130 }
14131
14132 private final void trimApplications() {
14133 synchronized (this) {
14134 int i;
14135
14136 // First remove any unused application processes whose package
14137 // has been removed.
14138 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14139 final ProcessRecord app = mRemovedProcesses.get(i);
14140 if (app.activities.size() == 0
14141 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014142 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014143 TAG, "Exiting empty application process "
14144 + app.processName + " ("
14145 + (app.thread != null ? app.thread.asBinder() : null)
14146 + ")\n");
14147 if (app.pid > 0 && app.pid != MY_PID) {
14148 Process.killProcess(app.pid);
14149 } else {
14150 try {
14151 app.thread.scheduleExit();
14152 } catch (Exception e) {
14153 // Ignore exceptions.
14154 }
14155 }
14156 cleanUpApplicationRecordLocked(app, false, -1);
14157 mRemovedProcesses.remove(i);
14158
14159 if (app.persistent) {
14160 if (app.persistent) {
14161 addAppLocked(app.info);
14162 }
14163 }
14164 }
14165 }
14166
14167 // Now try updating the OOM adjustment for each of the
14168 // application processes based on their current state.
14169 // If the setOomAdj() API is not supported, then go with our
14170 // back-up plan...
14171 if (!updateOomAdjLocked()) {
14172
14173 // Count how many processes are running services.
14174 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014175 for (i=mLruProcesses.size()-1; i>=0; i--) {
14176 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014177
14178 if (app.persistent || app.services.size() != 0
14179 || app.curReceiver != null
14180 || app.persistentActivities > 0) {
14181 // Don't count processes holding services against our
14182 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014183 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014184 TAG, "Not trimming app " + app + " with services: "
14185 + app.services);
14186 numServiceProcs++;
14187 }
14188 }
14189
14190 int curMaxProcs = mProcessLimit;
14191 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14192 if (mAlwaysFinishActivities) {
14193 curMaxProcs = 1;
14194 }
14195 curMaxProcs += numServiceProcs;
14196
14197 // Quit as many processes as we can to get down to the desired
14198 // process count. First remove any processes that no longer
14199 // have activites running in them.
14200 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014201 i<mLruProcesses.size()
14202 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014203 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014204 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014205 // Quit an application only if it is not currently
14206 // running any activities.
14207 if (!app.persistent && app.activities.size() == 0
14208 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014209 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014210 TAG, "Exiting empty application process "
14211 + app.processName + " ("
14212 + (app.thread != null ? app.thread.asBinder() : null)
14213 + ")\n");
14214 if (app.pid > 0 && app.pid != MY_PID) {
14215 Process.killProcess(app.pid);
14216 } else {
14217 try {
14218 app.thread.scheduleExit();
14219 } catch (Exception e) {
14220 // Ignore exceptions.
14221 }
14222 }
14223 // todo: For now we assume the application is not buggy
14224 // or evil, and will quit as a result of our request.
14225 // Eventually we need to drive this off of the death
14226 // notification, and kill the process if it takes too long.
14227 cleanUpApplicationRecordLocked(app, false, i);
14228 i--;
14229 }
14230 }
14231
14232 // If we still have too many processes, now from the least
14233 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014234 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014235 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014236 " of " + curMaxProcs + " processes");
14237 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014238 i<mLruProcesses.size()
14239 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014240 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014241 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014242 // Quit the application only if we have a state saved for
14243 // all of its activities.
14244 boolean canQuit = !app.persistent && app.curReceiver == null
14245 && app.services.size() == 0
14246 && app.persistentActivities == 0;
14247 int NUMA = app.activities.size();
14248 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014249 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014250 TAG, "Looking to quit " + app.processName);
14251 for (j=0; j<NUMA && canQuit; j++) {
14252 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014253 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014254 TAG, " " + r.intent.getComponent().flattenToShortString()
14255 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14256 canQuit = (r.haveState || !r.stateNotNeeded)
14257 && !r.visible && r.stopped;
14258 }
14259 if (canQuit) {
14260 // Finish all of the activities, and then the app itself.
14261 for (j=0; j<NUMA; j++) {
14262 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14263 if (!r.finishing) {
14264 destroyActivityLocked(r, false);
14265 }
14266 r.resultTo = null;
14267 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014268 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014269 + app.processName + " ("
14270 + (app.thread != null ? app.thread.asBinder() : null)
14271 + ")\n");
14272 if (app.pid > 0 && app.pid != MY_PID) {
14273 Process.killProcess(app.pid);
14274 } else {
14275 try {
14276 app.thread.scheduleExit();
14277 } catch (Exception e) {
14278 // Ignore exceptions.
14279 }
14280 }
14281 // todo: For now we assume the application is not buggy
14282 // or evil, and will quit as a result of our request.
14283 // Eventually we need to drive this off of the death
14284 // notification, and kill the process if it takes too long.
14285 cleanUpApplicationRecordLocked(app, false, i);
14286 i--;
14287 //dump();
14288 }
14289 }
14290
14291 }
14292
14293 int curMaxActivities = MAX_ACTIVITIES;
14294 if (mAlwaysFinishActivities) {
14295 curMaxActivities = 1;
14296 }
14297
14298 // Finally, if there are too many activities now running, try to
14299 // finish as many as we can to get back down to the limit.
14300 for ( i=0;
14301 i<mLRUActivities.size()
14302 && mLRUActivities.size() > curMaxActivities;
14303 i++) {
14304 final HistoryRecord r
14305 = (HistoryRecord)mLRUActivities.get(i);
14306
14307 // We can finish this one if we have its icicle saved and
14308 // it is not persistent.
14309 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14310 && r.stopped && !r.persistent && !r.finishing) {
14311 final int origSize = mLRUActivities.size();
14312 destroyActivityLocked(r, true);
14313
14314 // This will remove it from the LRU list, so keep
14315 // our index at the same value. Note that this check to
14316 // see if the size changes is just paranoia -- if
14317 // something unexpected happens, we don't want to end up
14318 // in an infinite loop.
14319 if (origSize > mLRUActivities.size()) {
14320 i--;
14321 }
14322 }
14323 }
14324 }
14325 }
14326
14327 /** This method sends the specified signal to each of the persistent apps */
14328 public void signalPersistentProcesses(int sig) throws RemoteException {
14329 if (sig != Process.SIGNAL_USR1) {
14330 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14331 }
14332
14333 synchronized (this) {
14334 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14335 != PackageManager.PERMISSION_GRANTED) {
14336 throw new SecurityException("Requires permission "
14337 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14338 }
14339
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014340 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14341 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014342 if (r.thread != null && r.persistent) {
14343 Process.sendSignal(r.pid, sig);
14344 }
14345 }
14346 }
14347 }
14348
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014349 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014350 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014351
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014352 try {
14353 synchronized (this) {
14354 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14355 // its own permission.
14356 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14357 != PackageManager.PERMISSION_GRANTED) {
14358 throw new SecurityException("Requires permission "
14359 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014360 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014361
14362 if (start && fd == null) {
14363 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014364 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014365
14366 ProcessRecord proc = null;
14367 try {
14368 int pid = Integer.parseInt(process);
14369 synchronized (mPidsSelfLocked) {
14370 proc = mPidsSelfLocked.get(pid);
14371 }
14372 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014373 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014374
14375 if (proc == null) {
14376 HashMap<String, SparseArray<ProcessRecord>> all
14377 = mProcessNames.getMap();
14378 SparseArray<ProcessRecord> procs = all.get(process);
14379 if (procs != null && procs.size() > 0) {
14380 proc = procs.valueAt(0);
14381 }
14382 }
14383
14384 if (proc == null || proc.thread == null) {
14385 throw new IllegalArgumentException("Unknown process: " + process);
14386 }
14387
14388 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14389 if (isSecure) {
14390 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14391 throw new SecurityException("Process not debuggable: " + proc);
14392 }
14393 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014394
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014395 proc.thread.profilerControl(start, path, fd);
14396 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014397 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014398 }
14399 } catch (RemoteException e) {
14400 throw new IllegalStateException("Process disappeared");
14401 } finally {
14402 if (fd != null) {
14403 try {
14404 fd.close();
14405 } catch (IOException e) {
14406 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014407 }
14408 }
14409 }
14410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014411 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14412 public void monitor() {
14413 synchronized (this) { }
14414 }
14415}