blob: a501cebe2975b625d760c91d1f114aa4c86b6e36 [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;
3519 addRecentTask(r.task);
3520
3521 } else if (sourceRecord != null) {
3522 if (!addingToTask &&
3523 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3524 // In this case, we are adding the activity to an existing
3525 // task, but the caller has asked to clear that task if the
3526 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003527 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003528 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003530 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531 deliverNewIntentLocked(top, r.intent);
3532 // For paranoia, make sure we have correctly
3533 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003534 if (doResume) {
3535 resumeTopActivityLocked(null);
3536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 return START_DELIVERED_TO_TOP;
3538 }
3539 } else if (!addingToTask &&
3540 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3541 // In this case, we are launching an activity in our own task
3542 // that may already be running somewhere in the history, and
3543 // we want to shuffle it to the front of the stack if so.
3544 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3545 if (where >= 0) {
3546 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003547 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003549 if (doResume) {
3550 resumeTopActivityLocked(null);
3551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 return START_DELIVERED_TO_TOP;
3553 }
3554 }
3555 // An existing activity is starting this new activity, so we want
3556 // to keep the new one in the same task as the one that is starting
3557 // it.
3558 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003559 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003560 + " in existing task " + r.task);
3561
3562 } else {
3563 // This not being started from an existing activity, and not part
3564 // of a new task... just put it in the top task, though these days
3565 // this case should never happen.
3566 final int N = mHistory.size();
3567 HistoryRecord prev =
3568 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3569 r.task = prev != null
3570 ? prev.task
3571 : new TaskRecord(mCurTask, r.info, intent,
3572 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003573 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003574 + " in new guessed " + r.task);
3575 }
3576 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003577 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003579 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003580 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581 return START_SUCCESS;
3582 }
3583
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003584 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3585 long thisTime, long totalTime) {
3586 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3587 WaitResult w = mWaitingActivityLaunched.get(i);
3588 w.timeout = timeout;
3589 if (r != null) {
3590 w.who = new ComponentName(r.info.packageName, r.info.name);
3591 }
3592 w.thisTime = thisTime;
3593 w.totalTime = totalTime;
3594 }
3595 notify();
3596 }
3597
3598 void reportActivityVisibleLocked(HistoryRecord r) {
3599 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3600 WaitResult w = mWaitingActivityVisible.get(i);
3601 w.timeout = false;
3602 if (r != null) {
3603 w.who = new ComponentName(r.info.packageName, r.info.name);
3604 }
3605 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3606 w.thisTime = w.totalTime;
3607 }
3608 notify();
3609 }
3610
3611 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003612 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3613 int grantedMode, IBinder resultTo,
3614 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003615 boolean debug, WaitResult outResult) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 // Refuse possible leaked file descriptors
3617 if (intent != null && intent.hasFileDescriptors()) {
3618 throw new IllegalArgumentException("File descriptors passed in Intent");
3619 }
3620
The Android Open Source Project4df24232009-03-05 14:34:35 -08003621 final boolean componentSpecified = intent.getComponent() != null;
3622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003623 // Don't modify the client's object!
3624 intent = new Intent(intent);
3625
3626 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 ActivityInfo aInfo;
3628 try {
3629 ResolveInfo rInfo =
3630 ActivityThread.getPackageManager().resolveIntent(
3631 intent, resolvedType,
3632 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003633 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 aInfo = rInfo != null ? rInfo.activityInfo : null;
3635 } catch (RemoteException e) {
3636 aInfo = null;
3637 }
3638
3639 if (aInfo != null) {
3640 // Store the found target back into the intent, because now that
3641 // we have it we never want to do this again. For example, if the
3642 // user navigates back to this point in the history, we should
3643 // always restart the exact same activity.
3644 intent.setComponent(new ComponentName(
3645 aInfo.applicationInfo.packageName, aInfo.name));
3646
3647 // Don't debug things in the system process
3648 if (debug) {
3649 if (!aInfo.processName.equals("system")) {
3650 setDebugApp(aInfo.processName, true, false);
3651 }
3652 }
3653 }
3654
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003655 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003656 int callingPid;
3657 int callingUid;
3658 if (caller == null) {
3659 callingPid = Binder.getCallingPid();
3660 callingUid = Binder.getCallingUid();
3661 } else {
3662 callingPid = callingUid = -1;
3663 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 final long origId = Binder.clearCallingIdentity();
3665 int res = startActivityLocked(caller, intent, resolvedType,
3666 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003667 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003668 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003670
3671 if (outResult != null) {
3672 outResult.result = res;
3673 if (res == IActivityManager.START_SUCCESS) {
3674 mWaitingActivityLaunched.add(outResult);
3675 do {
3676 try {
3677 wait();
3678 } catch (InterruptedException e) {
3679 }
3680 } while (!outResult.timeout && outResult.who == null);
3681 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3682 HistoryRecord r = this.topRunningActivityLocked(null);
3683 if (r.nowVisible) {
3684 outResult.timeout = false;
3685 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3686 outResult.totalTime = 0;
3687 outResult.thisTime = 0;
3688 } else {
3689 outResult.thisTime = SystemClock.uptimeMillis();
3690 mWaitingActivityVisible.add(outResult);
3691 do {
3692 try {
3693 wait();
3694 } catch (InterruptedException e) {
3695 }
3696 } while (!outResult.timeout && outResult.who == null);
3697 }
3698 }
3699 }
3700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 return res;
3702 }
3703 }
3704
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003705 public final int startActivity(IApplicationThread caller,
3706 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3707 int grantedMode, IBinder resultTo,
3708 String resultWho, int requestCode, boolean onlyIfNeeded,
3709 boolean debug) {
3710 return startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3711 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, null);
3712 }
3713
3714 public final WaitResult startActivityAndWait(IApplicationThread caller,
3715 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3716 int grantedMode, IBinder resultTo,
3717 String resultWho, int requestCode, boolean onlyIfNeeded,
3718 boolean debug) {
3719 WaitResult res = new WaitResult();
3720 startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3721 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, res);
3722 return res;
3723 }
3724
3725 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003726 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003727 IBinder resultTo, String resultWho, int requestCode,
3728 int flagsMask, int flagsValues) {
3729 // Refuse possible leaked file descriptors
3730 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3731 throw new IllegalArgumentException("File descriptors passed in Intent");
3732 }
3733
3734 IIntentSender sender = intent.getTarget();
3735 if (!(sender instanceof PendingIntentRecord)) {
3736 throw new IllegalArgumentException("Bad PendingIntent object");
3737 }
3738
3739 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003740
3741 synchronized (this) {
3742 // If this is coming from the currently resumed activity, it is
3743 // effectively saying that app switches are allowed at this point.
3744 if (mResumedActivity != null
3745 && mResumedActivity.info.applicationInfo.uid ==
3746 Binder.getCallingUid()) {
3747 mAppSwitchesAllowedTime = 0;
3748 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003749 }
3750
3751 return pir.sendInner(0, fillInIntent, resolvedType,
3752 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3753 }
3754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 public boolean startNextMatchingActivity(IBinder callingActivity,
3756 Intent intent) {
3757 // Refuse possible leaked file descriptors
3758 if (intent != null && intent.hasFileDescriptors() == true) {
3759 throw new IllegalArgumentException("File descriptors passed in Intent");
3760 }
3761
3762 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003763 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 if (index < 0) {
3765 return false;
3766 }
3767 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3768 if (r.app == null || r.app.thread == null) {
3769 // The caller is not running... d'oh!
3770 return false;
3771 }
3772 intent = new Intent(intent);
3773 // The caller is not allowed to change the data.
3774 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3775 // And we are resetting to find the next component...
3776 intent.setComponent(null);
3777
3778 ActivityInfo aInfo = null;
3779 try {
3780 List<ResolveInfo> resolves =
3781 ActivityThread.getPackageManager().queryIntentActivities(
3782 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003783 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784
3785 // Look for the original activity in the list...
3786 final int N = resolves != null ? resolves.size() : 0;
3787 for (int i=0; i<N; i++) {
3788 ResolveInfo rInfo = resolves.get(i);
3789 if (rInfo.activityInfo.packageName.equals(r.packageName)
3790 && rInfo.activityInfo.name.equals(r.info.name)) {
3791 // We found the current one... the next matching is
3792 // after it.
3793 i++;
3794 if (i<N) {
3795 aInfo = resolves.get(i).activityInfo;
3796 }
3797 break;
3798 }
3799 }
3800 } catch (RemoteException e) {
3801 }
3802
3803 if (aInfo == null) {
3804 // Nobody who is next!
3805 return false;
3806 }
3807
3808 intent.setComponent(new ComponentName(
3809 aInfo.applicationInfo.packageName, aInfo.name));
3810 intent.setFlags(intent.getFlags()&~(
3811 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3812 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3813 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3814 Intent.FLAG_ACTIVITY_NEW_TASK));
3815
3816 // Okay now we need to start the new activity, replacing the
3817 // currently running activity. This is a little tricky because
3818 // we want to start the new one as if the current one is finished,
3819 // but not finish the current one first so that there is no flicker.
3820 // And thus...
3821 final boolean wasFinishing = r.finishing;
3822 r.finishing = true;
3823
3824 // Propagate reply information over to the new activity.
3825 final HistoryRecord resultTo = r.resultTo;
3826 final String resultWho = r.resultWho;
3827 final int requestCode = r.requestCode;
3828 r.resultTo = null;
3829 if (resultTo != null) {
3830 resultTo.removeResultsLocked(r, resultWho, requestCode);
3831 }
3832
3833 final long origId = Binder.clearCallingIdentity();
3834 // XXX we are not dealing with propagating grantedUriPermissions...
3835 // those are not yet exposed to user code, so there is no need.
3836 int res = startActivityLocked(r.app.thread, intent,
3837 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003838 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 Binder.restoreCallingIdentity(origId);
3840
3841 r.finishing = wasFinishing;
3842 if (res != START_SUCCESS) {
3843 return false;
3844 }
3845 return true;
3846 }
3847 }
3848
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003849 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003850 Intent intent, String resolvedType, IBinder resultTo,
3851 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003852
3853 // This is so super not safe, that only the system (or okay root)
3854 // can do it.
3855 final int callingUid = Binder.getCallingUid();
3856 if (callingUid != 0 && callingUid != Process.myUid()) {
3857 throw new SecurityException(
3858 "startActivityInPackage only available to the system");
3859 }
3860
The Android Open Source Project4df24232009-03-05 14:34:35 -08003861 final boolean componentSpecified = intent.getComponent() != null;
3862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 // Don't modify the client's object!
3864 intent = new Intent(intent);
3865
3866 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867 ActivityInfo aInfo;
3868 try {
3869 ResolveInfo rInfo =
3870 ActivityThread.getPackageManager().resolveIntent(
3871 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003872 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873 aInfo = rInfo != null ? rInfo.activityInfo : null;
3874 } catch (RemoteException e) {
3875 aInfo = null;
3876 }
3877
3878 if (aInfo != null) {
3879 // Store the found target back into the intent, because now that
3880 // we have it we never want to do this again. For example, if the
3881 // user navigates back to this point in the history, we should
3882 // always restart the exact same activity.
3883 intent.setComponent(new ComponentName(
3884 aInfo.applicationInfo.packageName, aInfo.name));
3885 }
3886
3887 synchronized(this) {
3888 return startActivityLocked(null, intent, resolvedType,
3889 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003890 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003891 }
3892 }
3893
3894 private final void addRecentTask(TaskRecord task) {
3895 // Remove any existing entries that are the same kind of task.
3896 int N = mRecentTasks.size();
3897 for (int i=0; i<N; i++) {
3898 TaskRecord tr = mRecentTasks.get(i);
3899 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3900 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3901 mRecentTasks.remove(i);
3902 i--;
3903 N--;
3904 if (task.intent == null) {
3905 // If the new recent task we are adding is not fully
3906 // specified, then replace it with the existing recent task.
3907 task = tr;
3908 }
3909 }
3910 }
3911 if (N >= MAX_RECENT_TASKS) {
3912 mRecentTasks.remove(N-1);
3913 }
3914 mRecentTasks.add(0, task);
3915 }
3916
3917 public void setRequestedOrientation(IBinder token,
3918 int requestedOrientation) {
3919 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003920 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003921 if (index < 0) {
3922 return;
3923 }
3924 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3925 final long origId = Binder.clearCallingIdentity();
3926 mWindowManager.setAppOrientation(r, requestedOrientation);
3927 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003928 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 r.mayFreezeScreenLocked(r.app) ? r : null);
3930 if (config != null) {
3931 r.frozenBeforeDestroy = true;
3932 if (!updateConfigurationLocked(config, r)) {
3933 resumeTopActivityLocked(null);
3934 }
3935 }
3936 Binder.restoreCallingIdentity(origId);
3937 }
3938 }
3939
3940 public int getRequestedOrientation(IBinder token) {
3941 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003942 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 if (index < 0) {
3944 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3945 }
3946 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3947 return mWindowManager.getAppOrientation(r);
3948 }
3949 }
3950
3951 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003952 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3954 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3955 if (!r.finishing) {
3956 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3957 "no-history");
3958 }
3959 } else if (r.app != null && r.app.thread != null) {
3960 if (mFocusedActivity == r) {
3961 setFocusedActivityLocked(topRunningActivityLocked(null));
3962 }
3963 r.resumeKeyDispatchingLocked();
3964 try {
3965 r.stopped = false;
3966 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003967 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 TAG, "Stopping visible=" + r.visible + " for " + r);
3969 if (!r.visible) {
3970 mWindowManager.setAppVisibility(r, false);
3971 }
3972 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3973 } catch (Exception e) {
3974 // Maybe just ignore exceptions here... if the process
3975 // has crashed, our death notification will clean things
3976 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003977 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003978 // Just in case, assume it to be stopped.
3979 r.stopped = true;
3980 r.state = ActivityState.STOPPED;
3981 if (r.configDestroy) {
3982 destroyActivityLocked(r, true);
3983 }
3984 }
3985 }
3986 }
3987
3988 /**
3989 * @return Returns true if the activity is being finished, false if for
3990 * some reason it is being left as-is.
3991 */
3992 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3993 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003994 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 TAG, "Finishing activity: token=" + token
3996 + ", result=" + resultCode + ", data=" + resultData);
3997
Dianne Hackborn75b03852009-06-12 15:43:26 -07003998 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 if (index < 0) {
4000 return false;
4001 }
4002 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4003
4004 // Is this the last activity left?
4005 boolean lastActivity = true;
4006 for (int i=mHistory.size()-1; i>=0; i--) {
4007 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4008 if (!p.finishing && p != r) {
4009 lastActivity = false;
4010 break;
4011 }
4012 }
4013
4014 // If this is the last activity, but it is the home activity, then
4015 // just don't finish it.
4016 if (lastActivity) {
4017 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4018 return false;
4019 }
4020 }
4021
4022 finishActivityLocked(r, index, resultCode, resultData, reason);
4023 return true;
4024 }
4025
4026 /**
4027 * @return Returns true if this activity has been removed from the history
4028 * list, or false if it is still in the list and will be removed later.
4029 */
4030 private final boolean finishActivityLocked(HistoryRecord r, int index,
4031 int resultCode, Intent resultData, String reason) {
4032 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004033 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 return false;
4035 }
4036
4037 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004038 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004039 System.identityHashCode(r),
4040 r.task.taskId, r.shortComponentName, reason);
4041 r.task.numActivities--;
4042 if (r.frontOfTask && index < (mHistory.size()-1)) {
4043 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4044 if (next.task == r.task) {
4045 next.frontOfTask = true;
4046 }
4047 }
4048
4049 r.pauseKeyDispatchingLocked();
4050 if (mFocusedActivity == r) {
4051 setFocusedActivityLocked(topRunningActivityLocked(null));
4052 }
4053
4054 // send the result
4055 HistoryRecord resultTo = r.resultTo;
4056 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004057 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004058 + " who=" + r.resultWho + " req=" + r.requestCode
4059 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060 if (r.info.applicationInfo.uid > 0) {
4061 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4062 r.packageName, resultData, r);
4063 }
4064 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4065 resultData);
4066 r.resultTo = null;
4067 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004068 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004069
4070 // Make sure this HistoryRecord is not holding on to other resources,
4071 // because clients have remote IPC references to this object so we
4072 // can't assume that will go away and want to avoid circular IPC refs.
4073 r.results = null;
4074 r.pendingResults = null;
4075 r.newIntents = null;
4076 r.icicle = null;
4077
4078 if (mPendingThumbnails.size() > 0) {
4079 // There are clients waiting to receive thumbnails so, in case
4080 // this is an activity that someone is waiting for, add it
4081 // to the pending list so we can correctly update the clients.
4082 mCancelledThumbnails.add(r);
4083 }
4084
4085 if (mResumedActivity == r) {
4086 boolean endTask = index <= 0
4087 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004088 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004089 "Prepare close transition: finishing " + r);
4090 mWindowManager.prepareAppTransition(endTask
4091 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4092 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4093
4094 // Tell window manager to prepare for this one to be removed.
4095 mWindowManager.setAppVisibility(r, false);
4096
4097 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004098 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4099 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100 startPausingLocked(false, false);
4101 }
4102
4103 } else if (r.state != ActivityState.PAUSING) {
4104 // If the activity is PAUSING, we will complete the finish once
4105 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004106 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 return finishCurrentActivityLocked(r, index,
4108 FINISH_AFTER_PAUSE) == null;
4109 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004110 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004111 }
4112
4113 return false;
4114 }
4115
4116 private static final int FINISH_IMMEDIATELY = 0;
4117 private static final int FINISH_AFTER_PAUSE = 1;
4118 private static final int FINISH_AFTER_VISIBLE = 2;
4119
4120 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4121 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004122 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 if (index < 0) {
4124 return null;
4125 }
4126
4127 return finishCurrentActivityLocked(r, index, mode);
4128 }
4129
4130 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4131 int index, int mode) {
4132 // First things first: if this activity is currently visible,
4133 // and the resumed activity is not yet visible, then hold off on
4134 // finishing until the resumed one becomes visible.
4135 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4136 if (!mStoppingActivities.contains(r)) {
4137 mStoppingActivities.add(r);
4138 if (mStoppingActivities.size() > 3) {
4139 // If we already have a few activities waiting to stop,
4140 // then give up on things going idle and start clearing
4141 // them out.
4142 Message msg = Message.obtain();
4143 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4144 mHandler.sendMessage(msg);
4145 }
4146 }
4147 r.state = ActivityState.STOPPING;
4148 updateOomAdjLocked();
4149 return r;
4150 }
4151
4152 // make sure the record is cleaned out of other places.
4153 mStoppingActivities.remove(r);
4154 mWaitingVisibleActivities.remove(r);
4155 if (mResumedActivity == r) {
4156 mResumedActivity = null;
4157 }
4158 final ActivityState prevState = r.state;
4159 r.state = ActivityState.FINISHING;
4160
4161 if (mode == FINISH_IMMEDIATELY
4162 || prevState == ActivityState.STOPPED
4163 || prevState == ActivityState.INITIALIZING) {
4164 // If this activity is already stopped, we can just finish
4165 // it right now.
4166 return destroyActivityLocked(r, true) ? null : r;
4167 } else {
4168 // Need to go through the full pause cycle to get this
4169 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004170 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171 mFinishingActivities.add(r);
4172 resumeTopActivityLocked(null);
4173 }
4174 return r;
4175 }
4176
4177 /**
4178 * This is the internal entry point for handling Activity.finish().
4179 *
4180 * @param token The Binder token referencing the Activity we want to finish.
4181 * @param resultCode Result code, if any, from this Activity.
4182 * @param resultData Result data (Intent), if any, from this Activity.
4183 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004184 * @return Returns true if the activity successfully finished, or false if it is still running.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 */
4186 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4187 // Refuse possible leaked file descriptors
4188 if (resultData != null && resultData.hasFileDescriptors() == true) {
4189 throw new IllegalArgumentException("File descriptors passed in Intent");
4190 }
4191
4192 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004193 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 // Find the first activity that is not finishing.
4195 HistoryRecord next = topRunningActivityLocked(token, 0);
4196 if (next != null) {
4197 // ask watcher if this is allowed
4198 boolean resumeOK = true;
4199 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004200 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004201 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004202 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004203 }
4204
4205 if (!resumeOK) {
4206 return false;
4207 }
4208 }
4209 }
4210 final long origId = Binder.clearCallingIdentity();
4211 boolean res = requestFinishActivityLocked(token, resultCode,
4212 resultData, "app-request");
4213 Binder.restoreCallingIdentity(origId);
4214 return res;
4215 }
4216 }
4217
4218 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4219 String resultWho, int requestCode, int resultCode, Intent data) {
4220
4221 if (callingUid > 0) {
4222 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4223 data, r);
4224 }
4225
Joe Onorato8a9b2202010-02-26 18:56:32 -08004226 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004227 + " : who=" + resultWho + " req=" + requestCode
4228 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4230 try {
4231 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4232 list.add(new ResultInfo(resultWho, requestCode,
4233 resultCode, data));
4234 r.app.thread.scheduleSendResult(r, list);
4235 return;
4236 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004237 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 }
4239 }
4240
4241 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4242 }
4243
4244 public final void finishSubActivity(IBinder token, String resultWho,
4245 int requestCode) {
4246 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004247 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004248 if (index < 0) {
4249 return;
4250 }
4251 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4252
4253 final long origId = Binder.clearCallingIdentity();
4254
4255 int i;
4256 for (i=mHistory.size()-1; i>=0; i--) {
4257 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4258 if (r.resultTo == self && r.requestCode == requestCode) {
4259 if ((r.resultWho == null && resultWho == null) ||
4260 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4261 finishActivityLocked(r, i,
4262 Activity.RESULT_CANCELED, null, "request-sub");
4263 }
4264 }
4265 }
4266
4267 Binder.restoreCallingIdentity(origId);
4268 }
4269 }
4270
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004271 public void overridePendingTransition(IBinder token, String packageName,
4272 int enterAnim, int exitAnim) {
4273 synchronized(this) {
4274 int index = indexOfTokenLocked(token);
4275 if (index < 0) {
4276 return;
4277 }
4278 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4279
4280 final long origId = Binder.clearCallingIdentity();
4281
4282 if (self.state == ActivityState.RESUMED
4283 || self.state == ActivityState.PAUSING) {
4284 mWindowManager.overridePendingAppTransition(packageName,
4285 enterAnim, exitAnim);
4286 }
4287
4288 Binder.restoreCallingIdentity(origId);
4289 }
4290 }
4291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 /**
4293 * Perform clean-up of service connections in an activity record.
4294 */
4295 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4296 // Throw away any services that have been bound by this activity.
4297 if (r.connections != null) {
4298 Iterator<ConnectionRecord> it = r.connections.iterator();
4299 while (it.hasNext()) {
4300 ConnectionRecord c = it.next();
4301 removeConnectionLocked(c, null, r);
4302 }
4303 r.connections = null;
4304 }
4305 }
4306
4307 /**
4308 * Perform the common clean-up of an activity record. This is called both
4309 * as part of destroyActivityLocked() (when destroying the client-side
4310 * representation) and cleaning things up as a result of its hosting
4311 * processing going away, in which case there is no remaining client-side
4312 * state to destroy so only the cleanup here is needed.
4313 */
4314 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4315 if (mResumedActivity == r) {
4316 mResumedActivity = null;
4317 }
4318 if (mFocusedActivity == r) {
4319 mFocusedActivity = null;
4320 }
4321
4322 r.configDestroy = false;
4323 r.frozenBeforeDestroy = false;
4324
4325 // Make sure this record is no longer in the pending finishes list.
4326 // This could happen, for example, if we are trimming activities
4327 // down to the max limit while they are still waiting to finish.
4328 mFinishingActivities.remove(r);
4329 mWaitingVisibleActivities.remove(r);
4330
4331 // Remove any pending results.
4332 if (r.finishing && r.pendingResults != null) {
4333 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4334 PendingIntentRecord rec = apr.get();
4335 if (rec != null) {
4336 cancelIntentSenderLocked(rec, false);
4337 }
4338 }
4339 r.pendingResults = null;
4340 }
4341
4342 if (cleanServices) {
4343 cleanUpActivityServicesLocked(r);
4344 }
4345
4346 if (mPendingThumbnails.size() > 0) {
4347 // There are clients waiting to receive thumbnails so, in case
4348 // this is an activity that someone is waiting for, add it
4349 // to the pending list so we can correctly update the clients.
4350 mCancelledThumbnails.add(r);
4351 }
4352
4353 // Get rid of any pending idle timeouts.
4354 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4355 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4356 }
4357
4358 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4359 if (r.state != ActivityState.DESTROYED) {
4360 mHistory.remove(r);
4361 r.inHistory = false;
4362 r.state = ActivityState.DESTROYED;
4363 mWindowManager.removeAppToken(r);
4364 if (VALIDATE_TOKENS) {
4365 mWindowManager.validateAppTokens(mHistory);
4366 }
4367 cleanUpActivityServicesLocked(r);
4368 removeActivityUriPermissionsLocked(r);
4369 }
4370 }
4371
4372 /**
4373 * Destroy the current CLIENT SIDE instance of an activity. This may be
4374 * called both when actually finishing an activity, or when performing
4375 * a configuration switch where we destroy the current client-side object
4376 * but then create a new client-side object for this same HistoryRecord.
4377 */
4378 private final boolean destroyActivityLocked(HistoryRecord r,
4379 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004380 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004381 TAG, "Removing activity: token=" + r
4382 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004383 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 System.identityHashCode(r),
4385 r.task.taskId, r.shortComponentName);
4386
4387 boolean removedFromHistory = false;
4388
4389 cleanUpActivityLocked(r, false);
4390
Dianne Hackborn03abb812010-01-04 18:43:19 -08004391 final boolean hadApp = r.app != null;
4392
4393 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 if (removeFromApp) {
4395 int idx = r.app.activities.indexOf(r);
4396 if (idx >= 0) {
4397 r.app.activities.remove(idx);
4398 }
4399 if (r.persistent) {
4400 decPersistentCountLocked(r.app);
4401 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004402 if (r.app.activities.size() == 0) {
4403 // No longer have activities, so update location in
4404 // LRU list.
4405 updateLruProcessLocked(r.app, true, false);
4406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004407 }
4408
4409 boolean skipDestroy = false;
4410
4411 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004412 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4414 r.configChangeFlags);
4415 } catch (Exception e) {
4416 // We can just ignore exceptions here... if the process
4417 // has crashed, our death notification will clean things
4418 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004419 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004420 if (r.finishing) {
4421 removeActivityFromHistoryLocked(r);
4422 removedFromHistory = true;
4423 skipDestroy = true;
4424 }
4425 }
4426
4427 r.app = null;
4428 r.nowVisible = false;
4429
4430 if (r.finishing && !skipDestroy) {
4431 r.state = ActivityState.DESTROYING;
4432 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4433 msg.obj = r;
4434 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4435 } else {
4436 r.state = ActivityState.DESTROYED;
4437 }
4438 } else {
4439 // remove this record from the history.
4440 if (r.finishing) {
4441 removeActivityFromHistoryLocked(r);
4442 removedFromHistory = true;
4443 } else {
4444 r.state = ActivityState.DESTROYED;
4445 }
4446 }
4447
4448 r.configChangeFlags = 0;
4449
Dianne Hackborn03abb812010-01-04 18:43:19 -08004450 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004451 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004452 }
4453
4454 return removedFromHistory;
4455 }
4456
Dianne Hackborn03abb812010-01-04 18:43:19 -08004457 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004459 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004460 TAG, "Removing app " + app + " from list " + list
4461 + " with " + i + " entries");
4462 while (i > 0) {
4463 i--;
4464 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004465 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4467 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004468 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004469 list.remove(i);
4470 }
4471 }
4472 }
4473
4474 /**
4475 * Main function for removing an existing process from the activity manager
4476 * as a result of that process going away. Clears out all connections
4477 * to the process.
4478 */
4479 private final void handleAppDiedLocked(ProcessRecord app,
4480 boolean restarting) {
4481 cleanUpApplicationRecordLocked(app, restarting, -1);
4482 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004483 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 }
4485
4486 // Just in case...
4487 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004488 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 mPausingActivity = null;
4490 }
4491 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4492 mLastPausedActivity = null;
4493 }
4494
4495 // Remove this application's activities from active lists.
4496 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4497 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4498 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4499 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4500
4501 boolean atTop = true;
4502 boolean hasVisibleActivities = false;
4503
4504 // Clean out the history list.
4505 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004506 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004507 TAG, "Removing app " + app + " from history with " + i + " entries");
4508 while (i > 0) {
4509 i--;
4510 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004511 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4513 if (r.app == app) {
4514 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004515 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 TAG, "Removing this entry! frozen=" + r.haveState
4517 + " finishing=" + r.finishing);
4518 mHistory.remove(i);
4519
4520 r.inHistory = false;
4521 mWindowManager.removeAppToken(r);
4522 if (VALIDATE_TOKENS) {
4523 mWindowManager.validateAppTokens(mHistory);
4524 }
4525 removeActivityUriPermissionsLocked(r);
4526
4527 } else {
4528 // We have the current state for this activity, so
4529 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004530 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 TAG, "Keeping entry, setting app to null");
4532 if (r.visible) {
4533 hasVisibleActivities = true;
4534 }
4535 r.app = null;
4536 r.nowVisible = false;
4537 if (!r.haveState) {
4538 r.icicle = null;
4539 }
4540 }
4541
4542 cleanUpActivityLocked(r, true);
4543 r.state = ActivityState.STOPPED;
4544 }
4545 atTop = false;
4546 }
4547
4548 app.activities.clear();
4549
4550 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004551 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004552 + " running instrumentation " + app.instrumentationClass);
4553 Bundle info = new Bundle();
4554 info.putString("shortMsg", "Process crashed.");
4555 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4556 }
4557
4558 if (!restarting) {
4559 if (!resumeTopActivityLocked(null)) {
4560 // If there was nothing to resume, and we are not already
4561 // restarting this process, but there is a visible activity that
4562 // is hosted by the process... then make sure all visible
4563 // activities are running, taking care of restarting this
4564 // process.
4565 if (hasVisibleActivities) {
4566 ensureActivitiesVisibleLocked(null, 0);
4567 }
4568 }
4569 }
4570 }
4571
4572 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4573 IBinder threadBinder = thread.asBinder();
4574
4575 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004576 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4577 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004578 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4579 return i;
4580 }
4581 }
4582 return -1;
4583 }
4584
4585 private final ProcessRecord getRecordForAppLocked(
4586 IApplicationThread thread) {
4587 if (thread == null) {
4588 return null;
4589 }
4590
4591 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004592 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 }
4594
4595 private final void appDiedLocked(ProcessRecord app, int pid,
4596 IApplicationThread thread) {
4597
4598 mProcDeaths[0]++;
4599
Magnus Edlund7bb25812010-02-24 15:45:06 +01004600 // Clean up already done if the process has been re-started.
4601 if (app.pid == pid && app.thread != null &&
4602 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004603 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004604 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004605 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004606 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 TAG, "Dying app: " + app + ", pid: " + pid
4608 + ", thread: " + thread.asBinder());
4609 boolean doLowMem = app.instrumentationClass == null;
4610 handleAppDiedLocked(app, false);
4611
4612 if (doLowMem) {
4613 // If there are no longer any background processes running,
4614 // and the app that died was not running instrumentation,
4615 // then tell everyone we are now low on memory.
4616 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004617 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4618 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4620 haveBg = true;
4621 break;
4622 }
4623 }
4624
4625 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004626 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004627 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004628 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004629 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4630 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004631 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004632 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4633 // The low memory report is overriding any current
4634 // state for a GC request. Make sure to do
4635 // visible/foreground processes first.
4636 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4637 rec.lastRequestedGc = 0;
4638 } else {
4639 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004641 rec.reportLowMemory = true;
4642 rec.lastLowMemory = now;
4643 mProcessesToGc.remove(rec);
4644 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 }
4646 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004647 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004648 }
4649 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004650 } else if (app.pid != pid) {
4651 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004652 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004653 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004654 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004655 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004656 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004657 + thread.asBinder());
4658 }
4659 }
4660
Dan Egnor42471dd2010-01-07 17:25:22 -08004661 /**
4662 * If a stack trace dump file is configured, dump process stack traces.
4663 * @param pids of dalvik VM processes to dump stack traces for
4664 * @return file containing stack traces, or null if no dump file is configured
4665 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004666 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004667 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4668 if (tracesPath == null || tracesPath.length() == 0) {
4669 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004671
4672 File tracesFile = new File(tracesPath);
4673 try {
4674 File tracesDir = tracesFile.getParentFile();
4675 if (!tracesDir.exists()) tracesFile.mkdirs();
4676 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4677
4678 if (tracesFile.exists()) tracesFile.delete();
4679 tracesFile.createNewFile();
4680 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4681 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004682 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004683 return null;
4684 }
4685
4686 // Use a FileObserver to detect when traces finish writing.
4687 // The order of traces is considered important to maintain for legibility.
4688 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4689 public synchronized void onEvent(int event, String path) { notify(); }
4690 };
4691
4692 try {
4693 observer.startWatching();
4694 int num = pids.size();
4695 for (int i = 0; i < num; i++) {
4696 synchronized (observer) {
4697 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4698 observer.wait(200); // Wait for write-close, give up after 200msec
4699 }
4700 }
4701 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004702 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004703 } finally {
4704 observer.stopWatching();
4705 }
4706
4707 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004708 }
4709
Dan Egnor42471dd2010-01-07 17:25:22 -08004710 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4711 HistoryRecord parent, final String annotation) {
Mike Lockwoodb62f9592010-03-12 07:55:23 -05004712 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4713 if (mShuttingDown || app.notResponding || app.crashing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004714 return;
4715 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004718 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4719 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720
Dan Egnor42471dd2010-01-07 17:25:22 -08004721 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4722 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4723 pids.add(app.pid);
4724
4725 int parentPid = app.pid;
4726 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4727 if (parentPid != app.pid) pids.add(parentPid);
4728
4729 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4730
4731 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4732 ProcessRecord r = mLruProcesses.get(i);
4733 if (r != null && r.thread != null) {
4734 int pid = r.pid;
4735 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004736 }
4737 }
4738
Dan Egnor42471dd2010-01-07 17:25:22 -08004739 File tracesFile = dumpStackTraces(pids);
4740
4741 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004742 StringBuilder info = mStringBuilder;
4743 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004744 info.append("ANR in ").append(app.processName);
4745 if (activity != null && activity.shortComponentName != null) {
4746 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004747 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004748 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004750 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004751 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004752 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004753 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004755
Dan Egnor42471dd2010-01-07 17:25:22 -08004756 String cpuInfo = null;
4757 if (MONITOR_CPU_USAGE) {
4758 updateCpuStatsNow();
4759 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4760 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004761 }
4762
Joe Onorato8a9b2202010-02-26 18:56:32 -08004763 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004764 if (tracesFile == null) {
4765 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4766 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4767 }
4768
4769 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4770
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004771 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004772 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004773 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4774 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004776 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4777 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004778 }
4779 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004780 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004781 }
4782 }
4783
Dan Egnor42471dd2010-01-07 17:25:22 -08004784 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4785 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4786 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4787 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4788 Process.killProcess(app.pid);
4789 return;
4790 }
4791
4792 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004793 makeAppNotRespondingLocked(app,
4794 activity != null ? activity.shortComponentName : null,
4795 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004796 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004797
4798 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004799 Message msg = Message.obtain();
4800 HashMap map = new HashMap();
4801 msg.what = SHOW_NOT_RESPONDING_MSG;
4802 msg.obj = map;
4803 map.put("app", app);
4804 if (activity != null) {
4805 map.put("activity", activity);
4806 }
4807
4808 mHandler.sendMessage(msg);
4809 return;
4810 }
4811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004812 private final void decPersistentCountLocked(ProcessRecord app)
4813 {
4814 app.persistentActivities--;
4815 if (app.persistentActivities > 0) {
4816 // Still more of 'em...
4817 return;
4818 }
4819 if (app.persistent) {
4820 // Ah, but the application itself is persistent. Whatever!
4821 return;
4822 }
4823
4824 // App is no longer persistent... make sure it and the ones
4825 // following it in the LRU list have the correc oom_adj.
4826 updateOomAdjLocked();
4827 }
4828
4829 public void setPersistent(IBinder token, boolean isPersistent) {
4830 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4831 != PackageManager.PERMISSION_GRANTED) {
4832 String msg = "Permission Denial: setPersistent() from pid="
4833 + Binder.getCallingPid()
4834 + ", uid=" + Binder.getCallingUid()
4835 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004836 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837 throw new SecurityException(msg);
4838 }
4839
4840 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004841 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004842 if (index < 0) {
4843 return;
4844 }
4845 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4846 ProcessRecord app = r.app;
4847
Joe Onorato8a9b2202010-02-26 18:56:32 -08004848 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004849 TAG, "Setting persistence " + isPersistent + ": " + r);
4850
4851 if (isPersistent) {
4852 if (r.persistent) {
4853 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004854 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 return;
4856 }
4857 r.persistent = true;
4858 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004859 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860 if (app.persistentActivities > 1) {
4861 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004862 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 return;
4864 }
4865 if (app.persistent) {
4866 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004867 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 return;
4869 }
4870
4871 // App is now persistent... make sure it and the ones
4872 // following it now have the correct oom_adj.
4873 final long origId = Binder.clearCallingIdentity();
4874 updateOomAdjLocked();
4875 Binder.restoreCallingIdentity(origId);
4876
4877 } else {
4878 if (!r.persistent) {
4879 // Okay okay, I heard you already!
4880 return;
4881 }
4882 r.persistent = false;
4883 final long origId = Binder.clearCallingIdentity();
4884 decPersistentCountLocked(app);
4885 Binder.restoreCallingIdentity(origId);
4886
4887 }
4888 }
4889 }
4890
4891 public boolean clearApplicationUserData(final String packageName,
4892 final IPackageDataObserver observer) {
4893 int uid = Binder.getCallingUid();
4894 int pid = Binder.getCallingPid();
4895 long callingId = Binder.clearCallingIdentity();
4896 try {
4897 IPackageManager pm = ActivityThread.getPackageManager();
4898 int pkgUid = -1;
4899 synchronized(this) {
4900 try {
4901 pkgUid = pm.getPackageUid(packageName);
4902 } catch (RemoteException e) {
4903 }
4904 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004905 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004906 return false;
4907 }
4908 if (uid == pkgUid || checkComponentPermission(
4909 android.Manifest.permission.CLEAR_APP_USER_DATA,
4910 pid, uid, -1)
4911 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004912 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004913 } else {
4914 throw new SecurityException(pid+" does not have permission:"+
4915 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4916 "for process:"+packageName);
4917 }
4918 }
4919
4920 try {
4921 //clear application user data
4922 pm.clearApplicationUserData(packageName, observer);
4923 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4924 Uri.fromParts("package", packageName, null));
4925 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4926 broadcastIntentLocked(null, null, intent,
4927 null, null, 0, null, null, null,
4928 false, false, MY_PID, Process.SYSTEM_UID);
4929 } catch (RemoteException e) {
4930 }
4931 } finally {
4932 Binder.restoreCallingIdentity(callingId);
4933 }
4934 return true;
4935 }
4936
Dianne Hackborn03abb812010-01-04 18:43:19 -08004937 public void killBackgroundProcesses(final String packageName) {
4938 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4939 != PackageManager.PERMISSION_GRANTED &&
4940 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4941 != PackageManager.PERMISSION_GRANTED) {
4942 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004943 + Binder.getCallingPid()
4944 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004945 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004946 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004947 throw new SecurityException(msg);
4948 }
4949
4950 long callingId = Binder.clearCallingIdentity();
4951 try {
4952 IPackageManager pm = ActivityThread.getPackageManager();
4953 int pkgUid = -1;
4954 synchronized(this) {
4955 try {
4956 pkgUid = pm.getPackageUid(packageName);
4957 } catch (RemoteException e) {
4958 }
4959 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004960 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 return;
4962 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004963 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004964 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004965 }
4966 } finally {
4967 Binder.restoreCallingIdentity(callingId);
4968 }
4969 }
4970
4971 public void forceStopPackage(final String packageName) {
4972 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4973 != PackageManager.PERMISSION_GRANTED) {
4974 String msg = "Permission Denial: forceStopPackage() from pid="
4975 + Binder.getCallingPid()
4976 + ", uid=" + Binder.getCallingUid()
4977 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004978 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004979 throw new SecurityException(msg);
4980 }
4981
4982 long callingId = Binder.clearCallingIdentity();
4983 try {
4984 IPackageManager pm = ActivityThread.getPackageManager();
4985 int pkgUid = -1;
4986 synchronized(this) {
4987 try {
4988 pkgUid = pm.getPackageUid(packageName);
4989 } catch (RemoteException e) {
4990 }
4991 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004992 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004993 return;
4994 }
4995 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 }
4997 } finally {
4998 Binder.restoreCallingIdentity(callingId);
4999 }
5000 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005001
5002 /*
5003 * The pkg name and uid have to be specified.
5004 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5005 */
5006 public void killApplicationWithUid(String pkg, int uid) {
5007 if (pkg == null) {
5008 return;
5009 }
5010 // Make sure the uid is valid.
5011 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005012 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005013 return;
5014 }
5015 int callerUid = Binder.getCallingUid();
5016 // Only the system server can kill an application
5017 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005018 // Post an aysnc message to kill the application
5019 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5020 msg.arg1 = uid;
5021 msg.arg2 = 0;
5022 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005023 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005024 } else {
5025 throw new SecurityException(callerUid + " cannot kill pkg: " +
5026 pkg);
5027 }
5028 }
5029
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005030 public void closeSystemDialogs(String reason) {
5031 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5032 if (reason != null) {
5033 intent.putExtra("reason", reason);
5034 }
5035
5036 final int uid = Binder.getCallingUid();
5037 final long origId = Binder.clearCallingIdentity();
5038 synchronized (this) {
5039 int i = mWatchers.beginBroadcast();
5040 while (i > 0) {
5041 i--;
5042 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5043 if (w != null) {
5044 try {
5045 w.closingSystemDialogs(reason);
5046 } catch (RemoteException e) {
5047 }
5048 }
5049 }
5050 mWatchers.finishBroadcast();
5051
Dianne Hackbornffa42482009-09-23 22:20:11 -07005052 mWindowManager.closeSystemDialogs(reason);
5053
5054 for (i=mHistory.size()-1; i>=0; i--) {
5055 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5056 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5057 finishActivityLocked(r, i,
5058 Activity.RESULT_CANCELED, null, "close-sys");
5059 }
5060 }
5061
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005062 broadcastIntentLocked(null, null, intent, null,
5063 null, 0, null, null, null, false, false, -1, uid);
5064 }
5065 Binder.restoreCallingIdentity(origId);
5066 }
5067
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005068 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005069 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005070 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5071 for (int i=pids.length-1; i>=0; i--) {
5072 infos[i] = new Debug.MemoryInfo();
5073 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005074 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005075 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005076 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005077
5078 public void killApplicationProcess(String processName, int uid) {
5079 if (processName == null) {
5080 return;
5081 }
5082
5083 int callerUid = Binder.getCallingUid();
5084 // Only the system server can kill an application
5085 if (callerUid == Process.SYSTEM_UID) {
5086 synchronized (this) {
5087 ProcessRecord app = getProcessRecordLocked(processName, uid);
5088 if (app != null) {
5089 try {
5090 app.thread.scheduleSuicide();
5091 } catch (RemoteException e) {
5092 // If the other end already died, then our work here is done.
5093 }
5094 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005095 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005096 + processName + " / " + uid);
5097 }
5098 }
5099 } else {
5100 throw new SecurityException(callerUid + " cannot kill app process: " +
5101 processName);
5102 }
5103 }
5104
Dianne Hackborn03abb812010-01-04 18:43:19 -08005105 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005106 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005107 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5108 Uri.fromParts("package", packageName, null));
5109 intent.putExtra(Intent.EXTRA_UID, uid);
5110 broadcastIntentLocked(null, null, intent,
5111 null, null, 0, null, null, null,
5112 false, false, MY_PID, Process.SYSTEM_UID);
5113 }
5114
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005115 private final boolean killPackageProcessesLocked(String packageName, int uid,
5116 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005117 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118
Dianne Hackborn03abb812010-01-04 18:43:19 -08005119 // Remove all processes this package may have touched: all with the
5120 // same UID (except for the system or root user), and all whose name
5121 // matches the package name.
5122 final String procNamePrefix = packageName + ":";
5123 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5124 final int NA = apps.size();
5125 for (int ia=0; ia<NA; ia++) {
5126 ProcessRecord app = apps.valueAt(ia);
5127 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005128 if (doit) {
5129 procs.add(app);
5130 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005131 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5132 || app.processName.equals(packageName)
5133 || app.processName.startsWith(procNamePrefix)) {
5134 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005135 if (!doit) {
5136 return true;
5137 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005138 app.removed = true;
5139 procs.add(app);
5140 }
5141 }
5142 }
5143 }
5144
5145 int N = procs.size();
5146 for (int i=0; i<N; i++) {
5147 removeProcessLocked(procs.get(i), callerWillRestart);
5148 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005149 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005150 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005151
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005152 private final boolean forceStopPackageLocked(String name, int uid,
5153 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 int i, N;
5155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005156 if (uid < 0) {
5157 try {
5158 uid = ActivityThread.getPackageManager().getPackageUid(name);
5159 } catch (RemoteException e) {
5160 }
5161 }
5162
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005163 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005164 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005165
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005166 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5167 while (badApps.hasNext()) {
5168 SparseArray<Long> ba = badApps.next();
5169 if (ba.get(uid) != null) {
5170 badApps.remove();
5171 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172 }
5173 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005174
5175 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5176 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005177
5178 for (i=mHistory.size()-1; i>=0; i--) {
5179 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5180 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005181 if (!doit) {
5182 return true;
5183 }
5184 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005185 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 if (r.app != null) {
5187 r.app.removed = true;
5188 }
5189 r.app = null;
5190 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5191 }
5192 }
5193
5194 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5195 for (ServiceRecord service : mServices.values()) {
5196 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005197 if (!doit) {
5198 return true;
5199 }
5200 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005201 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 if (service.app != null) {
5203 service.app.removed = true;
5204 }
5205 service.app = null;
5206 services.add(service);
5207 }
5208 }
5209
5210 N = services.size();
5211 for (i=0; i<N; i++) {
5212 bringDownServiceLocked(services.get(i), true);
5213 }
5214
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005215 if (doit) {
5216 if (purgeCache) {
5217 AttributeCache ac = AttributeCache.instance();
5218 if (ac != null) {
5219 ac.removePackage(name);
5220 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005221 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005222 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005223 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005224
5225 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005226 }
5227
5228 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5229 final String name = app.processName;
5230 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005231 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 TAG, "Force removing process " + app + " (" + name
5233 + "/" + uid + ")");
5234
5235 mProcessNames.remove(name, uid);
5236 boolean needRestart = false;
5237 if (app.pid > 0 && app.pid != MY_PID) {
5238 int pid = app.pid;
5239 synchronized (mPidsSelfLocked) {
5240 mPidsSelfLocked.remove(pid);
5241 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5242 }
5243 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005244 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 Process.killProcess(pid);
5246
5247 if (app.persistent) {
5248 if (!callerWillRestart) {
5249 addAppLocked(app.info);
5250 } else {
5251 needRestart = true;
5252 }
5253 }
5254 } else {
5255 mRemovedProcesses.add(app);
5256 }
5257
5258 return needRestart;
5259 }
5260
5261 private final void processStartTimedOutLocked(ProcessRecord app) {
5262 final int pid = app.pid;
5263 boolean gone = false;
5264 synchronized (mPidsSelfLocked) {
5265 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5266 if (knownApp != null && knownApp.thread == null) {
5267 mPidsSelfLocked.remove(pid);
5268 gone = true;
5269 }
5270 }
5271
5272 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005273 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005274 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005275 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005277 // Take care of any launching providers waiting for this process.
5278 checkAppInLaunchingProvidersLocked(app, true);
5279 // Take care of any services that are waiting for the process.
5280 for (int i=0; i<mPendingServices.size(); i++) {
5281 ServiceRecord sr = mPendingServices.get(i);
5282 if (app.info.uid == sr.appInfo.uid
5283 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005284 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005285 mPendingServices.remove(i);
5286 i--;
5287 bringDownServiceLocked(sr, true);
5288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005289 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005290 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005291 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005292 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005293 try {
5294 IBackupManager bm = IBackupManager.Stub.asInterface(
5295 ServiceManager.getService(Context.BACKUP_SERVICE));
5296 bm.agentDisconnected(app.info.packageName);
5297 } catch (RemoteException e) {
5298 // Can't happen; the backup manager is local
5299 }
5300 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005301 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005302 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005303 mPendingBroadcast = null;
5304 scheduleBroadcastsLocked();
5305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005306 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005307 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005308 }
5309 }
5310
5311 private final boolean attachApplicationLocked(IApplicationThread thread,
5312 int pid) {
5313
5314 // Find the application record that is being attached... either via
5315 // the pid if we are running in multiple processes, or just pull the
5316 // next app record if we are emulating process with anonymous threads.
5317 ProcessRecord app;
5318 if (pid != MY_PID && pid >= 0) {
5319 synchronized (mPidsSelfLocked) {
5320 app = mPidsSelfLocked.get(pid);
5321 }
5322 } else if (mStartingProcesses.size() > 0) {
5323 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005324 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005325 } else {
5326 app = null;
5327 }
5328
5329 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005330 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005332 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005333 if (pid > 0 && pid != MY_PID) {
5334 Process.killProcess(pid);
5335 } else {
5336 try {
5337 thread.scheduleExit();
5338 } catch (Exception e) {
5339 // Ignore exceptions.
5340 }
5341 }
5342 return false;
5343 }
5344
5345 // If this application record is still attached to a previous
5346 // process, clean it up now.
5347 if (app.thread != null) {
5348 handleAppDiedLocked(app, true);
5349 }
5350
5351 // Tell the process all about itself.
5352
Joe Onorato8a9b2202010-02-26 18:56:32 -08005353 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 TAG, "Binding process pid " + pid + " to record " + app);
5355
5356 String processName = app.processName;
5357 try {
5358 thread.asBinder().linkToDeath(new AppDeathRecipient(
5359 app, pid, thread), 0);
5360 } catch (RemoteException e) {
5361 app.resetPackageList();
5362 startProcessLocked(app, "link fail", processName);
5363 return false;
5364 }
5365
Doug Zongker2bec3d42009-12-04 12:52:44 -08005366 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005367
5368 app.thread = thread;
5369 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005370 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5371 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005372 app.forcingToForeground = null;
5373 app.foregroundServices = false;
5374 app.debugging = false;
5375
5376 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5377
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005378 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5379 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005380
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005381 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005382 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005383 }
5384
Joe Onorato8a9b2202010-02-26 18:56:32 -08005385 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 TAG, "New app record " + app
5387 + " thread=" + thread.asBinder() + " pid=" + pid);
5388 try {
5389 int testMode = IApplicationThread.DEBUG_OFF;
5390 if (mDebugApp != null && mDebugApp.equals(processName)) {
5391 testMode = mWaitForDebugger
5392 ? IApplicationThread.DEBUG_WAIT
5393 : IApplicationThread.DEBUG_ON;
5394 app.debugging = true;
5395 if (mDebugTransient) {
5396 mDebugApp = mOrigDebugApp;
5397 mWaitForDebugger = mOrigWaitForDebugger;
5398 }
5399 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005400
Christopher Tate181fafa2009-05-14 11:12:14 -07005401 // If the app is being launched for restore or full backup, set it up specially
5402 boolean isRestrictedBackupMode = false;
5403 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5404 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5405 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5406 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005407
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005408 ensurePackageDexOpt(app.instrumentationInfo != null
5409 ? app.instrumentationInfo.packageName
5410 : app.info.packageName);
5411 if (app.instrumentationClass != null) {
5412 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005413 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005414 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005415 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005416 thread.bindApplication(processName, app.instrumentationInfo != null
5417 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005418 app.instrumentationClass, app.instrumentationProfileFile,
5419 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005420 isRestrictedBackupMode || !normalMode,
5421 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005422 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005423 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 } catch (Exception e) {
5425 // todo: Yikes! What should we do? For now we will try to
5426 // start another process, but that could easily get us in
5427 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005428 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429
5430 app.resetPackageList();
5431 startProcessLocked(app, "bind fail", processName);
5432 return false;
5433 }
5434
5435 // Remove this record from the list of starting applications.
5436 mPersistentStartingProcesses.remove(app);
5437 mProcessesOnHold.remove(app);
5438
5439 boolean badApp = false;
5440 boolean didSomething = false;
5441
5442 // See if the top visible activity is waiting to run in this process...
5443 HistoryRecord hr = topRunningActivityLocked(null);
5444 if (hr != null) {
5445 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5446 && processName.equals(hr.processName)) {
5447 try {
5448 if (realStartActivityLocked(hr, app, true, true)) {
5449 didSomething = true;
5450 }
5451 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005452 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005453 + hr.intent.getComponent().flattenToShortString(), e);
5454 badApp = true;
5455 }
5456 } else {
5457 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5458 }
5459 }
5460
5461 // Find any services that should be running in this process...
5462 if (!badApp && mPendingServices.size() > 0) {
5463 ServiceRecord sr = null;
5464 try {
5465 for (int i=0; i<mPendingServices.size(); i++) {
5466 sr = mPendingServices.get(i);
5467 if (app.info.uid != sr.appInfo.uid
5468 || !processName.equals(sr.processName)) {
5469 continue;
5470 }
5471
5472 mPendingServices.remove(i);
5473 i--;
5474 realStartServiceLocked(sr, app);
5475 didSomething = true;
5476 }
5477 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005478 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 + sr.shortName, e);
5480 badApp = true;
5481 }
5482 }
5483
5484 // Check if the next broadcast receiver is in this process...
5485 BroadcastRecord br = mPendingBroadcast;
5486 if (!badApp && br != null && br.curApp == app) {
5487 try {
5488 mPendingBroadcast = null;
5489 processCurBroadcastLocked(br, app);
5490 didSomething = true;
5491 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005492 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 + br.curComponent.flattenToShortString(), e);
5494 badApp = true;
5495 logBroadcastReceiverDiscard(br);
5496 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5497 br.resultExtras, br.resultAbort, true);
5498 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005499 // We need to reset the state if we fails to start the receiver.
5500 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 }
5502 }
5503
Christopher Tate181fafa2009-05-14 11:12:14 -07005504 // Check whether the next backup agent is in this process...
5505 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005506 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005507 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005508 try {
5509 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5510 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005511 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005512 e.printStackTrace();
5513 }
5514 }
5515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005516 if (badApp) {
5517 // todo: Also need to kill application to deal with all
5518 // kinds of exceptions.
5519 handleAppDiedLocked(app, false);
5520 return false;
5521 }
5522
5523 if (!didSomething) {
5524 updateOomAdjLocked();
5525 }
5526
5527 return true;
5528 }
5529
5530 public final void attachApplication(IApplicationThread thread) {
5531 synchronized (this) {
5532 int callingPid = Binder.getCallingPid();
5533 final long origId = Binder.clearCallingIdentity();
5534 attachApplicationLocked(thread, callingPid);
5535 Binder.restoreCallingIdentity(origId);
5536 }
5537 }
5538
Dianne Hackborne88846e2009-09-30 21:34:25 -07005539 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005540 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005541 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005542 Binder.restoreCallingIdentity(origId);
5543 }
5544
5545 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5546 boolean remove) {
5547 int N = mStoppingActivities.size();
5548 if (N <= 0) return null;
5549
5550 ArrayList<HistoryRecord> stops = null;
5551
5552 final boolean nowVisible = mResumedActivity != null
5553 && mResumedActivity.nowVisible
5554 && !mResumedActivity.waitingVisible;
5555 for (int i=0; i<N; i++) {
5556 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005557 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 + nowVisible + " waitingVisible=" + s.waitingVisible
5559 + " finishing=" + s.finishing);
5560 if (s.waitingVisible && nowVisible) {
5561 mWaitingVisibleActivities.remove(s);
5562 s.waitingVisible = false;
5563 if (s.finishing) {
5564 // If this activity is finishing, it is sitting on top of
5565 // everyone else but we now know it is no longer needed...
5566 // so get rid of it. Otherwise, we need to go through the
5567 // normal flow and hide it once we determine that it is
5568 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005569 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005570 mWindowManager.setAppVisibility(s, false);
5571 }
5572 }
5573 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005574 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005575 if (stops == null) {
5576 stops = new ArrayList<HistoryRecord>();
5577 }
5578 stops.add(s);
5579 mStoppingActivities.remove(i);
5580 N--;
5581 i--;
5582 }
5583 }
5584
5585 return stops;
5586 }
5587
5588 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005589 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005590 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005591 mWindowManager.enableScreenAfterBoot();
5592 }
5593
Dianne Hackborne88846e2009-09-30 21:34:25 -07005594 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5595 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005596 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597
5598 ArrayList<HistoryRecord> stops = null;
5599 ArrayList<HistoryRecord> finishes = null;
5600 ArrayList<HistoryRecord> thumbnails = null;
5601 int NS = 0;
5602 int NF = 0;
5603 int NT = 0;
5604 IApplicationThread sendThumbnail = null;
5605 boolean booting = false;
5606 boolean enableScreen = false;
5607
5608 synchronized (this) {
5609 if (token != null) {
5610 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5611 }
5612
5613 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005614 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 if (index >= 0) {
5616 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5617
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005618 if (fromTimeout) {
5619 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5620 }
5621
Dianne Hackborne88846e2009-09-30 21:34:25 -07005622 // This is a hack to semi-deal with a race condition
5623 // in the client where it can be constructed with a
5624 // newer configuration from when we asked it to launch.
5625 // We'll update with whatever configuration it now says
5626 // it used to launch.
5627 if (config != null) {
5628 r.configuration = config;
5629 }
5630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 // No longer need to keep the device awake.
5632 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5633 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5634 mLaunchingActivity.release();
5635 }
5636
5637 // We are now idle. If someone is waiting for a thumbnail from
5638 // us, we can now deliver.
5639 r.idle = true;
5640 scheduleAppGcsLocked();
5641 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5642 sendThumbnail = r.app.thread;
5643 r.thumbnailNeeded = false;
5644 }
5645
5646 // If this activity is fullscreen, set up to hide those under it.
5647
Joe Onorato8a9b2202010-02-26 18:56:32 -08005648 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 ensureActivitiesVisibleLocked(null, 0);
5650
Joe Onorato8a9b2202010-02-26 18:56:32 -08005651 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005652 if (!mBooted && !fromTimeout) {
5653 mBooted = true;
5654 enableScreen = true;
5655 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005656
5657 } else if (fromTimeout) {
5658 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005659 }
5660
5661 // Atomically retrieve all of the other things to do.
5662 stops = processStoppingActivitiesLocked(true);
5663 NS = stops != null ? stops.size() : 0;
5664 if ((NF=mFinishingActivities.size()) > 0) {
5665 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5666 mFinishingActivities.clear();
5667 }
5668 if ((NT=mCancelledThumbnails.size()) > 0) {
5669 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5670 mCancelledThumbnails.clear();
5671 }
5672
5673 booting = mBooting;
5674 mBooting = false;
5675 }
5676
5677 int i;
5678
5679 // Send thumbnail if requested.
5680 if (sendThumbnail != null) {
5681 try {
5682 sendThumbnail.requestThumbnail(token);
5683 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005684 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005685 sendPendingThumbnail(null, token, null, null, true);
5686 }
5687 }
5688
5689 // Stop any activities that are scheduled to do so but have been
5690 // waiting for the next one to start.
5691 for (i=0; i<NS; i++) {
5692 HistoryRecord r = (HistoryRecord)stops.get(i);
5693 synchronized (this) {
5694 if (r.finishing) {
5695 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5696 } else {
5697 stopActivityLocked(r);
5698 }
5699 }
5700 }
5701
5702 // Finish any activities that are scheduled to do so but have been
5703 // waiting for the next one to start.
5704 for (i=0; i<NF; i++) {
5705 HistoryRecord r = (HistoryRecord)finishes.get(i);
5706 synchronized (this) {
5707 destroyActivityLocked(r, true);
5708 }
5709 }
5710
5711 // Report back to any thumbnail receivers.
5712 for (i=0; i<NT; i++) {
5713 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5714 sendPendingThumbnail(r, null, null, null, true);
5715 }
5716
5717 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005718 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005719 }
5720
5721 trimApplications();
5722 //dump();
5723 //mWindowManager.dump();
5724
5725 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 enableScreenAfterBoot();
5727 }
5728 }
5729
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005730 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005731 IntentFilter pkgFilter = new IntentFilter();
5732 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5733 pkgFilter.addDataScheme("package");
5734 mContext.registerReceiver(new BroadcastReceiver() {
5735 @Override
5736 public void onReceive(Context context, Intent intent) {
5737 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5738 if (pkgs != null) {
5739 for (String pkg : pkgs) {
5740 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5741 setResultCode(Activity.RESULT_OK);
5742 return;
5743 }
5744 }
5745 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005746 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005747 }, pkgFilter);
5748
5749 synchronized (this) {
5750 // Ensure that any processes we had put on hold are now started
5751 // up.
5752 final int NP = mProcessesOnHold.size();
5753 if (NP > 0) {
5754 ArrayList<ProcessRecord> procs =
5755 new ArrayList<ProcessRecord>(mProcessesOnHold);
5756 for (int ip=0; ip<NP; ip++) {
5757 this.startProcessLocked(procs.get(ip), "on-hold", null);
5758 }
5759 }
5760
5761 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5762 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005763 broadcastIntentLocked(null, null,
5764 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5765 null, null, 0, null, null,
5766 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5767 false, false, MY_PID, Process.SYSTEM_UID);
5768 }
5769 }
5770 }
5771
5772 final void ensureBootCompleted() {
5773 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005774 boolean enableScreen;
5775 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005776 booting = mBooting;
5777 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005778 enableScreen = !mBooted;
5779 mBooted = true;
5780 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005781
5782 if (booting) {
5783 finishBooting();
5784 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005785
5786 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005787 enableScreenAfterBoot();
5788 }
5789 }
5790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 public final void activityPaused(IBinder token, Bundle icicle) {
5792 // Refuse possible leaked file descriptors
5793 if (icicle != null && icicle.hasFileDescriptors()) {
5794 throw new IllegalArgumentException("File descriptors passed in Bundle");
5795 }
5796
5797 final long origId = Binder.clearCallingIdentity();
5798 activityPaused(token, icicle, false);
5799 Binder.restoreCallingIdentity(origId);
5800 }
5801
5802 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005803 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005804 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5805 + ", timeout=" + timeout);
5806
5807 HistoryRecord r = null;
5808
5809 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005810 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 if (index >= 0) {
5812 r = (HistoryRecord)mHistory.get(index);
5813 if (!timeout) {
5814 r.icicle = icicle;
5815 r.haveState = true;
5816 }
5817 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5818 if (mPausingActivity == r) {
5819 r.state = ActivityState.PAUSED;
5820 completePauseLocked();
5821 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005822 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005823 System.identityHashCode(r), r.shortComponentName,
5824 mPausingActivity != null
5825 ? mPausingActivity.shortComponentName : "(none)");
5826 }
5827 }
5828 }
5829 }
5830
5831 public final void activityStopped(IBinder token, Bitmap thumbnail,
5832 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005833 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005834 TAG, "Activity stopped: token=" + token);
5835
5836 HistoryRecord r = null;
5837
5838 final long origId = Binder.clearCallingIdentity();
5839
5840 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005841 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005842 if (index >= 0) {
5843 r = (HistoryRecord)mHistory.get(index);
5844 r.thumbnail = thumbnail;
5845 r.description = description;
5846 r.stopped = true;
5847 r.state = ActivityState.STOPPED;
5848 if (!r.finishing) {
5849 if (r.configDestroy) {
5850 destroyActivityLocked(r, true);
5851 resumeTopActivityLocked(null);
5852 }
5853 }
5854 }
5855 }
5856
5857 if (r != null) {
5858 sendPendingThumbnail(r, null, null, null, false);
5859 }
5860
5861 trimApplications();
5862
5863 Binder.restoreCallingIdentity(origId);
5864 }
5865
5866 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005867 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 synchronized (this) {
5869 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5870
Dianne Hackborn75b03852009-06-12 15:43:26 -07005871 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005872 if (index >= 0) {
5873 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5874 if (r.state == ActivityState.DESTROYING) {
5875 final long origId = Binder.clearCallingIdentity();
5876 removeActivityFromHistoryLocked(r);
5877 Binder.restoreCallingIdentity(origId);
5878 }
5879 }
5880 }
5881 }
5882
5883 public String getCallingPackage(IBinder token) {
5884 synchronized (this) {
5885 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005886 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005887 }
5888 }
5889
5890 public ComponentName getCallingActivity(IBinder token) {
5891 synchronized (this) {
5892 HistoryRecord r = getCallingRecordLocked(token);
5893 return r != null ? r.intent.getComponent() : null;
5894 }
5895 }
5896
5897 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005898 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005899 if (index >= 0) {
5900 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5901 if (r != null) {
5902 return r.resultTo;
5903 }
5904 }
5905 return null;
5906 }
5907
5908 public ComponentName getActivityClassForToken(IBinder token) {
5909 synchronized(this) {
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 return r.intent.getComponent();
5914 }
5915 return null;
5916 }
5917 }
5918
5919 public String getPackageForToken(IBinder token) {
5920 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005921 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005922 if (index >= 0) {
5923 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5924 return r.packageName;
5925 }
5926 return null;
5927 }
5928 }
5929
5930 public IIntentSender getIntentSender(int type,
5931 String packageName, IBinder token, String resultWho,
5932 int requestCode, Intent intent, String resolvedType, int flags) {
5933 // Refuse possible leaked file descriptors
5934 if (intent != null && intent.hasFileDescriptors() == true) {
5935 throw new IllegalArgumentException("File descriptors passed in Intent");
5936 }
5937
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005938 if (type == INTENT_SENDER_BROADCAST) {
5939 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5940 throw new IllegalArgumentException(
5941 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5942 }
5943 }
5944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005945 synchronized(this) {
5946 int callingUid = Binder.getCallingUid();
5947 try {
5948 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5949 Process.supportsProcesses()) {
5950 int uid = ActivityThread.getPackageManager()
5951 .getPackageUid(packageName);
5952 if (uid != Binder.getCallingUid()) {
5953 String msg = "Permission Denial: getIntentSender() from pid="
5954 + Binder.getCallingPid()
5955 + ", uid=" + Binder.getCallingUid()
5956 + ", (need uid=" + uid + ")"
5957 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005958 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005959 throw new SecurityException(msg);
5960 }
5961 }
5962 } catch (RemoteException e) {
5963 throw new SecurityException(e);
5964 }
5965 HistoryRecord activity = null;
5966 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005967 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 if (index < 0) {
5969 return null;
5970 }
5971 activity = (HistoryRecord)mHistory.get(index);
5972 if (activity.finishing) {
5973 return null;
5974 }
5975 }
5976
5977 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5978 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5979 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5980 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5981 |PendingIntent.FLAG_UPDATE_CURRENT);
5982
5983 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5984 type, packageName, activity, resultWho,
5985 requestCode, intent, resolvedType, flags);
5986 WeakReference<PendingIntentRecord> ref;
5987 ref = mIntentSenderRecords.get(key);
5988 PendingIntentRecord rec = ref != null ? ref.get() : null;
5989 if (rec != null) {
5990 if (!cancelCurrent) {
5991 if (updateCurrent) {
5992 rec.key.requestIntent.replaceExtras(intent);
5993 }
5994 return rec;
5995 }
5996 rec.canceled = true;
5997 mIntentSenderRecords.remove(key);
5998 }
5999 if (noCreate) {
6000 return rec;
6001 }
6002 rec = new PendingIntentRecord(this, key, callingUid);
6003 mIntentSenderRecords.put(key, rec.ref);
6004 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6005 if (activity.pendingResults == null) {
6006 activity.pendingResults
6007 = new HashSet<WeakReference<PendingIntentRecord>>();
6008 }
6009 activity.pendingResults.add(rec.ref);
6010 }
6011 return rec;
6012 }
6013 }
6014
6015 public void cancelIntentSender(IIntentSender sender) {
6016 if (!(sender instanceof PendingIntentRecord)) {
6017 return;
6018 }
6019 synchronized(this) {
6020 PendingIntentRecord rec = (PendingIntentRecord)sender;
6021 try {
6022 int uid = ActivityThread.getPackageManager()
6023 .getPackageUid(rec.key.packageName);
6024 if (uid != Binder.getCallingUid()) {
6025 String msg = "Permission Denial: cancelIntentSender() from pid="
6026 + Binder.getCallingPid()
6027 + ", uid=" + Binder.getCallingUid()
6028 + " is not allowed to cancel packges "
6029 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006030 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006031 throw new SecurityException(msg);
6032 }
6033 } catch (RemoteException e) {
6034 throw new SecurityException(e);
6035 }
6036 cancelIntentSenderLocked(rec, true);
6037 }
6038 }
6039
6040 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6041 rec.canceled = true;
6042 mIntentSenderRecords.remove(rec.key);
6043 if (cleanActivity && rec.key.activity != null) {
6044 rec.key.activity.pendingResults.remove(rec.ref);
6045 }
6046 }
6047
6048 public String getPackageForIntentSender(IIntentSender pendingResult) {
6049 if (!(pendingResult instanceof PendingIntentRecord)) {
6050 return null;
6051 }
6052 synchronized(this) {
6053 try {
6054 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6055 return res.key.packageName;
6056 } catch (ClassCastException e) {
6057 }
6058 }
6059 return null;
6060 }
6061
6062 public void setProcessLimit(int max) {
6063 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6064 "setProcessLimit()");
6065 mProcessLimit = max;
6066 }
6067
6068 public int getProcessLimit() {
6069 return mProcessLimit;
6070 }
6071
6072 void foregroundTokenDied(ForegroundToken token) {
6073 synchronized (ActivityManagerService.this) {
6074 synchronized (mPidsSelfLocked) {
6075 ForegroundToken cur
6076 = mForegroundProcesses.get(token.pid);
6077 if (cur != token) {
6078 return;
6079 }
6080 mForegroundProcesses.remove(token.pid);
6081 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6082 if (pr == null) {
6083 return;
6084 }
6085 pr.forcingToForeground = null;
6086 pr.foregroundServices = false;
6087 }
6088 updateOomAdjLocked();
6089 }
6090 }
6091
6092 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6093 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6094 "setProcessForeground()");
6095 synchronized(this) {
6096 boolean changed = false;
6097
6098 synchronized (mPidsSelfLocked) {
6099 ProcessRecord pr = mPidsSelfLocked.get(pid);
6100 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006101 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 return;
6103 }
6104 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6105 if (oldToken != null) {
6106 oldToken.token.unlinkToDeath(oldToken, 0);
6107 mForegroundProcesses.remove(pid);
6108 pr.forcingToForeground = null;
6109 changed = true;
6110 }
6111 if (isForeground && token != null) {
6112 ForegroundToken newToken = new ForegroundToken() {
6113 public void binderDied() {
6114 foregroundTokenDied(this);
6115 }
6116 };
6117 newToken.pid = pid;
6118 newToken.token = token;
6119 try {
6120 token.linkToDeath(newToken, 0);
6121 mForegroundProcesses.put(pid, newToken);
6122 pr.forcingToForeground = token;
6123 changed = true;
6124 } catch (RemoteException e) {
6125 // If the process died while doing this, we will later
6126 // do the cleanup with the process death link.
6127 }
6128 }
6129 }
6130
6131 if (changed) {
6132 updateOomAdjLocked();
6133 }
6134 }
6135 }
6136
6137 // =========================================================
6138 // PERMISSIONS
6139 // =========================================================
6140
6141 static class PermissionController extends IPermissionController.Stub {
6142 ActivityManagerService mActivityManagerService;
6143 PermissionController(ActivityManagerService activityManagerService) {
6144 mActivityManagerService = activityManagerService;
6145 }
6146
6147 public boolean checkPermission(String permission, int pid, int uid) {
6148 return mActivityManagerService.checkPermission(permission, pid,
6149 uid) == PackageManager.PERMISSION_GRANTED;
6150 }
6151 }
6152
6153 /**
6154 * This can be called with or without the global lock held.
6155 */
6156 int checkComponentPermission(String permission, int pid, int uid,
6157 int reqUid) {
6158 // We might be performing an operation on behalf of an indirect binder
6159 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6160 // client identity accordingly before proceeding.
6161 Identity tlsIdentity = sCallerIdentity.get();
6162 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006163 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006164 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6165 uid = tlsIdentity.uid;
6166 pid = tlsIdentity.pid;
6167 }
6168
6169 // Root, system server and our own process get to do everything.
6170 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6171 !Process.supportsProcesses()) {
6172 return PackageManager.PERMISSION_GRANTED;
6173 }
6174 // If the target requires a specific UID, always fail for others.
6175 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006176 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006177 return PackageManager.PERMISSION_DENIED;
6178 }
6179 if (permission == null) {
6180 return PackageManager.PERMISSION_GRANTED;
6181 }
6182 try {
6183 return ActivityThread.getPackageManager()
6184 .checkUidPermission(permission, uid);
6185 } catch (RemoteException e) {
6186 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006187 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006188 }
6189 return PackageManager.PERMISSION_DENIED;
6190 }
6191
6192 /**
6193 * As the only public entry point for permissions checking, this method
6194 * can enforce the semantic that requesting a check on a null global
6195 * permission is automatically denied. (Internally a null permission
6196 * string is used when calling {@link #checkComponentPermission} in cases
6197 * when only uid-based security is needed.)
6198 *
6199 * This can be called with or without the global lock held.
6200 */
6201 public int checkPermission(String permission, int pid, int uid) {
6202 if (permission == null) {
6203 return PackageManager.PERMISSION_DENIED;
6204 }
6205 return checkComponentPermission(permission, pid, uid, -1);
6206 }
6207
6208 /**
6209 * Binder IPC calls go through the public entry point.
6210 * This can be called with or without the global lock held.
6211 */
6212 int checkCallingPermission(String permission) {
6213 return checkPermission(permission,
6214 Binder.getCallingPid(),
6215 Binder.getCallingUid());
6216 }
6217
6218 /**
6219 * This can be called with or without the global lock held.
6220 */
6221 void enforceCallingPermission(String permission, String func) {
6222 if (checkCallingPermission(permission)
6223 == PackageManager.PERMISSION_GRANTED) {
6224 return;
6225 }
6226
6227 String msg = "Permission Denial: " + func + " from pid="
6228 + Binder.getCallingPid()
6229 + ", uid=" + Binder.getCallingUid()
6230 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006231 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006232 throw new SecurityException(msg);
6233 }
6234
6235 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6236 ProviderInfo pi, int uid, int modeFlags) {
6237 try {
6238 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6239 if ((pi.readPermission != null) &&
6240 (pm.checkUidPermission(pi.readPermission, uid)
6241 != PackageManager.PERMISSION_GRANTED)) {
6242 return false;
6243 }
6244 }
6245 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6246 if ((pi.writePermission != null) &&
6247 (pm.checkUidPermission(pi.writePermission, uid)
6248 != PackageManager.PERMISSION_GRANTED)) {
6249 return false;
6250 }
6251 }
6252 return true;
6253 } catch (RemoteException e) {
6254 return false;
6255 }
6256 }
6257
6258 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6259 int modeFlags) {
6260 // Root gets to do everything.
6261 if (uid == 0 || !Process.supportsProcesses()) {
6262 return true;
6263 }
6264 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6265 if (perms == null) return false;
6266 UriPermission perm = perms.get(uri);
6267 if (perm == null) return false;
6268 return (modeFlags&perm.modeFlags) == modeFlags;
6269 }
6270
6271 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6272 // Another redirected-binder-call permissions check as in
6273 // {@link checkComponentPermission}.
6274 Identity tlsIdentity = sCallerIdentity.get();
6275 if (tlsIdentity != null) {
6276 uid = tlsIdentity.uid;
6277 pid = tlsIdentity.pid;
6278 }
6279
6280 // Our own process gets to do everything.
6281 if (pid == MY_PID) {
6282 return PackageManager.PERMISSION_GRANTED;
6283 }
6284 synchronized(this) {
6285 return checkUriPermissionLocked(uri, uid, modeFlags)
6286 ? PackageManager.PERMISSION_GRANTED
6287 : PackageManager.PERMISSION_DENIED;
6288 }
6289 }
6290
6291 private void grantUriPermissionLocked(int callingUid,
6292 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6293 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6294 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6295 if (modeFlags == 0) {
6296 return;
6297 }
6298
Joe Onorato8a9b2202010-02-26 18:56:32 -08006299 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006300 "Requested grant " + targetPkg + " permission to " + uri);
6301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006302 final IPackageManager pm = ActivityThread.getPackageManager();
6303
6304 // If this is not a content: uri, we can't do anything with it.
6305 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006306 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006307 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006308 return;
6309 }
6310
6311 String name = uri.getAuthority();
6312 ProviderInfo pi = null;
6313 ContentProviderRecord cpr
6314 = (ContentProviderRecord)mProvidersByName.get(name);
6315 if (cpr != null) {
6316 pi = cpr.info;
6317 } else {
6318 try {
6319 pi = pm.resolveContentProvider(name,
6320 PackageManager.GET_URI_PERMISSION_PATTERNS);
6321 } catch (RemoteException ex) {
6322 }
6323 }
6324 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006325 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006326 return;
6327 }
6328
6329 int targetUid;
6330 try {
6331 targetUid = pm.getPackageUid(targetPkg);
6332 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006333 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006334 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006335 return;
6336 }
6337 } catch (RemoteException ex) {
6338 return;
6339 }
6340
6341 // First... does the target actually need this permission?
6342 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6343 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006344 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006345 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 return;
6347 }
6348
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006349 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006350 if (!pi.grantUriPermissions) {
6351 throw new SecurityException("Provider " + pi.packageName
6352 + "/" + pi.name
6353 + " does not allow granting of Uri permissions (uri "
6354 + uri + ")");
6355 }
6356 if (pi.uriPermissionPatterns != null) {
6357 final int N = pi.uriPermissionPatterns.length;
6358 boolean allowed = false;
6359 for (int i=0; i<N; i++) {
6360 if (pi.uriPermissionPatterns[i] != null
6361 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6362 allowed = true;
6363 break;
6364 }
6365 }
6366 if (!allowed) {
6367 throw new SecurityException("Provider " + pi.packageName
6368 + "/" + pi.name
6369 + " does not allow granting of permission to path of Uri "
6370 + uri);
6371 }
6372 }
6373
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006374 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 // this uri?
6376 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6377 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6378 throw new SecurityException("Uid " + callingUid
6379 + " does not have permission to uri " + uri);
6380 }
6381 }
6382
6383 // Okay! So here we are: the caller has the assumed permission
6384 // to the uri, and the target doesn't. Let's now give this to
6385 // the target.
6386
Joe Onorato8a9b2202010-02-26 18:56:32 -08006387 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006388 "Granting " + targetPkg + " permission to " + uri);
6389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006390 HashMap<Uri, UriPermission> targetUris
6391 = mGrantedUriPermissions.get(targetUid);
6392 if (targetUris == null) {
6393 targetUris = new HashMap<Uri, UriPermission>();
6394 mGrantedUriPermissions.put(targetUid, targetUris);
6395 }
6396
6397 UriPermission perm = targetUris.get(uri);
6398 if (perm == null) {
6399 perm = new UriPermission(targetUid, uri);
6400 targetUris.put(uri, perm);
6401
6402 }
6403 perm.modeFlags |= modeFlags;
6404 if (activity == null) {
6405 perm.globalModeFlags |= modeFlags;
6406 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6407 perm.readActivities.add(activity);
6408 if (activity.readUriPermissions == null) {
6409 activity.readUriPermissions = new HashSet<UriPermission>();
6410 }
6411 activity.readUriPermissions.add(perm);
6412 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6413 perm.writeActivities.add(activity);
6414 if (activity.writeUriPermissions == null) {
6415 activity.writeUriPermissions = new HashSet<UriPermission>();
6416 }
6417 activity.writeUriPermissions.add(perm);
6418 }
6419 }
6420
6421 private void grantUriPermissionFromIntentLocked(int callingUid,
6422 String targetPkg, Intent intent, HistoryRecord activity) {
6423 if (intent == null) {
6424 return;
6425 }
6426 Uri data = intent.getData();
6427 if (data == null) {
6428 return;
6429 }
6430 grantUriPermissionLocked(callingUid, targetPkg, data,
6431 intent.getFlags(), activity);
6432 }
6433
6434 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6435 Uri uri, int modeFlags) {
6436 synchronized(this) {
6437 final ProcessRecord r = getRecordForAppLocked(caller);
6438 if (r == null) {
6439 throw new SecurityException("Unable to find app for caller "
6440 + caller
6441 + " when granting permission to uri " + uri);
6442 }
6443 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006444 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 return;
6446 }
6447 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006448 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006449 return;
6450 }
6451
6452 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6453 null);
6454 }
6455 }
6456
6457 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6458 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6459 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6460 HashMap<Uri, UriPermission> perms
6461 = mGrantedUriPermissions.get(perm.uid);
6462 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006463 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006464 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 perms.remove(perm.uri);
6466 if (perms.size() == 0) {
6467 mGrantedUriPermissions.remove(perm.uid);
6468 }
6469 }
6470 }
6471 }
6472
6473 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6474 if (activity.readUriPermissions != null) {
6475 for (UriPermission perm : activity.readUriPermissions) {
6476 perm.readActivities.remove(activity);
6477 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6478 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6479 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6480 removeUriPermissionIfNeededLocked(perm);
6481 }
6482 }
6483 }
6484 if (activity.writeUriPermissions != null) {
6485 for (UriPermission perm : activity.writeUriPermissions) {
6486 perm.writeActivities.remove(activity);
6487 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6488 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6489 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6490 removeUriPermissionIfNeededLocked(perm);
6491 }
6492 }
6493 }
6494 }
6495
6496 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6497 int modeFlags) {
6498 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6499 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6500 if (modeFlags == 0) {
6501 return;
6502 }
6503
Joe Onorato8a9b2202010-02-26 18:56:32 -08006504 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006505 "Revoking all granted permissions to " + uri);
6506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006507 final IPackageManager pm = ActivityThread.getPackageManager();
6508
6509 final String authority = uri.getAuthority();
6510 ProviderInfo pi = null;
6511 ContentProviderRecord cpr
6512 = (ContentProviderRecord)mProvidersByName.get(authority);
6513 if (cpr != null) {
6514 pi = cpr.info;
6515 } else {
6516 try {
6517 pi = pm.resolveContentProvider(authority,
6518 PackageManager.GET_URI_PERMISSION_PATTERNS);
6519 } catch (RemoteException ex) {
6520 }
6521 }
6522 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006523 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006524 return;
6525 }
6526
6527 // Does the caller have this permission on the URI?
6528 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6529 // Right now, if you are not the original owner of the permission,
6530 // you are not allowed to revoke it.
6531 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6532 throw new SecurityException("Uid " + callingUid
6533 + " does not have permission to uri " + uri);
6534 //}
6535 }
6536
6537 // Go through all of the permissions and remove any that match.
6538 final List<String> SEGMENTS = uri.getPathSegments();
6539 if (SEGMENTS != null) {
6540 final int NS = SEGMENTS.size();
6541 int N = mGrantedUriPermissions.size();
6542 for (int i=0; i<N; i++) {
6543 HashMap<Uri, UriPermission> perms
6544 = mGrantedUriPermissions.valueAt(i);
6545 Iterator<UriPermission> it = perms.values().iterator();
6546 toploop:
6547 while (it.hasNext()) {
6548 UriPermission perm = it.next();
6549 Uri targetUri = perm.uri;
6550 if (!authority.equals(targetUri.getAuthority())) {
6551 continue;
6552 }
6553 List<String> targetSegments = targetUri.getPathSegments();
6554 if (targetSegments == null) {
6555 continue;
6556 }
6557 if (targetSegments.size() < NS) {
6558 continue;
6559 }
6560 for (int j=0; j<NS; j++) {
6561 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6562 continue toploop;
6563 }
6564 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006565 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006566 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006567 perm.clearModes(modeFlags);
6568 if (perm.modeFlags == 0) {
6569 it.remove();
6570 }
6571 }
6572 if (perms.size() == 0) {
6573 mGrantedUriPermissions.remove(
6574 mGrantedUriPermissions.keyAt(i));
6575 N--;
6576 i--;
6577 }
6578 }
6579 }
6580 }
6581
6582 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6583 int modeFlags) {
6584 synchronized(this) {
6585 final ProcessRecord r = getRecordForAppLocked(caller);
6586 if (r == null) {
6587 throw new SecurityException("Unable to find app for caller "
6588 + caller
6589 + " when revoking permission to uri " + uri);
6590 }
6591 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006592 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006593 return;
6594 }
6595
6596 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6597 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6598 if (modeFlags == 0) {
6599 return;
6600 }
6601
6602 final IPackageManager pm = ActivityThread.getPackageManager();
6603
6604 final String authority = uri.getAuthority();
6605 ProviderInfo pi = null;
6606 ContentProviderRecord cpr
6607 = (ContentProviderRecord)mProvidersByName.get(authority);
6608 if (cpr != null) {
6609 pi = cpr.info;
6610 } else {
6611 try {
6612 pi = pm.resolveContentProvider(authority,
6613 PackageManager.GET_URI_PERMISSION_PATTERNS);
6614 } catch (RemoteException ex) {
6615 }
6616 }
6617 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006618 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 return;
6620 }
6621
6622 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6623 }
6624 }
6625
6626 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6627 synchronized (this) {
6628 ProcessRecord app =
6629 who != null ? getRecordForAppLocked(who) : null;
6630 if (app == null) return;
6631
6632 Message msg = Message.obtain();
6633 msg.what = WAIT_FOR_DEBUGGER_MSG;
6634 msg.obj = app;
6635 msg.arg1 = waiting ? 1 : 0;
6636 mHandler.sendMessage(msg);
6637 }
6638 }
6639
6640 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6641 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006642 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006643 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006644 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006645 }
6646
6647 // =========================================================
6648 // TASK MANAGEMENT
6649 // =========================================================
6650
6651 public List getTasks(int maxNum, int flags,
6652 IThumbnailReceiver receiver) {
6653 ArrayList list = new ArrayList();
6654
6655 PendingThumbnailsRecord pending = null;
6656 IApplicationThread topThumbnail = null;
6657 HistoryRecord topRecord = null;
6658
6659 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006660 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006661 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6662 + ", receiver=" + receiver);
6663
6664 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6665 != PackageManager.PERMISSION_GRANTED) {
6666 if (receiver != null) {
6667 // If the caller wants to wait for pending thumbnails,
6668 // it ain't gonna get them.
6669 try {
6670 receiver.finished();
6671 } catch (RemoteException ex) {
6672 }
6673 }
6674 String msg = "Permission Denial: getTasks() from pid="
6675 + Binder.getCallingPid()
6676 + ", uid=" + Binder.getCallingUid()
6677 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006678 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006679 throw new SecurityException(msg);
6680 }
6681
6682 int pos = mHistory.size()-1;
6683 HistoryRecord next =
6684 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6685 HistoryRecord top = null;
6686 CharSequence topDescription = null;
6687 TaskRecord curTask = null;
6688 int numActivities = 0;
6689 int numRunning = 0;
6690 while (pos >= 0 && maxNum > 0) {
6691 final HistoryRecord r = next;
6692 pos--;
6693 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6694
6695 // Initialize state for next task if needed.
6696 if (top == null ||
6697 (top.state == ActivityState.INITIALIZING
6698 && top.task == r.task)) {
6699 top = r;
6700 topDescription = r.description;
6701 curTask = r.task;
6702 numActivities = numRunning = 0;
6703 }
6704
6705 // Add 'r' into the current task.
6706 numActivities++;
6707 if (r.app != null && r.app.thread != null) {
6708 numRunning++;
6709 }
6710 if (topDescription == null) {
6711 topDescription = r.description;
6712 }
6713
Joe Onorato8a9b2202010-02-26 18:56:32 -08006714 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 TAG, r.intent.getComponent().flattenToShortString()
6716 + ": task=" + r.task);
6717
6718 // If the next one is a different task, generate a new
6719 // TaskInfo entry for what we have.
6720 if (next == null || next.task != curTask) {
6721 ActivityManager.RunningTaskInfo ci
6722 = new ActivityManager.RunningTaskInfo();
6723 ci.id = curTask.taskId;
6724 ci.baseActivity = r.intent.getComponent();
6725 ci.topActivity = top.intent.getComponent();
6726 ci.thumbnail = top.thumbnail;
6727 ci.description = topDescription;
6728 ci.numActivities = numActivities;
6729 ci.numRunning = numRunning;
6730 //System.out.println(
6731 // "#" + maxNum + ": " + " descr=" + ci.description);
6732 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006733 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006734 TAG, "State=" + top.state + "Idle=" + top.idle
6735 + " app=" + top.app
6736 + " thr=" + (top.app != null ? top.app.thread : null));
6737 if (top.state == ActivityState.RESUMED
6738 || top.state == ActivityState.PAUSING) {
6739 if (top.idle && top.app != null
6740 && top.app.thread != null) {
6741 topRecord = top;
6742 topThumbnail = top.app.thread;
6743 } else {
6744 top.thumbnailNeeded = true;
6745 }
6746 }
6747 if (pending == null) {
6748 pending = new PendingThumbnailsRecord(receiver);
6749 }
6750 pending.pendingRecords.add(top);
6751 }
6752 list.add(ci);
6753 maxNum--;
6754 top = null;
6755 }
6756 }
6757
6758 if (pending != null) {
6759 mPendingThumbnails.add(pending);
6760 }
6761 }
6762
Joe Onorato8a9b2202010-02-26 18:56:32 -08006763 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006764
6765 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006766 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006767 try {
6768 topThumbnail.requestThumbnail(topRecord);
6769 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006770 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006771 sendPendingThumbnail(null, topRecord, null, null, true);
6772 }
6773 }
6774
6775 if (pending == null && receiver != null) {
6776 // In this case all thumbnails were available and the client
6777 // is being asked to be told when the remaining ones come in...
6778 // which is unusually, since the top-most currently running
6779 // activity should never have a canned thumbnail! Oh well.
6780 try {
6781 receiver.finished();
6782 } catch (RemoteException ex) {
6783 }
6784 }
6785
6786 return list;
6787 }
6788
6789 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6790 int flags) {
6791 synchronized (this) {
6792 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6793 "getRecentTasks()");
6794
6795 final int N = mRecentTasks.size();
6796 ArrayList<ActivityManager.RecentTaskInfo> res
6797 = new ArrayList<ActivityManager.RecentTaskInfo>(
6798 maxNum < N ? maxNum : N);
6799 for (int i=0; i<N && maxNum > 0; i++) {
6800 TaskRecord tr = mRecentTasks.get(i);
6801 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6802 || (tr.intent == null)
6803 || ((tr.intent.getFlags()
6804 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6805 ActivityManager.RecentTaskInfo rti
6806 = new ActivityManager.RecentTaskInfo();
6807 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6808 rti.baseIntent = new Intent(
6809 tr.intent != null ? tr.intent : tr.affinityIntent);
6810 rti.origActivity = tr.origActivity;
6811 res.add(rti);
6812 maxNum--;
6813 }
6814 }
6815 return res;
6816 }
6817 }
6818
6819 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6820 int j;
6821 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6822 TaskRecord jt = startTask;
6823
6824 // First look backwards
6825 for (j=startIndex-1; j>=0; j--) {
6826 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6827 if (r.task != jt) {
6828 jt = r.task;
6829 if (affinity.equals(jt.affinity)) {
6830 return j;
6831 }
6832 }
6833 }
6834
6835 // Now look forwards
6836 final int N = mHistory.size();
6837 jt = startTask;
6838 for (j=startIndex+1; j<N; j++) {
6839 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6840 if (r.task != jt) {
6841 if (affinity.equals(jt.affinity)) {
6842 return j;
6843 }
6844 jt = r.task;
6845 }
6846 }
6847
6848 // Might it be at the top?
6849 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6850 return N-1;
6851 }
6852
6853 return -1;
6854 }
6855
6856 /**
6857 * Perform a reset of the given task, if needed as part of launching it.
6858 * Returns the new HistoryRecord at the top of the task.
6859 */
6860 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6861 HistoryRecord newActivity) {
6862 boolean forceReset = (newActivity.info.flags
6863 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6864 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6865 if ((newActivity.info.flags
6866 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6867 forceReset = true;
6868 }
6869 }
6870
6871 final TaskRecord task = taskTop.task;
6872
6873 // We are going to move through the history list so that we can look
6874 // at each activity 'target' with 'below' either the interesting
6875 // activity immediately below it in the stack or null.
6876 HistoryRecord target = null;
6877 int targetI = 0;
6878 int taskTopI = -1;
6879 int replyChainEnd = -1;
6880 int lastReparentPos = -1;
6881 for (int i=mHistory.size()-1; i>=-1; i--) {
6882 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6883
6884 if (below != null && below.finishing) {
6885 continue;
6886 }
6887 if (target == null) {
6888 target = below;
6889 targetI = i;
6890 // If we were in the middle of a reply chain before this
6891 // task, it doesn't appear like the root of the chain wants
6892 // anything interesting, so drop it.
6893 replyChainEnd = -1;
6894 continue;
6895 }
6896
6897 final int flags = target.info.flags;
6898
6899 final boolean finishOnTaskLaunch =
6900 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6901 final boolean allowTaskReparenting =
6902 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6903
6904 if (target.task == task) {
6905 // We are inside of the task being reset... we'll either
6906 // finish this activity, push it out for another task,
6907 // or leave it as-is. We only do this
6908 // for activities that are not the root of the task (since
6909 // if we finish the root, we may no longer have the task!).
6910 if (taskTopI < 0) {
6911 taskTopI = targetI;
6912 }
6913 if (below != null && below.task == task) {
6914 final boolean clearWhenTaskReset =
6915 (target.intent.getFlags()
6916 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006917 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006918 // If this activity is sending a reply to a previous
6919 // activity, we can't do anything with it now until
6920 // we reach the start of the reply chain.
6921 // XXX note that we are assuming the result is always
6922 // to the previous activity, which is almost always
6923 // the case but we really shouldn't count on.
6924 if (replyChainEnd < 0) {
6925 replyChainEnd = targetI;
6926 }
Ed Heyl73798232009-03-24 21:32:21 -07006927 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006928 && target.taskAffinity != null
6929 && !target.taskAffinity.equals(task.affinity)) {
6930 // If this activity has an affinity for another
6931 // task, then we need to move it out of here. We will
6932 // move it as far out of the way as possible, to the
6933 // bottom of the activity stack. This also keeps it
6934 // correctly ordered with any activities we previously
6935 // moved.
6936 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6937 if (target.taskAffinity != null
6938 && target.taskAffinity.equals(p.task.affinity)) {
6939 // If the activity currently at the bottom has the
6940 // same task affinity as the one we are moving,
6941 // then merge it into the same task.
6942 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006943 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006944 + " out to bottom task " + p.task);
6945 } else {
6946 mCurTask++;
6947 if (mCurTask <= 0) {
6948 mCurTask = 1;
6949 }
6950 target.task = new TaskRecord(mCurTask, target.info, null,
6951 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6952 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006953 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006954 + " out to new task " + target.task);
6955 }
6956 mWindowManager.setAppGroupId(target, task.taskId);
6957 if (replyChainEnd < 0) {
6958 replyChainEnd = targetI;
6959 }
6960 int dstPos = 0;
6961 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6962 p = (HistoryRecord)mHistory.get(srcPos);
6963 if (p.finishing) {
6964 continue;
6965 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006966 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006967 + " out to target's task " + target.task);
6968 task.numActivities--;
6969 p.task = target.task;
6970 target.task.numActivities++;
6971 mHistory.remove(srcPos);
6972 mHistory.add(dstPos, p);
6973 mWindowManager.moveAppToken(dstPos, p);
6974 mWindowManager.setAppGroupId(p, p.task.taskId);
6975 dstPos++;
6976 if (VALIDATE_TOKENS) {
6977 mWindowManager.validateAppTokens(mHistory);
6978 }
6979 i++;
6980 }
6981 if (taskTop == p) {
6982 taskTop = below;
6983 }
6984 if (taskTopI == replyChainEnd) {
6985 taskTopI = -1;
6986 }
6987 replyChainEnd = -1;
6988 addRecentTask(target.task);
6989 } else if (forceReset || finishOnTaskLaunch
6990 || clearWhenTaskReset) {
6991 // If the activity should just be removed -- either
6992 // because it asks for it, or the task should be
6993 // cleared -- then finish it and anything that is
6994 // part of its reply chain.
6995 if (clearWhenTaskReset) {
6996 // In this case, we want to finish this activity
6997 // and everything above it, so be sneaky and pretend
6998 // like these are all in the reply chain.
6999 replyChainEnd = targetI+1;
7000 while (replyChainEnd < mHistory.size() &&
7001 ((HistoryRecord)mHistory.get(
7002 replyChainEnd)).task == task) {
7003 replyChainEnd++;
7004 }
7005 replyChainEnd--;
7006 } else if (replyChainEnd < 0) {
7007 replyChainEnd = targetI;
7008 }
7009 HistoryRecord p = null;
7010 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7011 p = (HistoryRecord)mHistory.get(srcPos);
7012 if (p.finishing) {
7013 continue;
7014 }
7015 if (finishActivityLocked(p, srcPos,
7016 Activity.RESULT_CANCELED, null, "reset")) {
7017 replyChainEnd--;
7018 srcPos--;
7019 }
7020 }
7021 if (taskTop == p) {
7022 taskTop = below;
7023 }
7024 if (taskTopI == replyChainEnd) {
7025 taskTopI = -1;
7026 }
7027 replyChainEnd = -1;
7028 } else {
7029 // If we were in the middle of a chain, well the
7030 // activity that started it all doesn't want anything
7031 // special, so leave it all as-is.
7032 replyChainEnd = -1;
7033 }
7034 } else {
7035 // Reached the bottom of the task -- any reply chain
7036 // should be left as-is.
7037 replyChainEnd = -1;
7038 }
7039
7040 } else if (target.resultTo != null) {
7041 // If this activity is sending a reply to a previous
7042 // activity, we can't do anything with it now until
7043 // we reach the start of the reply chain.
7044 // XXX note that we are assuming the result is always
7045 // to the previous activity, which is almost always
7046 // the case but we really shouldn't count on.
7047 if (replyChainEnd < 0) {
7048 replyChainEnd = targetI;
7049 }
7050
7051 } else if (taskTopI >= 0 && allowTaskReparenting
7052 && task.affinity != null
7053 && task.affinity.equals(target.taskAffinity)) {
7054 // We are inside of another task... if this activity has
7055 // an affinity for our task, then either remove it if we are
7056 // clearing or move it over to our task. Note that
7057 // we currently punt on the case where we are resetting a
7058 // task that is not at the top but who has activities above
7059 // with an affinity to it... this is really not a normal
7060 // case, and we will need to later pull that task to the front
7061 // and usually at that point we will do the reset and pick
7062 // up those remaining activities. (This only happens if
7063 // someone starts an activity in a new task from an activity
7064 // in a task that is not currently on top.)
7065 if (forceReset || finishOnTaskLaunch) {
7066 if (replyChainEnd < 0) {
7067 replyChainEnd = targetI;
7068 }
7069 HistoryRecord p = null;
7070 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7071 p = (HistoryRecord)mHistory.get(srcPos);
7072 if (p.finishing) {
7073 continue;
7074 }
7075 if (finishActivityLocked(p, srcPos,
7076 Activity.RESULT_CANCELED, null, "reset")) {
7077 taskTopI--;
7078 lastReparentPos--;
7079 replyChainEnd--;
7080 srcPos--;
7081 }
7082 }
7083 replyChainEnd = -1;
7084 } else {
7085 if (replyChainEnd < 0) {
7086 replyChainEnd = targetI;
7087 }
7088 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7089 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7090 if (p.finishing) {
7091 continue;
7092 }
7093 if (lastReparentPos < 0) {
7094 lastReparentPos = taskTopI;
7095 taskTop = p;
7096 } else {
7097 lastReparentPos--;
7098 }
7099 mHistory.remove(srcPos);
7100 p.task.numActivities--;
7101 p.task = task;
7102 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007103 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007104 + " in to resetting task " + task);
7105 task.numActivities++;
7106 mWindowManager.moveAppToken(lastReparentPos, p);
7107 mWindowManager.setAppGroupId(p, p.task.taskId);
7108 if (VALIDATE_TOKENS) {
7109 mWindowManager.validateAppTokens(mHistory);
7110 }
7111 }
7112 replyChainEnd = -1;
7113
7114 // Now we've moved it in to place... but what if this is
7115 // a singleTop activity and we have put it on top of another
7116 // instance of the same activity? Then we drop the instance
7117 // below so it remains singleTop.
7118 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7119 for (int j=lastReparentPos-1; j>=0; j--) {
7120 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7121 if (p.finishing) {
7122 continue;
7123 }
7124 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7125 if (finishActivityLocked(p, j,
7126 Activity.RESULT_CANCELED, null, "replace")) {
7127 taskTopI--;
7128 lastReparentPos--;
7129 }
7130 }
7131 }
7132 }
7133 }
7134 }
7135
7136 target = below;
7137 targetI = i;
7138 }
7139
7140 return taskTop;
7141 }
7142
7143 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007144 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007145 */
7146 public void moveTaskToFront(int task) {
7147 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7148 "moveTaskToFront()");
7149
7150 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007151 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7152 Binder.getCallingUid(), "Task to front")) {
7153 return;
7154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007155 final long origId = Binder.clearCallingIdentity();
7156 try {
7157 int N = mRecentTasks.size();
7158 for (int i=0; i<N; i++) {
7159 TaskRecord tr = mRecentTasks.get(i);
7160 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007161 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007162 return;
7163 }
7164 }
7165 for (int i=mHistory.size()-1; i>=0; i--) {
7166 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7167 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007168 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007169 return;
7170 }
7171 }
7172 } finally {
7173 Binder.restoreCallingIdentity(origId);
7174 }
7175 }
7176 }
7177
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007178 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007179 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180
7181 final int task = tr.taskId;
7182 int top = mHistory.size()-1;
7183
7184 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7185 // nothing to do!
7186 return;
7187 }
7188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007189 ArrayList moved = new ArrayList();
7190
7191 // Applying the affinities may have removed entries from the history,
7192 // so get the size again.
7193 top = mHistory.size()-1;
7194 int pos = top;
7195
7196 // Shift all activities with this task up to the top
7197 // of the stack, keeping them in the same internal order.
7198 while (pos >= 0) {
7199 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007200 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007201 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7202 boolean first = true;
7203 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007204 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007205 mHistory.remove(pos);
7206 mHistory.add(top, r);
7207 moved.add(0, r);
7208 top--;
7209 if (first) {
7210 addRecentTask(r.task);
7211 first = false;
7212 }
7213 }
7214 pos--;
7215 }
7216
Joe Onorato8a9b2202010-02-26 18:56:32 -08007217 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007218 "Prepare to front transition: task=" + tr);
7219 if (reason != null &&
7220 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7221 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7222 HistoryRecord r = topRunningActivityLocked(null);
7223 if (r != null) {
7224 mNoAnimActivities.add(r);
7225 }
7226 } else {
7227 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7228 }
7229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007230 mWindowManager.moveAppTokensToTop(moved);
7231 if (VALIDATE_TOKENS) {
7232 mWindowManager.validateAppTokens(mHistory);
7233 }
7234
7235 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007236 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007237 }
7238
7239 private final void finishTaskMove(int task) {
7240 resumeTopActivityLocked(null);
7241 }
7242
7243 public void moveTaskToBack(int task) {
7244 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7245 "moveTaskToBack()");
7246
7247 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007248 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7249 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7250 Binder.getCallingUid(), "Task to back")) {
7251 return;
7252 }
7253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007254 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007255 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007256 Binder.restoreCallingIdentity(origId);
7257 }
7258 }
7259
7260 /**
7261 * Moves an activity, and all of the other activities within the same task, to the bottom
7262 * of the history stack. The activity's order within the task is unchanged.
7263 *
7264 * @param token A reference to the activity we wish to move
7265 * @param nonRoot If false then this only works if the activity is the root
7266 * of a task; if true it will work for any activity in a task.
7267 * @return Returns true if the move completed, false if not.
7268 */
7269 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7270 synchronized(this) {
7271 final long origId = Binder.clearCallingIdentity();
7272 int taskId = getTaskForActivityLocked(token, !nonRoot);
7273 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007274 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275 }
7276 Binder.restoreCallingIdentity(origId);
7277 }
7278 return false;
7279 }
7280
7281 /**
7282 * Worker method for rearranging history stack. Implements the function of moving all
7283 * activities for a specific task (gathering them if disjoint) into a single group at the
7284 * bottom of the stack.
7285 *
7286 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7287 * to premeptively cancel the move.
7288 *
7289 * @param task The taskId to collect and move to the bottom.
7290 * @return Returns true if the move completed, false if not.
7291 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007292 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007293 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007294
7295 // If we have a watcher, preflight the move before committing to it. First check
7296 // for *other* available tasks, but if none are available, then try again allowing the
7297 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007298 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 HistoryRecord next = topRunningActivityLocked(null, task);
7300 if (next == null) {
7301 next = topRunningActivityLocked(null, 0);
7302 }
7303 if (next != null) {
7304 // ask watcher if this is allowed
7305 boolean moveOK = true;
7306 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007307 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007309 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007310 }
7311 if (!moveOK) {
7312 return false;
7313 }
7314 }
7315 }
7316
7317 ArrayList moved = new ArrayList();
7318
Joe Onorato8a9b2202010-02-26 18:56:32 -08007319 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007321
7322 final int N = mHistory.size();
7323 int bottom = 0;
7324 int pos = 0;
7325
7326 // Shift all activities with this task down to the bottom
7327 // of the stack, keeping them in the same internal order.
7328 while (pos < N) {
7329 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007330 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007331 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7332 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007333 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007334 mHistory.remove(pos);
7335 mHistory.add(bottom, r);
7336 moved.add(r);
7337 bottom++;
7338 }
7339 pos++;
7340 }
7341
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007342 if (reason != null &&
7343 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7344 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7345 HistoryRecord r = topRunningActivityLocked(null);
7346 if (r != null) {
7347 mNoAnimActivities.add(r);
7348 }
7349 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007350 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352 mWindowManager.moveAppTokensToBottom(moved);
7353 if (VALIDATE_TOKENS) {
7354 mWindowManager.validateAppTokens(mHistory);
7355 }
7356
7357 finishTaskMove(task);
7358 return true;
7359 }
7360
7361 public void moveTaskBackwards(int task) {
7362 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7363 "moveTaskBackwards()");
7364
7365 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007366 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7367 Binder.getCallingUid(), "Task backwards")) {
7368 return;
7369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007370 final long origId = Binder.clearCallingIdentity();
7371 moveTaskBackwardsLocked(task);
7372 Binder.restoreCallingIdentity(origId);
7373 }
7374 }
7375
7376 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007377 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 }
7379
7380 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7381 synchronized(this) {
7382 return getTaskForActivityLocked(token, onlyRoot);
7383 }
7384 }
7385
7386 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7387 final int N = mHistory.size();
7388 TaskRecord lastTask = null;
7389 for (int i=0; i<N; i++) {
7390 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7391 if (r == token) {
7392 if (!onlyRoot || lastTask != r.task) {
7393 return r.task.taskId;
7394 }
7395 return -1;
7396 }
7397 lastTask = r.task;
7398 }
7399
7400 return -1;
7401 }
7402
7403 /**
7404 * Returns the top activity in any existing task matching the given
7405 * Intent. Returns null if no such task is found.
7406 */
7407 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7408 ComponentName cls = intent.getComponent();
7409 if (info.targetActivity != null) {
7410 cls = new ComponentName(info.packageName, info.targetActivity);
7411 }
7412
7413 TaskRecord cp = null;
7414
7415 final int N = mHistory.size();
7416 for (int i=(N-1); i>=0; i--) {
7417 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7418 if (!r.finishing && r.task != cp
7419 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7420 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007421 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007422 // + "/aff=" + r.task.affinity + " to new cls="
7423 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7424 if (r.task.affinity != null) {
7425 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007426 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 return r;
7428 }
7429 } else if (r.task.intent != null
7430 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007431 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007433 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434 return r;
7435 } else if (r.task.affinityIntent != null
7436 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007437 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007439 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 return r;
7441 }
7442 }
7443 }
7444
7445 return null;
7446 }
7447
7448 /**
7449 * Returns the first activity (starting from the top of the stack) that
7450 * is the same as the given activity. Returns null if no such activity
7451 * is found.
7452 */
7453 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7454 ComponentName cls = intent.getComponent();
7455 if (info.targetActivity != null) {
7456 cls = new ComponentName(info.packageName, info.targetActivity);
7457 }
7458
7459 final int N = mHistory.size();
7460 for (int i=(N-1); i>=0; i--) {
7461 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7462 if (!r.finishing) {
7463 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007464 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007466 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007467 return r;
7468 }
7469 }
7470 }
7471
7472 return null;
7473 }
7474
7475 public void finishOtherInstances(IBinder token, ComponentName className) {
7476 synchronized(this) {
7477 final long origId = Binder.clearCallingIdentity();
7478
7479 int N = mHistory.size();
7480 TaskRecord lastTask = null;
7481 for (int i=0; i<N; i++) {
7482 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7483 if (r.realActivity.equals(className)
7484 && r != token && lastTask != r.task) {
7485 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7486 null, "others")) {
7487 i--;
7488 N--;
7489 }
7490 }
7491 lastTask = r.task;
7492 }
7493
7494 Binder.restoreCallingIdentity(origId);
7495 }
7496 }
7497
7498 // =========================================================
7499 // THUMBNAILS
7500 // =========================================================
7501
7502 public void reportThumbnail(IBinder token,
7503 Bitmap thumbnail, CharSequence description) {
7504 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7505 final long origId = Binder.clearCallingIdentity();
7506 sendPendingThumbnail(null, token, thumbnail, description, true);
7507 Binder.restoreCallingIdentity(origId);
7508 }
7509
7510 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7511 Bitmap thumbnail, CharSequence description, boolean always) {
7512 TaskRecord task = null;
7513 ArrayList receivers = null;
7514
7515 //System.out.println("Send pending thumbnail: " + r);
7516
7517 synchronized(this) {
7518 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007519 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007520 if (index < 0) {
7521 return;
7522 }
7523 r = (HistoryRecord)mHistory.get(index);
7524 }
7525 if (thumbnail == null) {
7526 thumbnail = r.thumbnail;
7527 description = r.description;
7528 }
7529 if (thumbnail == null && !always) {
7530 // If there is no thumbnail, and this entry is not actually
7531 // going away, then abort for now and pick up the next
7532 // thumbnail we get.
7533 return;
7534 }
7535 task = r.task;
7536
7537 int N = mPendingThumbnails.size();
7538 int i=0;
7539 while (i<N) {
7540 PendingThumbnailsRecord pr =
7541 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7542 //System.out.println("Looking in " + pr.pendingRecords);
7543 if (pr.pendingRecords.remove(r)) {
7544 if (receivers == null) {
7545 receivers = new ArrayList();
7546 }
7547 receivers.add(pr);
7548 if (pr.pendingRecords.size() == 0) {
7549 pr.finished = true;
7550 mPendingThumbnails.remove(i);
7551 N--;
7552 continue;
7553 }
7554 }
7555 i++;
7556 }
7557 }
7558
7559 if (receivers != null) {
7560 final int N = receivers.size();
7561 for (int i=0; i<N; i++) {
7562 try {
7563 PendingThumbnailsRecord pr =
7564 (PendingThumbnailsRecord)receivers.get(i);
7565 pr.receiver.newThumbnail(
7566 task != null ? task.taskId : -1, thumbnail, description);
7567 if (pr.finished) {
7568 pr.receiver.finished();
7569 }
7570 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007571 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007572 }
7573 }
7574 }
7575 }
7576
7577 // =========================================================
7578 // CONTENT PROVIDERS
7579 // =========================================================
7580
7581 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7582 List providers = null;
7583 try {
7584 providers = ActivityThread.getPackageManager().
7585 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007586 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007587 } catch (RemoteException ex) {
7588 }
7589 if (providers != null) {
7590 final int N = providers.size();
7591 for (int i=0; i<N; i++) {
7592 ProviderInfo cpi =
7593 (ProviderInfo)providers.get(i);
7594 ContentProviderRecord cpr =
7595 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7596 if (cpr == null) {
7597 cpr = new ContentProviderRecord(cpi, app.info);
7598 mProvidersByClass.put(cpi.name, cpr);
7599 }
7600 app.pubProviders.put(cpi.name, cpr);
7601 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007602 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 }
7604 }
7605 return providers;
7606 }
7607
7608 private final String checkContentProviderPermissionLocked(
7609 ProviderInfo cpi, ProcessRecord r, int mode) {
7610 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7611 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7612 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7613 cpi.exported ? -1 : cpi.applicationInfo.uid)
7614 == PackageManager.PERMISSION_GRANTED
7615 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7616 return null;
7617 }
7618 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7619 cpi.exported ? -1 : cpi.applicationInfo.uid)
7620 == PackageManager.PERMISSION_GRANTED) {
7621 return null;
7622 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007623
7624 PathPermission[] pps = cpi.pathPermissions;
7625 if (pps != null) {
7626 int i = pps.length;
7627 while (i > 0) {
7628 i--;
7629 PathPermission pp = pps[i];
7630 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7631 cpi.exported ? -1 : cpi.applicationInfo.uid)
7632 == PackageManager.PERMISSION_GRANTED
7633 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7634 return null;
7635 }
7636 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7637 cpi.exported ? -1 : cpi.applicationInfo.uid)
7638 == PackageManager.PERMISSION_GRANTED) {
7639 return null;
7640 }
7641 }
7642 }
7643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007644 String msg = "Permission Denial: opening provider " + cpi.name
7645 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7646 + ", uid=" + callingUid + ") requires "
7647 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007648 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007649 return msg;
7650 }
7651
7652 private final ContentProviderHolder getContentProviderImpl(
7653 IApplicationThread caller, String name) {
7654 ContentProviderRecord cpr;
7655 ProviderInfo cpi = null;
7656
7657 synchronized(this) {
7658 ProcessRecord r = null;
7659 if (caller != null) {
7660 r = getRecordForAppLocked(caller);
7661 if (r == null) {
7662 throw new SecurityException(
7663 "Unable to find app for caller " + caller
7664 + " (pid=" + Binder.getCallingPid()
7665 + ") when getting content provider " + name);
7666 }
7667 }
7668
7669 // First check if this content provider has been published...
7670 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7671 if (cpr != null) {
7672 cpi = cpr.info;
7673 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7674 return new ContentProviderHolder(cpi,
7675 cpi.readPermission != null
7676 ? cpi.readPermission : cpi.writePermission);
7677 }
7678
7679 if (r != null && cpr.canRunHere(r)) {
7680 // This provider has been published or is in the process
7681 // of being published... but it is also allowed to run
7682 // in the caller's process, so don't make a connection
7683 // and just let the caller instantiate its own instance.
7684 if (cpr.provider != null) {
7685 // don't give caller the provider object, it needs
7686 // to make its own.
7687 cpr = new ContentProviderRecord(cpr);
7688 }
7689 return cpr;
7690 }
7691
7692 final long origId = Binder.clearCallingIdentity();
7693
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007694 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007695 // return it right away.
7696 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007697 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007698 "Adding provider requested by "
7699 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007700 + cpr.info.processName);
7701 Integer cnt = r.conProviders.get(cpr);
7702 if (cnt == null) {
7703 r.conProviders.put(cpr, new Integer(1));
7704 } else {
7705 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007707 cpr.clients.add(r);
7708 } else {
7709 cpr.externals++;
7710 }
7711
7712 if (cpr.app != null) {
7713 updateOomAdjLocked(cpr.app);
7714 }
7715
7716 Binder.restoreCallingIdentity(origId);
7717
7718 } else {
7719 try {
7720 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007721 resolveContentProvider(name,
7722 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007723 } catch (RemoteException ex) {
7724 }
7725 if (cpi == null) {
7726 return null;
7727 }
7728
7729 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7730 return new ContentProviderHolder(cpi,
7731 cpi.readPermission != null
7732 ? cpi.readPermission : cpi.writePermission);
7733 }
7734
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007735 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7736 && !cpi.processName.equals("system")) {
7737 // If this content provider does not run in the system
7738 // process, and the system is not yet ready to run other
7739 // processes, then fail fast instead of hanging.
7740 throw new IllegalArgumentException(
7741 "Attempt to launch content provider before system ready");
7742 }
7743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007744 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7745 final boolean firstClass = cpr == null;
7746 if (firstClass) {
7747 try {
7748 ApplicationInfo ai =
7749 ActivityThread.getPackageManager().
7750 getApplicationInfo(
7751 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007752 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007753 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007754 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007755 + cpi.name);
7756 return null;
7757 }
7758 cpr = new ContentProviderRecord(cpi, ai);
7759 } catch (RemoteException ex) {
7760 // pm is in same process, this will never happen.
7761 }
7762 }
7763
7764 if (r != null && cpr.canRunHere(r)) {
7765 // If this is a multiprocess provider, then just return its
7766 // info and allow the caller to instantiate it. Only do
7767 // this if the provider is the same user as the caller's
7768 // process, or can run as root (so can be in any process).
7769 return cpr;
7770 }
7771
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007772 if (DEBUG_PROVIDER) {
7773 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007774 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007775 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007776 }
7777
7778 // This is single process, and our app is now connecting to it.
7779 // See if we are already in the process of launching this
7780 // provider.
7781 final int N = mLaunchingProviders.size();
7782 int i;
7783 for (i=0; i<N; i++) {
7784 if (mLaunchingProviders.get(i) == cpr) {
7785 break;
7786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007787 }
7788
7789 // If the provider is not already being launched, then get it
7790 // started.
7791 if (i >= N) {
7792 final long origId = Binder.clearCallingIdentity();
7793 ProcessRecord proc = startProcessLocked(cpi.processName,
7794 cpr.appInfo, false, 0, "content provider",
7795 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007796 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007798 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 + cpi.applicationInfo.packageName + "/"
7800 + cpi.applicationInfo.uid + " for provider "
7801 + name + ": process is bad");
7802 return null;
7803 }
7804 cpr.launchingApp = proc;
7805 mLaunchingProviders.add(cpr);
7806 Binder.restoreCallingIdentity(origId);
7807 }
7808
7809 // Make sure the provider is published (the same provider class
7810 // may be published under multiple names).
7811 if (firstClass) {
7812 mProvidersByClass.put(cpi.name, cpr);
7813 }
7814 mProvidersByName.put(name, cpr);
7815
7816 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007817 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007818 "Adding provider requested by "
7819 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007820 + cpr.info.processName);
7821 Integer cnt = r.conProviders.get(cpr);
7822 if (cnt == null) {
7823 r.conProviders.put(cpr, new Integer(1));
7824 } else {
7825 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7826 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007827 cpr.clients.add(r);
7828 } else {
7829 cpr.externals++;
7830 }
7831 }
7832 }
7833
7834 // Wait for the provider to be published...
7835 synchronized (cpr) {
7836 while (cpr.provider == null) {
7837 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007838 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007839 + cpi.applicationInfo.packageName + "/"
7840 + cpi.applicationInfo.uid + " for provider "
7841 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007842 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007843 cpi.applicationInfo.packageName,
7844 cpi.applicationInfo.uid, name);
7845 return null;
7846 }
7847 try {
7848 cpr.wait();
7849 } catch (InterruptedException ex) {
7850 }
7851 }
7852 }
7853 return cpr;
7854 }
7855
7856 public final ContentProviderHolder getContentProvider(
7857 IApplicationThread caller, String name) {
7858 if (caller == null) {
7859 String msg = "null IApplicationThread when getting content provider "
7860 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007861 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 throw new SecurityException(msg);
7863 }
7864
7865 return getContentProviderImpl(caller, name);
7866 }
7867
7868 private ContentProviderHolder getContentProviderExternal(String name) {
7869 return getContentProviderImpl(null, name);
7870 }
7871
7872 /**
7873 * Drop a content provider from a ProcessRecord's bookkeeping
7874 * @param cpr
7875 */
7876 public void removeContentProvider(IApplicationThread caller, String name) {
7877 synchronized (this) {
7878 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7879 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007880 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007881 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007882 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007883 return;
7884 }
7885 final ProcessRecord r = getRecordForAppLocked(caller);
7886 if (r == null) {
7887 throw new SecurityException(
7888 "Unable to find app for caller " + caller +
7889 " when removing content provider " + name);
7890 }
7891 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007892 ContentProviderRecord localCpr = (ContentProviderRecord)
7893 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007894 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007895 + r.info.processName + " from process "
7896 + localCpr.appInfo.processName);
7897 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007898 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007899 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007900 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 return;
7902 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007903 Integer cnt = r.conProviders.get(localCpr);
7904 if (cnt == null || cnt.intValue() <= 1) {
7905 localCpr.clients.remove(r);
7906 r.conProviders.remove(localCpr);
7907 } else {
7908 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007910 }
7911 updateOomAdjLocked();
7912 }
7913 }
7914
7915 private void removeContentProviderExternal(String name) {
7916 synchronized (this) {
7917 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7918 if(cpr == null) {
7919 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007920 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007921 return;
7922 }
7923
7924 //update content provider record entry info
7925 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7926 localCpr.externals--;
7927 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007928 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007929 }
7930 updateOomAdjLocked();
7931 }
7932 }
7933
7934 public final void publishContentProviders(IApplicationThread caller,
7935 List<ContentProviderHolder> providers) {
7936 if (providers == null) {
7937 return;
7938 }
7939
7940 synchronized(this) {
7941 final ProcessRecord r = getRecordForAppLocked(caller);
7942 if (r == null) {
7943 throw new SecurityException(
7944 "Unable to find app for caller " + caller
7945 + " (pid=" + Binder.getCallingPid()
7946 + ") when publishing content providers");
7947 }
7948
7949 final long origId = Binder.clearCallingIdentity();
7950
7951 final int N = providers.size();
7952 for (int i=0; i<N; i++) {
7953 ContentProviderHolder src = providers.get(i);
7954 if (src == null || src.info == null || src.provider == null) {
7955 continue;
7956 }
7957 ContentProviderRecord dst =
7958 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7959 if (dst != null) {
7960 mProvidersByClass.put(dst.info.name, dst);
7961 String names[] = dst.info.authority.split(";");
7962 for (int j = 0; j < names.length; j++) {
7963 mProvidersByName.put(names[j], dst);
7964 }
7965
7966 int NL = mLaunchingProviders.size();
7967 int j;
7968 for (j=0; j<NL; j++) {
7969 if (mLaunchingProviders.get(j) == dst) {
7970 mLaunchingProviders.remove(j);
7971 j--;
7972 NL--;
7973 }
7974 }
7975 synchronized (dst) {
7976 dst.provider = src.provider;
7977 dst.app = r;
7978 dst.notifyAll();
7979 }
7980 updateOomAdjLocked(r);
7981 }
7982 }
7983
7984 Binder.restoreCallingIdentity(origId);
7985 }
7986 }
7987
7988 public static final void installSystemProviders() {
7989 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7990 List providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007991 if (providers != null) {
7992 for (int i=providers.size()-1; i>=0; i--) {
7993 ProviderInfo pi = (ProviderInfo)providers.get(i);
7994 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007995 Slog.w(TAG, "Not installing system proc provider " + pi.name
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007996 + ": not system .apk");
7997 providers.remove(i);
7998 }
7999 }
8000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008001 mSystemThread.installSystemProviders(providers);
8002 }
8003
8004 // =========================================================
8005 // GLOBAL MANAGEMENT
8006 // =========================================================
8007
8008 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8009 ApplicationInfo info, String customProcess) {
8010 String proc = customProcess != null ? customProcess : info.processName;
8011 BatteryStatsImpl.Uid.Proc ps = null;
8012 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8013 synchronized (stats) {
8014 ps = stats.getProcessStatsLocked(info.uid, proc);
8015 }
8016 return new ProcessRecord(ps, thread, info, proc);
8017 }
8018
8019 final ProcessRecord addAppLocked(ApplicationInfo info) {
8020 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8021
8022 if (app == null) {
8023 app = newProcessRecordLocked(null, info, null);
8024 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008025 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008026 }
8027
8028 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8029 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8030 app.persistent = true;
8031 app.maxAdj = CORE_SERVER_ADJ;
8032 }
8033 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8034 mPersistentStartingProcesses.add(app);
8035 startProcessLocked(app, "added application", app.processName);
8036 }
8037
8038 return app;
8039 }
8040
8041 public void unhandledBack() {
8042 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8043 "unhandledBack()");
8044
8045 synchronized(this) {
8046 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008047 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 TAG, "Performing unhandledBack(): stack size = " + count);
8049 if (count > 1) {
8050 final long origId = Binder.clearCallingIdentity();
8051 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8052 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8053 Binder.restoreCallingIdentity(origId);
8054 }
8055 }
8056 }
8057
8058 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8059 String name = uri.getAuthority();
8060 ContentProviderHolder cph = getContentProviderExternal(name);
8061 ParcelFileDescriptor pfd = null;
8062 if (cph != null) {
8063 // We record the binder invoker's uid in thread-local storage before
8064 // going to the content provider to open the file. Later, in the code
8065 // that handles all permissions checks, we look for this uid and use
8066 // that rather than the Activity Manager's own uid. The effect is that
8067 // we do the check against the caller's permissions even though it looks
8068 // to the content provider like the Activity Manager itself is making
8069 // the request.
8070 sCallerIdentity.set(new Identity(
8071 Binder.getCallingPid(), Binder.getCallingUid()));
8072 try {
8073 pfd = cph.provider.openFile(uri, "r");
8074 } catch (FileNotFoundException e) {
8075 // do nothing; pfd will be returned null
8076 } finally {
8077 // Ensure that whatever happens, we clean up the identity state
8078 sCallerIdentity.remove();
8079 }
8080
8081 // We've got the fd now, so we're done with the provider.
8082 removeContentProviderExternal(name);
8083 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008084 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008085 }
8086 return pfd;
8087 }
8088
8089 public void goingToSleep() {
8090 synchronized(this) {
8091 mSleeping = true;
8092 mWindowManager.setEventDispatching(false);
8093
8094 if (mResumedActivity != null) {
8095 pauseIfSleepingLocked();
8096 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008097 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008098 }
8099 }
8100 }
8101
Dianne Hackborn55280a92009-05-07 15:53:46 -07008102 public boolean shutdown(int timeout) {
8103 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8104 != PackageManager.PERMISSION_GRANTED) {
8105 throw new SecurityException("Requires permission "
8106 + android.Manifest.permission.SHUTDOWN);
8107 }
8108
8109 boolean timedout = false;
8110
8111 synchronized(this) {
8112 mShuttingDown = true;
8113 mWindowManager.setEventDispatching(false);
8114
8115 if (mResumedActivity != null) {
8116 pauseIfSleepingLocked();
8117 final long endTime = System.currentTimeMillis() + timeout;
8118 while (mResumedActivity != null || mPausingActivity != null) {
8119 long delay = endTime - System.currentTimeMillis();
8120 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008121 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008122 timedout = true;
8123 break;
8124 }
8125 try {
8126 this.wait();
8127 } catch (InterruptedException e) {
8128 }
8129 }
8130 }
8131 }
8132
8133 mUsageStatsService.shutdown();
8134 mBatteryStatsService.shutdown();
8135
8136 return timedout;
8137 }
8138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008140 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008141 if (!mGoingToSleep.isHeld()) {
8142 mGoingToSleep.acquire();
8143 if (mLaunchingActivity.isHeld()) {
8144 mLaunchingActivity.release();
8145 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8146 }
8147 }
8148
8149 // If we are not currently pausing an activity, get the current
8150 // one to pause. If we are pausing one, we will just let that stuff
8151 // run and release the wake lock when all done.
8152 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008153 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8154 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008155 startPausingLocked(false, true);
8156 }
8157 }
8158 }
8159
8160 public void wakingUp() {
8161 synchronized(this) {
8162 if (mGoingToSleep.isHeld()) {
8163 mGoingToSleep.release();
8164 }
8165 mWindowManager.setEventDispatching(true);
8166 mSleeping = false;
8167 resumeTopActivityLocked(null);
8168 }
8169 }
8170
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008171 public void stopAppSwitches() {
8172 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8173 != PackageManager.PERMISSION_GRANTED) {
8174 throw new SecurityException("Requires permission "
8175 + android.Manifest.permission.STOP_APP_SWITCHES);
8176 }
8177
8178 synchronized(this) {
8179 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8180 + APP_SWITCH_DELAY_TIME;
8181 mDidAppSwitch = false;
8182 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8183 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8184 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8185 }
8186 }
8187
8188 public void resumeAppSwitches() {
8189 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8190 != PackageManager.PERMISSION_GRANTED) {
8191 throw new SecurityException("Requires permission "
8192 + android.Manifest.permission.STOP_APP_SWITCHES);
8193 }
8194
8195 synchronized(this) {
8196 // Note that we don't execute any pending app switches... we will
8197 // let those wait until either the timeout, or the next start
8198 // activity request.
8199 mAppSwitchesAllowedTime = 0;
8200 }
8201 }
8202
8203 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8204 String name) {
8205 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8206 return true;
8207 }
8208
8209 final int perm = checkComponentPermission(
8210 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8211 callingUid, -1);
8212 if (perm == PackageManager.PERMISSION_GRANTED) {
8213 return true;
8214 }
8215
Joe Onorato8a9b2202010-02-26 18:56:32 -08008216 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008217 return false;
8218 }
8219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008220 public void setDebugApp(String packageName, boolean waitForDebugger,
8221 boolean persistent) {
8222 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8223 "setDebugApp()");
8224
8225 // Note that this is not really thread safe if there are multiple
8226 // callers into it at the same time, but that's not a situation we
8227 // care about.
8228 if (persistent) {
8229 final ContentResolver resolver = mContext.getContentResolver();
8230 Settings.System.putString(
8231 resolver, Settings.System.DEBUG_APP,
8232 packageName);
8233 Settings.System.putInt(
8234 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8235 waitForDebugger ? 1 : 0);
8236 }
8237
8238 synchronized (this) {
8239 if (!persistent) {
8240 mOrigDebugApp = mDebugApp;
8241 mOrigWaitForDebugger = mWaitForDebugger;
8242 }
8243 mDebugApp = packageName;
8244 mWaitForDebugger = waitForDebugger;
8245 mDebugTransient = !persistent;
8246 if (packageName != null) {
8247 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008248 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008249 Binder.restoreCallingIdentity(origId);
8250 }
8251 }
8252 }
8253
8254 public void setAlwaysFinish(boolean enabled) {
8255 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8256 "setAlwaysFinish()");
8257
8258 Settings.System.putInt(
8259 mContext.getContentResolver(),
8260 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8261
8262 synchronized (this) {
8263 mAlwaysFinishActivities = enabled;
8264 }
8265 }
8266
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008267 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008269 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008271 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008272 }
8273 }
8274
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008275 public boolean isUserAMonkey() {
8276 // For now the fact that there is a controller implies
8277 // we have a monkey.
8278 synchronized (this) {
8279 return mController != null;
8280 }
8281 }
8282
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008283 public void registerActivityWatcher(IActivityWatcher watcher) {
8284 mWatchers.register(watcher);
8285 }
8286
8287 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8288 mWatchers.unregister(watcher);
8289 }
8290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008291 public final void enterSafeMode() {
8292 synchronized(this) {
8293 // It only makes sense to do this before the system is ready
8294 // and started launching other packages.
8295 if (!mSystemReady) {
8296 try {
8297 ActivityThread.getPackageManager().enterSafeMode();
8298 } catch (RemoteException e) {
8299 }
8300
8301 View v = LayoutInflater.from(mContext).inflate(
8302 com.android.internal.R.layout.safe_mode, null);
8303 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8304 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8305 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8306 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8307 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8308 lp.format = v.getBackground().getOpacity();
8309 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8310 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8311 ((WindowManager)mContext.getSystemService(
8312 Context.WINDOW_SERVICE)).addView(v, lp);
8313 }
8314 }
8315 }
8316
8317 public void noteWakeupAlarm(IIntentSender sender) {
8318 if (!(sender instanceof PendingIntentRecord)) {
8319 return;
8320 }
8321 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8322 synchronized (stats) {
8323 if (mBatteryStatsService.isOnBattery()) {
8324 mBatteryStatsService.enforceCallingPermission();
8325 PendingIntentRecord rec = (PendingIntentRecord)sender;
8326 int MY_UID = Binder.getCallingUid();
8327 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8328 BatteryStatsImpl.Uid.Pkg pkg =
8329 stats.getPackageStatsLocked(uid, rec.key.packageName);
8330 pkg.incWakeupsLocked();
8331 }
8332 }
8333 }
8334
8335 public boolean killPidsForMemory(int[] pids) {
8336 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8337 throw new SecurityException("killPidsForMemory only available to the system");
8338 }
8339
8340 // XXX Note: don't acquire main activity lock here, because the window
8341 // manager calls in with its locks held.
8342
8343 boolean killed = false;
8344 synchronized (mPidsSelfLocked) {
8345 int[] types = new int[pids.length];
8346 int worstType = 0;
8347 for (int i=0; i<pids.length; i++) {
8348 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8349 if (proc != null) {
8350 int type = proc.setAdj;
8351 types[i] = type;
8352 if (type > worstType) {
8353 worstType = type;
8354 }
8355 }
8356 }
8357
8358 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8359 // then constrain it so we will kill all hidden procs.
8360 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8361 worstType = HIDDEN_APP_MIN_ADJ;
8362 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008363 Slog.w(TAG, "Killing processes for memory at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008364 for (int i=0; i<pids.length; i++) {
8365 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8366 if (proc == null) {
8367 continue;
8368 }
8369 int adj = proc.setAdj;
8370 if (adj >= worstType) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008371 Slog.w(TAG, "Killing for memory: " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008372 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008373 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008374 proc.processName, adj);
8375 killed = true;
8376 Process.killProcess(pids[i]);
8377 }
8378 }
8379 }
8380 return killed;
8381 }
8382
8383 public void reportPss(IApplicationThread caller, int pss) {
8384 Watchdog.PssRequestor req;
8385 String name;
8386 ProcessRecord callerApp;
8387 synchronized (this) {
8388 if (caller == null) {
8389 return;
8390 }
8391 callerApp = getRecordForAppLocked(caller);
8392 if (callerApp == null) {
8393 return;
8394 }
8395 callerApp.lastPss = pss;
8396 req = callerApp;
8397 name = callerApp.processName;
8398 }
8399 Watchdog.getInstance().reportPss(req, name, pss);
8400 if (!callerApp.persistent) {
8401 removeRequestedPss(callerApp);
8402 }
8403 }
8404
8405 public void requestPss(Runnable completeCallback) {
8406 ArrayList<ProcessRecord> procs;
8407 synchronized (this) {
8408 mRequestPssCallback = completeCallback;
8409 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008410 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8411 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008412 if (!proc.persistent) {
8413 mRequestPssList.add(proc);
8414 }
8415 }
8416 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8417 }
8418
8419 int oldPri = Process.getThreadPriority(Process.myTid());
8420 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8421 for (int i=procs.size()-1; i>=0; i--) {
8422 ProcessRecord proc = procs.get(i);
8423 proc.lastPss = 0;
8424 proc.requestPss();
8425 }
8426 Process.setThreadPriority(oldPri);
8427 }
8428
8429 void removeRequestedPss(ProcessRecord proc) {
8430 Runnable callback = null;
8431 synchronized (this) {
8432 if (mRequestPssList.remove(proc)) {
8433 if (mRequestPssList.size() == 0) {
8434 callback = mRequestPssCallback;
8435 mRequestPssCallback = null;
8436 }
8437 }
8438 }
8439
8440 if (callback != null) {
8441 callback.run();
8442 }
8443 }
8444
8445 public void collectPss(Watchdog.PssStats stats) {
8446 stats.mEmptyPss = 0;
8447 stats.mEmptyCount = 0;
8448 stats.mBackgroundPss = 0;
8449 stats.mBackgroundCount = 0;
8450 stats.mServicePss = 0;
8451 stats.mServiceCount = 0;
8452 stats.mVisiblePss = 0;
8453 stats.mVisibleCount = 0;
8454 stats.mForegroundPss = 0;
8455 stats.mForegroundCount = 0;
8456 stats.mNoPssCount = 0;
8457 synchronized (this) {
8458 int i;
8459 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8460 ? mProcDeaths.length : stats.mProcDeaths.length;
8461 int aggr = 0;
8462 for (i=0; i<NPD; i++) {
8463 aggr += mProcDeaths[i];
8464 stats.mProcDeaths[i] = aggr;
8465 }
8466 while (i<stats.mProcDeaths.length) {
8467 stats.mProcDeaths[i] = 0;
8468 i++;
8469 }
8470
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008471 for (i=mLruProcesses.size()-1; i>=0; i--) {
8472 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008473 if (proc.persistent) {
8474 continue;
8475 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008476 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008477 if (proc.lastPss == 0) {
8478 stats.mNoPssCount++;
8479 continue;
8480 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008481 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8482 if (proc.empty) {
8483 stats.mEmptyPss += proc.lastPss;
8484 stats.mEmptyCount++;
8485 } else {
8486 stats.mBackgroundPss += proc.lastPss;
8487 stats.mBackgroundCount++;
8488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008489 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8490 stats.mVisiblePss += proc.lastPss;
8491 stats.mVisibleCount++;
8492 } else {
8493 stats.mForegroundPss += proc.lastPss;
8494 stats.mForegroundCount++;
8495 }
8496 }
8497 }
8498 }
8499
8500 public final void startRunning(String pkg, String cls, String action,
8501 String data) {
8502 synchronized(this) {
8503 if (mStartRunning) {
8504 return;
8505 }
8506 mStartRunning = true;
8507 mTopComponent = pkg != null && cls != null
8508 ? new ComponentName(pkg, cls) : null;
8509 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8510 mTopData = data;
8511 if (!mSystemReady) {
8512 return;
8513 }
8514 }
8515
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008516 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008517 }
8518
8519 private void retrieveSettings() {
8520 final ContentResolver resolver = mContext.getContentResolver();
8521 String debugApp = Settings.System.getString(
8522 resolver, Settings.System.DEBUG_APP);
8523 boolean waitForDebugger = Settings.System.getInt(
8524 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8525 boolean alwaysFinishActivities = Settings.System.getInt(
8526 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8527
8528 Configuration configuration = new Configuration();
8529 Settings.System.getConfiguration(resolver, configuration);
8530
8531 synchronized (this) {
8532 mDebugApp = mOrigDebugApp = debugApp;
8533 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8534 mAlwaysFinishActivities = alwaysFinishActivities;
8535 // This happens before any activities are started, so we can
8536 // change mConfiguration in-place.
8537 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008538 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008539 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 }
8541 }
8542
8543 public boolean testIsSystemReady() {
8544 // no need to synchronize(this) just to read & return the value
8545 return mSystemReady;
8546 }
8547
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008548 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008549 // In the simulator, startRunning will never have been called, which
8550 // normally sets a few crucial variables. Do it here instead.
8551 if (!Process.supportsProcesses()) {
8552 mStartRunning = true;
8553 mTopAction = Intent.ACTION_MAIN;
8554 }
8555
8556 synchronized(this) {
8557 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008558 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008559 return;
8560 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008561
8562 // Check to see if there are any update receivers to run.
8563 if (!mDidUpdate) {
8564 if (mWaitingUpdate) {
8565 return;
8566 }
8567 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8568 List<ResolveInfo> ris = null;
8569 try {
8570 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8571 intent, null, 0);
8572 } catch (RemoteException e) {
8573 }
8574 if (ris != null) {
8575 for (int i=ris.size()-1; i>=0; i--) {
8576 if ((ris.get(i).activityInfo.applicationInfo.flags
8577 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8578 ris.remove(i);
8579 }
8580 }
8581 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8582 for (int i=0; i<ris.size(); i++) {
8583 ActivityInfo ai = ris.get(i).activityInfo;
8584 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8585 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008586 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008587 finisher = new IIntentReceiver.Stub() {
8588 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008589 String data, Bundle extras, boolean ordered,
8590 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008591 throws RemoteException {
8592 synchronized (ActivityManagerService.this) {
8593 mDidUpdate = true;
8594 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008595 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008596 }
8597 };
8598 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008599 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008600 broadcastIntentLocked(null, null, intent, null, finisher,
8601 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008602 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008603 mWaitingUpdate = true;
8604 }
8605 }
8606 }
8607 if (mWaitingUpdate) {
8608 return;
8609 }
8610 mDidUpdate = true;
8611 }
8612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 mSystemReady = true;
8614 if (!mStartRunning) {
8615 return;
8616 }
8617 }
8618
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008619 ArrayList<ProcessRecord> procsToKill = null;
8620 synchronized(mPidsSelfLocked) {
8621 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8622 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8623 if (!isAllowedWhileBooting(proc.info)){
8624 if (procsToKill == null) {
8625 procsToKill = new ArrayList<ProcessRecord>();
8626 }
8627 procsToKill.add(proc);
8628 }
8629 }
8630 }
8631
8632 if (procsToKill != null) {
8633 synchronized(this) {
8634 for (int i=procsToKill.size()-1; i>=0; i--) {
8635 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008636 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008637 removeProcessLocked(proc, true);
8638 }
8639 }
8640 }
8641
Joe Onorato8a9b2202010-02-26 18:56:32 -08008642 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008643 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 SystemClock.uptimeMillis());
8645
8646 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008647 // Make sure we have no pre-ready processes sitting around.
8648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8650 ResolveInfo ri = mContext.getPackageManager()
8651 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008652 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653 CharSequence errorMsg = null;
8654 if (ri != null) {
8655 ActivityInfo ai = ri.activityInfo;
8656 ApplicationInfo app = ai.applicationInfo;
8657 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8658 mTopAction = Intent.ACTION_FACTORY_TEST;
8659 mTopData = null;
8660 mTopComponent = new ComponentName(app.packageName,
8661 ai.name);
8662 } else {
8663 errorMsg = mContext.getResources().getText(
8664 com.android.internal.R.string.factorytest_not_system);
8665 }
8666 } else {
8667 errorMsg = mContext.getResources().getText(
8668 com.android.internal.R.string.factorytest_no_action);
8669 }
8670 if (errorMsg != null) {
8671 mTopAction = null;
8672 mTopData = null;
8673 mTopComponent = null;
8674 Message msg = Message.obtain();
8675 msg.what = SHOW_FACTORY_ERROR_MSG;
8676 msg.getData().putCharSequence("msg", errorMsg);
8677 mHandler.sendMessage(msg);
8678 }
8679 }
8680 }
8681
8682 retrieveSettings();
8683
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008684 if (goingCallback != null) goingCallback.run();
8685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008686 synchronized (this) {
8687 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8688 try {
8689 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008690 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008691 if (apps != null) {
8692 int N = apps.size();
8693 int i;
8694 for (i=0; i<N; i++) {
8695 ApplicationInfo info
8696 = (ApplicationInfo)apps.get(i);
8697 if (info != null &&
8698 !info.packageName.equals("android")) {
8699 addAppLocked(info);
8700 }
8701 }
8702 }
8703 } catch (RemoteException ex) {
8704 // pm is in same process, this will never happen.
8705 }
8706 }
8707
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008708 // Start up initial activity.
8709 mBooting = true;
8710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008711 try {
8712 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8713 Message msg = Message.obtain();
8714 msg.what = SHOW_UID_ERROR_MSG;
8715 mHandler.sendMessage(msg);
8716 }
8717 } catch (RemoteException e) {
8718 }
8719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008720 resumeTopActivityLocked(null);
8721 }
8722 }
8723
Dan Egnorb7f03672009-12-09 16:22:32 -08008724 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008725 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008726 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008727 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008728 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008729 startAppProblemLocked(app);
8730 app.stopFreezingAllLocked();
8731 return handleAppCrashLocked(app);
8732 }
8733
Dan Egnorb7f03672009-12-09 16:22:32 -08008734 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008735 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008736 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008737 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008738 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8739 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008740 startAppProblemLocked(app);
8741 app.stopFreezingAllLocked();
8742 }
8743
8744 /**
8745 * Generate a process error record, suitable for attachment to a ProcessRecord.
8746 *
8747 * @param app The ProcessRecord in which the error occurred.
8748 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8749 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008750 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008751 * @param shortMsg Short message describing the crash.
8752 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008753 * @param stackTrace Full crash stack trace, may be null.
8754 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008755 * @return Returns a fully-formed AppErrorStateInfo record.
8756 */
8757 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008758 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008761 report.condition = condition;
8762 report.processName = app.processName;
8763 report.pid = app.pid;
8764 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008765 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008766 report.shortMsg = shortMsg;
8767 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008768 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008769
8770 return report;
8771 }
8772
Dan Egnor42471dd2010-01-07 17:25:22 -08008773 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008774 synchronized (this) {
8775 app.crashing = false;
8776 app.crashingReport = null;
8777 app.notResponding = false;
8778 app.notRespondingReport = null;
8779 if (app.anrDialog == fromDialog) {
8780 app.anrDialog = null;
8781 }
8782 if (app.waitDialog == fromDialog) {
8783 app.waitDialog = null;
8784 }
8785 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008786 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008787 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 + app.processName
8789 + " (pid=" + app.pid + ") at user's request");
8790 Process.killProcess(app.pid);
8791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008792 }
8793 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008794
Dan Egnorb7f03672009-12-09 16:22:32 -08008795 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008796 long now = SystemClock.uptimeMillis();
8797
8798 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8799 app.info.uid);
8800 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8801 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008802 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008803 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008804 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008805 app.info.processName, app.info.uid);
8806 killServicesLocked(app, false);
8807 for (int i=mHistory.size()-1; i>=0; i--) {
8808 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8809 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008810 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008811 + r.intent.getComponent().flattenToShortString());
8812 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8813 }
8814 }
8815 if (!app.persistent) {
8816 // We don't want to start this process again until the user
8817 // explicitly does so... but for persistent process, we really
8818 // need to keep it running. If a persistent process is actually
8819 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008820 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008821 app.info.processName);
8822 mBadProcesses.put(app.info.processName, app.info.uid, now);
8823 app.bad = true;
8824 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8825 app.removed = true;
8826 removeProcessLocked(app, false);
8827 return false;
8828 }
8829 }
8830
8831 // Bump up the crash count of any services currently running in the proc.
8832 if (app.services.size() != 0) {
8833 // Any services running in the application need to be placed
8834 // back in the pending list.
8835 Iterator it = app.services.iterator();
8836 while (it.hasNext()) {
8837 ServiceRecord sr = (ServiceRecord)it.next();
8838 sr.crashCount++;
8839 }
8840 }
8841
8842 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8843 return true;
8844 }
8845
8846 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008847 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8848 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008849 skipCurrentReceiverLocked(app);
8850 }
8851
8852 void skipCurrentReceiverLocked(ProcessRecord app) {
8853 boolean reschedule = false;
8854 BroadcastRecord r = app.curReceiver;
8855 if (r != null) {
8856 // The current broadcast is waiting for this app's receiver
8857 // to be finished. Looks like that's not going to happen, so
8858 // let the broadcast continue.
8859 logBroadcastReceiverDiscard(r);
8860 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8861 r.resultExtras, r.resultAbort, true);
8862 reschedule = true;
8863 }
8864 r = mPendingBroadcast;
8865 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008866 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008867 "skip & discard pending app " + r);
8868 logBroadcastReceiverDiscard(r);
8869 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8870 r.resultExtras, r.resultAbort, true);
8871 reschedule = true;
8872 }
8873 if (reschedule) {
8874 scheduleBroadcastsLocked();
8875 }
8876 }
8877
Dan Egnor60d87622009-12-16 16:32:58 -08008878 /**
8879 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8880 * The application process will exit immediately after this call returns.
8881 * @param app object of the crashing app, null for the system server
8882 * @param crashInfo describing the exception
8883 */
8884 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8885 ProcessRecord r = findAppProcess(app);
8886
8887 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8888 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008889 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008890 crashInfo.exceptionClassName,
8891 crashInfo.exceptionMessage,
8892 crashInfo.throwFileName,
8893 crashInfo.throwLineNumber);
8894
Dan Egnor42471dd2010-01-07 17:25:22 -08008895 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008896
8897 crashApplication(r, crashInfo);
8898 }
8899
8900 /**
8901 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8902 * @param app object of the crashing app, null for the system server
8903 * @param tag reported by the caller
8904 * @param crashInfo describing the context of the error
8905 * @return true if the process should exit immediately (WTF is fatal)
8906 */
8907 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008908 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008909 ProcessRecord r = findAppProcess(app);
8910
8911 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8912 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008913 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008914 tag, crashInfo.exceptionMessage);
8915
Dan Egnor42471dd2010-01-07 17:25:22 -08008916 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008917
Doug Zongker43866e02010-01-07 12:09:54 -08008918 if (Settings.Secure.getInt(mContext.getContentResolver(),
8919 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008920 crashApplication(r, crashInfo);
8921 return true;
8922 } else {
8923 return false;
8924 }
8925 }
8926
8927 /**
8928 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8929 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8930 */
8931 private ProcessRecord findAppProcess(IBinder app) {
8932 if (app == null) {
8933 return null;
8934 }
8935
8936 synchronized (this) {
8937 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8938 final int NA = apps.size();
8939 for (int ia=0; ia<NA; ia++) {
8940 ProcessRecord p = apps.valueAt(ia);
8941 if (p.thread != null && p.thread.asBinder() == app) {
8942 return p;
8943 }
8944 }
8945 }
8946
Joe Onorato8a9b2202010-02-26 18:56:32 -08008947 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008948 return null;
8949 }
8950 }
8951
8952 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008953 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008954 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008955 * @param process which caused the error, null means the system server
8956 * @param activity which triggered the error, null if unknown
8957 * @param parent activity related to the error, null if unknown
8958 * @param subject line related to the error, null if absent
8959 * @param report in long form describing the error, null if absent
8960 * @param logFile to include in the report, null if none
8961 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008962 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08008963 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08008964 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
8965 final String report, final File logFile,
8966 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08008967 // NOTE -- this must never acquire the ActivityManagerService lock,
8968 // otherwise the watchdog may be prevented from resetting the system.
8969
Dan Egnora455d192010-03-12 08:52:28 -08008970 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08008971 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08008972 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08008973 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08008974 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08008975 } else {
Dan Egnora455d192010-03-12 08:52:28 -08008976 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08008977 }
8978
Dan Egnora455d192010-03-12 08:52:28 -08008979 final String dropboxTag = prefix + eventType;
8980 final DropBoxManager dbox = (DropBoxManager)
8981 mContext.getSystemService(Context.DROPBOX_SERVICE);
8982
8983 // Exit early if the dropbox isn't configured to accept this report type.
8984 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
8985
8986 final StringBuilder sb = new StringBuilder(1024);
8987 if (process == null || process.pid == MY_PID) {
8988 sb.append("Process: system_server\n");
8989 } else {
8990 sb.append("Process: ").append(process.processName).append("\n");
8991 }
8992 if (process != null) {
8993 int flags = process.info.flags;
8994 IPackageManager pm = ActivityThread.getPackageManager();
8995 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8996 for (String pkg : process.pkgList) {
8997 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08008998 try {
Dan Egnora455d192010-03-12 08:52:28 -08008999 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9000 if (pi != null) {
9001 sb.append(" v").append(pi.versionCode);
9002 if (pi.versionName != null) {
9003 sb.append(" (").append(pi.versionName).append(")");
9004 }
9005 }
9006 } catch (RemoteException e) {
9007 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009008 }
Dan Egnora455d192010-03-12 08:52:28 -08009009 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009010 }
Dan Egnora455d192010-03-12 08:52:28 -08009011 }
9012 if (activity != null) {
9013 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9014 }
9015 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9016 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9017 }
9018 if (parent != null && parent != activity) {
9019 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9020 }
9021 if (subject != null) {
9022 sb.append("Subject: ").append(subject).append("\n");
9023 }
9024 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9025 sb.append("\n");
9026
9027 // Do the rest in a worker thread to avoid blocking the caller on I/O
9028 // (After this point, we shouldn't access AMS internal data structures.)
9029 Thread worker = new Thread("Error dump: " + dropboxTag) {
9030 @Override
9031 public void run() {
9032 if (report != null) {
9033 sb.append(report);
9034 }
9035 if (logFile != null) {
9036 try {
9037 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9038 } catch (IOException e) {
9039 Slog.e(TAG, "Error reading " + logFile, e);
9040 }
9041 }
9042 if (crashInfo != null && crashInfo.stackTrace != null) {
9043 sb.append(crashInfo.stackTrace);
9044 }
9045
9046 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9047 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9048 if (lines > 0) {
9049 sb.append("\n");
9050
9051 // Merge several logcat streams, and take the last N lines
9052 InputStreamReader input = null;
9053 try {
9054 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9055 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9056 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9057
9058 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9059 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9060 input = new InputStreamReader(logcat.getInputStream());
9061
9062 int num;
9063 char[] buf = new char[8192];
9064 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9065 } catch (IOException e) {
9066 Slog.e(TAG, "Error running logcat", e);
9067 } finally {
9068 if (input != null) try { input.close(); } catch (IOException e) {}
9069 }
9070 }
9071
9072 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009073 }
Dan Egnora455d192010-03-12 08:52:28 -08009074 };
9075
9076 if (process == null || process.pid == MY_PID) {
9077 worker.run(); // We may be about to die -- need to run this synchronously
9078 } else {
9079 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009080 }
9081 }
9082
9083 /**
9084 * Bring up the "unexpected error" dialog box for a crashing app.
9085 * Deal with edge cases (intercepts from instrumented applications,
9086 * ActivityController, error intent receivers, that sort of thing).
9087 * @param r the application crashing
9088 * @param crashInfo describing the failure
9089 */
9090 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009091 long timeMillis = System.currentTimeMillis();
9092 String shortMsg = crashInfo.exceptionClassName;
9093 String longMsg = crashInfo.exceptionMessage;
9094 String stackTrace = crashInfo.stackTrace;
9095 if (shortMsg != null && longMsg != null) {
9096 longMsg = shortMsg + ": " + longMsg;
9097 } else if (shortMsg != null) {
9098 longMsg = shortMsg;
9099 }
9100
Dan Egnor60d87622009-12-16 16:32:58 -08009101 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009103 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009104 try {
9105 String name = r != null ? r.processName : null;
9106 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009107 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009108 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009109 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009110 + " at watcher's request");
9111 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009112 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 }
9114 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009115 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009116 }
9117 }
9118
9119 final long origId = Binder.clearCallingIdentity();
9120
9121 // If this process is running instrumentation, finish it.
9122 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009123 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009124 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009125 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9126 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009127 Bundle info = new Bundle();
9128 info.putString("shortMsg", shortMsg);
9129 info.putString("longMsg", longMsg);
9130 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9131 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009132 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009133 }
9134
Dan Egnor60d87622009-12-16 16:32:58 -08009135 // If we can't identify the process or it's already exceeded its crash quota,
9136 // quit right away without showing a crash dialog.
9137 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009138 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009139 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009140 }
9141
9142 Message msg = Message.obtain();
9143 msg.what = SHOW_ERROR_MSG;
9144 HashMap data = new HashMap();
9145 data.put("result", result);
9146 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147 msg.obj = data;
9148 mHandler.sendMessage(msg);
9149
9150 Binder.restoreCallingIdentity(origId);
9151 }
9152
9153 int res = result.get();
9154
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009155 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009156 synchronized (this) {
9157 if (r != null) {
9158 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9159 SystemClock.uptimeMillis());
9160 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009161 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009162 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009163 }
9164 }
9165
9166 if (appErrorIntent != null) {
9167 try {
9168 mContext.startActivity(appErrorIntent);
9169 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009170 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009171 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009174
9175 Intent createAppErrorIntentLocked(ProcessRecord r,
9176 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9177 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009178 if (report == null) {
9179 return null;
9180 }
9181 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9182 result.setComponent(r.errorReportReceiver);
9183 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9184 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9185 return result;
9186 }
9187
Dan Egnorb7f03672009-12-09 16:22:32 -08009188 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9189 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009190 if (r.errorReportReceiver == null) {
9191 return null;
9192 }
9193
9194 if (!r.crashing && !r.notResponding) {
9195 return null;
9196 }
9197
Dan Egnorb7f03672009-12-09 16:22:32 -08009198 ApplicationErrorReport report = new ApplicationErrorReport();
9199 report.packageName = r.info.packageName;
9200 report.installerPackageName = r.errorReportReceiver.getPackageName();
9201 report.processName = r.processName;
9202 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009203 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009204
Dan Egnorb7f03672009-12-09 16:22:32 -08009205 if (r.crashing) {
9206 report.type = ApplicationErrorReport.TYPE_CRASH;
9207 report.crashInfo = crashInfo;
9208 } else if (r.notResponding) {
9209 report.type = ApplicationErrorReport.TYPE_ANR;
9210 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009211
Dan Egnorb7f03672009-12-09 16:22:32 -08009212 report.anrInfo.activity = r.notRespondingReport.tag;
9213 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9214 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009215 }
9216
Dan Egnorb7f03672009-12-09 16:22:32 -08009217 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009218 }
9219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9221 // assume our apps are happy - lazy create the list
9222 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9223
9224 synchronized (this) {
9225
9226 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009227 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9228 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009229 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9230 // This one's in trouble, so we'll generate a report for it
9231 // crashes are higher priority (in case there's a crash *and* an anr)
9232 ActivityManager.ProcessErrorStateInfo report = null;
9233 if (app.crashing) {
9234 report = app.crashingReport;
9235 } else if (app.notResponding) {
9236 report = app.notRespondingReport;
9237 }
9238
9239 if (report != null) {
9240 if (errList == null) {
9241 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9242 }
9243 errList.add(report);
9244 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009245 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009246 " crashing = " + app.crashing +
9247 " notResponding = " + app.notResponding);
9248 }
9249 }
9250 }
9251 }
9252
9253 return errList;
9254 }
9255
9256 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9257 // Lazy instantiation of list
9258 List<ActivityManager.RunningAppProcessInfo> runList = null;
9259 synchronized (this) {
9260 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009261 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9262 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009263 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9264 // Generate process state info for running application
9265 ActivityManager.RunningAppProcessInfo currApp =
9266 new ActivityManager.RunningAppProcessInfo(app.processName,
9267 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009268 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009269 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009270 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9272 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9273 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009274 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9275 } else if (adj >= HOME_APP_ADJ) {
9276 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9277 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 } else if (adj >= SECONDARY_SERVER_ADJ) {
9279 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9280 } else if (adj >= VISIBLE_APP_ADJ) {
9281 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9282 } else {
9283 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9284 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009285 currApp.importanceReasonCode = app.adjTypeCode;
9286 if (app.adjSource instanceof ProcessRecord) {
9287 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9288 } else if (app.adjSource instanceof HistoryRecord) {
9289 HistoryRecord r = (HistoryRecord)app.adjSource;
9290 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9291 }
9292 if (app.adjTarget instanceof ComponentName) {
9293 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9294 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009295 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009296 // + " lru=" + currApp.lru);
9297 if (runList == null) {
9298 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9299 }
9300 runList.add(currApp);
9301 }
9302 }
9303 }
9304 return runList;
9305 }
9306
9307 @Override
9308 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009309 if (checkCallingPermission(android.Manifest.permission.DUMP)
9310 != PackageManager.PERMISSION_GRANTED) {
9311 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9312 + Binder.getCallingPid()
9313 + ", uid=" + Binder.getCallingUid()
9314 + " without permission "
9315 + android.Manifest.permission.DUMP);
9316 return;
9317 }
9318
9319 boolean dumpAll = false;
9320
9321 int opti = 0;
9322 while (opti < args.length) {
9323 String opt = args[opti];
9324 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9325 break;
9326 }
9327 opti++;
9328 if ("-a".equals(opt)) {
9329 dumpAll = true;
9330 } else if ("-h".equals(opt)) {
9331 pw.println("Activity manager dump options:");
9332 pw.println(" [-a] [h- [cmd] ...");
9333 pw.println(" cmd may be one of:");
9334 pw.println(" activities: activity stack state");
9335 pw.println(" broadcasts: broadcast state");
9336 pw.println(" intents: pending intent state");
9337 pw.println(" processes: process state");
9338 pw.println(" providers: content provider state");
9339 pw.println(" services: service state");
9340 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009341 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009342 } else {
9343 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009344 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009345 }
9346
9347 // Is the caller requesting to dump a particular piece of data?
9348 if (opti < args.length) {
9349 String cmd = args[opti];
9350 opti++;
9351 if ("activities".equals(cmd) || "a".equals(cmd)) {
9352 synchronized (this) {
9353 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009354 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009355 return;
9356 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9357 synchronized (this) {
9358 dumpBroadcastsLocked(fd, pw, args, opti, true);
9359 }
9360 return;
9361 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9362 synchronized (this) {
9363 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9364 }
9365 return;
9366 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9367 synchronized (this) {
9368 dumpProcessesLocked(fd, pw, args, opti, true);
9369 }
9370 return;
9371 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9372 synchronized (this) {
9373 dumpProvidersLocked(fd, pw, args, opti, true);
9374 }
9375 return;
9376 } else if ("service".equals(cmd)) {
9377 dumpService(fd, pw, args, opti, true);
9378 return;
9379 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9380 synchronized (this) {
9381 dumpServicesLocked(fd, pw, args, opti, true);
9382 }
9383 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009384 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009385 }
9386
9387 // No piece of data specified, dump everything.
9388 synchronized (this) {
9389 boolean needSep;
9390 if (dumpAll) {
9391 pw.println("Providers in Current Activity Manager State:");
9392 }
9393 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9394 if (needSep) {
9395 pw.println(" ");
9396 }
9397 if (dumpAll) {
9398 pw.println("-------------------------------------------------------------------------------");
9399 pw.println("Broadcasts in Current Activity Manager State:");
9400 }
9401 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9402 if (needSep) {
9403 pw.println(" ");
9404 }
9405 if (dumpAll) {
9406 pw.println("-------------------------------------------------------------------------------");
9407 pw.println("Services in Current Activity Manager State:");
9408 }
9409 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9410 if (needSep) {
9411 pw.println(" ");
9412 }
9413 if (dumpAll) {
9414 pw.println("-------------------------------------------------------------------------------");
9415 pw.println("PendingIntents in Current Activity Manager State:");
9416 }
9417 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9418 if (needSep) {
9419 pw.println(" ");
9420 }
9421 if (dumpAll) {
9422 pw.println("-------------------------------------------------------------------------------");
9423 pw.println("Activities in Current Activity Manager State:");
9424 }
9425 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9426 if (needSep) {
9427 pw.println(" ");
9428 }
9429 if (dumpAll) {
9430 pw.println("-------------------------------------------------------------------------------");
9431 pw.println("Processes in Current Activity Manager State:");
9432 }
9433 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9434 }
9435 }
9436
9437 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9438 int opti, boolean dumpAll, boolean needHeader) {
9439 if (needHeader) {
9440 pw.println(" Activity stack:");
9441 }
9442 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9443 pw.println(" ");
9444 pw.println(" Running activities (most recent first):");
9445 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9446 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009447 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009448 pw.println(" Activities waiting for another to become visible:");
9449 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9450 }
9451 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009453 pw.println(" Activities waiting to stop:");
9454 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9455 }
9456 if (mFinishingActivities.size() > 0) {
9457 pw.println(" ");
9458 pw.println(" Activities waiting to finish:");
9459 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009461
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009462 pw.println(" ");
9463 pw.println(" mPausingActivity: " + mPausingActivity);
9464 pw.println(" mResumedActivity: " + mResumedActivity);
9465 pw.println(" mFocusedActivity: " + mFocusedActivity);
9466 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009467
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009468 if (dumpAll && mRecentTasks.size() > 0) {
9469 pw.println(" ");
9470 pw.println("Recent tasks in Current Activity Manager State:");
9471
9472 final int N = mRecentTasks.size();
9473 for (int i=0; i<N; i++) {
9474 TaskRecord tr = mRecentTasks.get(i);
9475 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9476 pw.println(tr);
9477 mRecentTasks.get(i).dump(pw, " ");
9478 }
9479 }
9480
9481 pw.println(" ");
9482 pw.println(" mCurTask: " + mCurTask);
9483
9484 return true;
9485 }
9486
9487 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9488 int opti, boolean dumpAll) {
9489 boolean needSep = false;
9490 int numPers = 0;
9491
9492 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009493 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9494 final int NA = procs.size();
9495 for (int ia=0; ia<NA; ia++) {
9496 if (!needSep) {
9497 pw.println(" All known processes:");
9498 needSep = true;
9499 }
9500 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009501 pw.print(r.persistent ? " *PERS*" : " *APP*");
9502 pw.print(" UID "); pw.print(procs.keyAt(ia));
9503 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009504 r.dump(pw, " ");
9505 if (r.persistent) {
9506 numPers++;
9507 }
9508 }
9509 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009510 }
9511
9512 if (mLruProcesses.size() > 0) {
9513 if (needSep) pw.println(" ");
9514 needSep = true;
9515 pw.println(" Running processes (most recent first):");
9516 dumpProcessList(pw, this, mLruProcesses, " ",
9517 "App ", "PERS", true);
9518 needSep = true;
9519 }
9520
9521 synchronized (mPidsSelfLocked) {
9522 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009523 if (needSep) pw.println(" ");
9524 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009525 pw.println(" PID mappings:");
9526 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9527 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9528 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009529 }
9530 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009531 }
9532
9533 if (mForegroundProcesses.size() > 0) {
9534 if (needSep) pw.println(" ");
9535 needSep = true;
9536 pw.println(" Foreground Processes:");
9537 for (int i=0; i<mForegroundProcesses.size(); i++) {
9538 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9539 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009540 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009541 }
9542
9543 if (mPersistentStartingProcesses.size() > 0) {
9544 if (needSep) pw.println(" ");
9545 needSep = true;
9546 pw.println(" Persisent processes that are starting:");
9547 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9548 "Starting Norm", "Restarting PERS", false);
9549 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009551 if (mStartingProcesses.size() > 0) {
9552 if (needSep) pw.println(" ");
9553 needSep = true;
9554 pw.println(" Processes that are starting:");
9555 dumpProcessList(pw, this, mStartingProcesses, " ",
9556 "Starting Norm", "Starting PERS", false);
9557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009558
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009559 if (mRemovedProcesses.size() > 0) {
9560 if (needSep) pw.println(" ");
9561 needSep = true;
9562 pw.println(" Processes that are being removed:");
9563 dumpProcessList(pw, this, mRemovedProcesses, " ",
9564 "Removed Norm", "Removed PERS", false);
9565 }
9566
9567 if (mProcessesOnHold.size() > 0) {
9568 if (needSep) pw.println(" ");
9569 needSep = true;
9570 pw.println(" Processes that are on old until the system is ready:");
9571 dumpProcessList(pw, this, mProcessesOnHold, " ",
9572 "OnHold Norm", "OnHold PERS", false);
9573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009574
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009575 if (mProcessesToGc.size() > 0) {
9576 if (needSep) pw.println(" ");
9577 needSep = true;
9578 pw.println(" Processes that are waiting to GC:");
9579 long now = SystemClock.uptimeMillis();
9580 for (int i=0; i<mProcessesToGc.size(); i++) {
9581 ProcessRecord proc = mProcessesToGc.get(i);
9582 pw.print(" Process "); pw.println(proc);
9583 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9584 pw.print(", last gced=");
9585 pw.print(now-proc.lastRequestedGc);
9586 pw.print(" ms ago, last lowMem=");
9587 pw.print(now-proc.lastLowMemory);
9588 pw.println(" ms ago");
9589
9590 }
9591 }
9592
9593 if (mProcessCrashTimes.getMap().size() > 0) {
9594 if (needSep) pw.println(" ");
9595 needSep = true;
9596 pw.println(" Time since processes crashed:");
9597 long now = SystemClock.uptimeMillis();
9598 for (Map.Entry<String, SparseArray<Long>> procs
9599 : mProcessCrashTimes.getMap().entrySet()) {
9600 SparseArray<Long> uids = procs.getValue();
9601 final int N = uids.size();
9602 for (int i=0; i<N; i++) {
9603 pw.print(" Process "); pw.print(procs.getKey());
9604 pw.print(" uid "); pw.print(uids.keyAt(i));
9605 pw.print(": last crashed ");
9606 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009607 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009608 }
9609 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009611
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009612 if (mBadProcesses.getMap().size() > 0) {
9613 if (needSep) pw.println(" ");
9614 needSep = true;
9615 pw.println(" Bad processes:");
9616 for (Map.Entry<String, SparseArray<Long>> procs
9617 : mBadProcesses.getMap().entrySet()) {
9618 SparseArray<Long> uids = procs.getValue();
9619 final int N = uids.size();
9620 for (int i=0; i<N; i++) {
9621 pw.print(" Bad process "); pw.print(procs.getKey());
9622 pw.print(" uid "); pw.print(uids.keyAt(i));
9623 pw.print(": crashed at time ");
9624 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009625 }
9626 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009628
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009629 pw.println(" ");
9630 pw.println(" mHomeProcess: " + mHomeProcess);
9631 pw.println(" mConfiguration: " + mConfiguration);
9632 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9633 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9634 || mOrigWaitForDebugger) {
9635 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9636 + " mDebugTransient=" + mDebugTransient
9637 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9638 }
9639 if (mAlwaysFinishActivities || mController != null) {
9640 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9641 + " mController=" + mController);
9642 }
9643 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009644 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 pw.println(" mStartRunning=" + mStartRunning
9646 + " mSystemReady=" + mSystemReady
9647 + " mBooting=" + mBooting
9648 + " mBooted=" + mBooted
9649 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009650 pw.println(" mGoingToSleep=" + mGoingToSleep);
9651 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009653
9654 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009655 }
9656
9657 /**
9658 * There are three ways to call this:
9659 * - no service specified: dump all the services
9660 * - a flattened component name that matched an existing service was specified as the
9661 * first arg: dump that one service
9662 * - the first arg isn't the flattened component name of an existing service:
9663 * dump all services whose component contains the first arg as a substring
9664 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009665 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9666 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 String[] newArgs;
9668 String componentNameString;
9669 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009670 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009671 componentNameString = null;
9672 newArgs = EMPTY_STRING_ARRAY;
9673 r = null;
9674 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009675 componentNameString = args[opti];
9676 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009677 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9678 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009679 newArgs = new String[args.length - opti];
9680 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009681 }
9682
9683 if (r != null) {
9684 dumpService(fd, pw, r, newArgs);
9685 } else {
9686 for (ServiceRecord r1 : mServices.values()) {
9687 if (componentNameString == null
9688 || r1.name.flattenToString().contains(componentNameString)) {
9689 dumpService(fd, pw, r1, newArgs);
9690 }
9691 }
9692 }
9693 }
9694
9695 /**
9696 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9697 * there is a thread associated with the service.
9698 */
9699 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9700 pw.println(" Service " + r.name.flattenToString());
9701 if (r.app != null && r.app.thread != null) {
9702 try {
9703 // flush anything that is already in the PrintWriter since the thread is going
9704 // to write to the file descriptor directly
9705 pw.flush();
9706 r.app.thread.dumpService(fd, r, args);
9707 pw.print("\n");
9708 } catch (RemoteException e) {
9709 pw.println("got a RemoteException while dumping the service");
9710 }
9711 }
9712 }
9713
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009714 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9715 int opti, boolean dumpAll) {
9716 boolean needSep = false;
9717
9718 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009719 if (mRegisteredReceivers.size() > 0) {
9720 pw.println(" ");
9721 pw.println(" Registered Receivers:");
9722 Iterator it = mRegisteredReceivers.values().iterator();
9723 while (it.hasNext()) {
9724 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009725 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009726 r.dump(pw, " ");
9727 }
9728 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009730 pw.println(" ");
9731 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009732 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009733 needSep = true;
9734 }
9735
9736 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9737 || mPendingBroadcast != null) {
9738 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009739 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009740 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009741 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009742 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9743 pw.println(" Broadcast #" + i + ":");
9744 mParallelBroadcasts.get(i).dump(pw, " ");
9745 }
9746 if (mOrderedBroadcasts.size() > 0) {
9747 pw.println(" ");
9748 pw.println(" Active serialized broadcasts:");
9749 }
9750 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9751 pw.println(" Serialized Broadcast #" + i + ":");
9752 mOrderedBroadcasts.get(i).dump(pw, " ");
9753 }
9754 pw.println(" ");
9755 pw.println(" Pending broadcast:");
9756 if (mPendingBroadcast != null) {
9757 mPendingBroadcast.dump(pw, " ");
9758 } else {
9759 pw.println(" (null)");
9760 }
9761 needSep = true;
9762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009763
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009764 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009766 pw.println(" Historical broadcasts:");
9767 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9768 BroadcastRecord r = mBroadcastHistory[i];
9769 if (r == null) {
9770 break;
9771 }
9772 pw.println(" Historical Broadcast #" + i + ":");
9773 r.dump(pw, " ");
9774 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009775 needSep = true;
9776 }
9777
9778 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009779 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009780 pw.println(" Sticky broadcasts:");
9781 StringBuilder sb = new StringBuilder(128);
9782 for (Map.Entry<String, ArrayList<Intent>> ent
9783 : mStickyBroadcasts.entrySet()) {
9784 pw.print(" * Sticky action "); pw.print(ent.getKey());
9785 pw.println(":");
9786 ArrayList<Intent> intents = ent.getValue();
9787 final int N = intents.size();
9788 for (int i=0; i<N; i++) {
9789 sb.setLength(0);
9790 sb.append(" Intent: ");
9791 intents.get(i).toShortString(sb, true, false);
9792 pw.println(sb.toString());
9793 Bundle bundle = intents.get(i).getExtras();
9794 if (bundle != null) {
9795 pw.print(" ");
9796 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009797 }
9798 }
9799 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009800 needSep = true;
9801 }
9802
9803 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009804 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009805 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009806 pw.println(" mHandler:");
9807 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009808 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009809 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009810
9811 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009812 }
9813
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009814 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9815 int opti, boolean dumpAll) {
9816 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009817
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009818 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 if (mServices.size() > 0) {
9820 pw.println(" Active services:");
9821 Iterator<ServiceRecord> it = mServices.values().iterator();
9822 while (it.hasNext()) {
9823 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009824 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 r.dump(pw, " ");
9826 }
9827 needSep = true;
9828 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009831 if (mPendingServices.size() > 0) {
9832 if (needSep) pw.println(" ");
9833 pw.println(" Pending services:");
9834 for (int i=0; i<mPendingServices.size(); i++) {
9835 ServiceRecord r = mPendingServices.get(i);
9836 pw.print(" * Pending "); pw.println(r);
9837 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009838 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009839 needSep = true;
9840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009841
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009842 if (mRestartingServices.size() > 0) {
9843 if (needSep) pw.println(" ");
9844 pw.println(" Restarting services:");
9845 for (int i=0; i<mRestartingServices.size(); i++) {
9846 ServiceRecord r = mRestartingServices.get(i);
9847 pw.print(" * Restarting "); pw.println(r);
9848 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009849 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009850 needSep = true;
9851 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009852
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009853 if (mStoppingServices.size() > 0) {
9854 if (needSep) pw.println(" ");
9855 pw.println(" Stopping services:");
9856 for (int i=0; i<mStoppingServices.size(); i++) {
9857 ServiceRecord r = mStoppingServices.get(i);
9858 pw.print(" * Stopping "); pw.println(r);
9859 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009861 needSep = true;
9862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009863
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009864 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 if (mServiceConnections.size() > 0) {
9866 if (needSep) pw.println(" ");
9867 pw.println(" Connection bindings to services:");
9868 Iterator<ConnectionRecord> it
9869 = mServiceConnections.values().iterator();
9870 while (it.hasNext()) {
9871 ConnectionRecord 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 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009875 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009876 }
9877 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009878
9879 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009880 }
9881
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009882 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9883 int opti, boolean dumpAll) {
9884 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009885
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009886 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009887 if (mProvidersByClass.size() > 0) {
9888 if (needSep) pw.println(" ");
9889 pw.println(" Published content providers (by class):");
9890 Iterator it = mProvidersByClass.entrySet().iterator();
9891 while (it.hasNext()) {
9892 Map.Entry e = (Map.Entry)it.next();
9893 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009894 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009895 r.dump(pw, " ");
9896 }
9897 needSep = true;
9898 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009899
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009900 if (mProvidersByName.size() > 0) {
9901 pw.println(" ");
9902 pw.println(" Authority to provider mappings:");
9903 Iterator it = mProvidersByName.entrySet().iterator();
9904 while (it.hasNext()) {
9905 Map.Entry e = (Map.Entry)it.next();
9906 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9907 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9908 pw.println(r);
9909 }
9910 needSep = true;
9911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009912 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009913
9914 if (mLaunchingProviders.size() > 0) {
9915 if (needSep) pw.println(" ");
9916 pw.println(" Launching content providers:");
9917 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9918 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9919 pw.println(mLaunchingProviders.get(i));
9920 }
9921 needSep = true;
9922 }
9923
9924 if (mGrantedUriPermissions.size() > 0) {
9925 pw.println();
9926 pw.println("Granted Uri Permissions:");
9927 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9928 int uid = mGrantedUriPermissions.keyAt(i);
9929 HashMap<Uri, UriPermission> perms
9930 = mGrantedUriPermissions.valueAt(i);
9931 pw.print(" * UID "); pw.print(uid);
9932 pw.println(" holds:");
9933 for (UriPermission perm : perms.values()) {
9934 pw.print(" "); pw.println(perm);
9935 perm.dump(pw, " ");
9936 }
9937 }
9938 needSep = true;
9939 }
9940
9941 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009942 }
9943
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009944 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9945 int opti, boolean dumpAll) {
9946 boolean needSep = false;
9947
9948 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009949 if (this.mIntentSenderRecords.size() > 0) {
9950 Iterator<WeakReference<PendingIntentRecord>> it
9951 = mIntentSenderRecords.values().iterator();
9952 while (it.hasNext()) {
9953 WeakReference<PendingIntentRecord> ref = it.next();
9954 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009955 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009956 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009957 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009958 rec.dump(pw, " ");
9959 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009960 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009961 }
9962 }
9963 }
9964 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009965
9966 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009967 }
9968
9969 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009970 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971 TaskRecord lastTask = null;
9972 for (int i=list.size()-1; i>=0; i--) {
9973 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009974 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009975 if (lastTask != r.task) {
9976 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009977 pw.print(prefix);
9978 pw.print(full ? "* " : " ");
9979 pw.println(lastTask);
9980 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009981 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009983 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009984 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9985 pw.print(" #"); pw.print(i); pw.print(": ");
9986 pw.println(r);
9987 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009988 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009990 }
9991 }
9992
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009993 private static String buildOomTag(String prefix, String space, int val, int base) {
9994 if (val == base) {
9995 if (space == null) return prefix;
9996 return prefix + " ";
9997 }
9998 return prefix + "+" + Integer.toString(val-base);
9999 }
10000
10001 private static final int dumpProcessList(PrintWriter pw,
10002 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010003 String prefix, String normalLabel, String persistentLabel,
10004 boolean inclOomAdj) {
10005 int numPers = 0;
10006 for (int i=list.size()-1; i>=0; i--) {
10007 ProcessRecord r = (ProcessRecord)list.get(i);
10008 if (false) {
10009 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10010 + " #" + i + ":");
10011 r.dump(pw, prefix + " ");
10012 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010013 String oomAdj;
10014 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010015 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010016 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010017 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10018 } else if (r.setAdj >= HOME_APP_ADJ) {
10019 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10020 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10021 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10022 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10023 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10024 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10025 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10026 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10027 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010028 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010029 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010030 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010031 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010032 } else {
10033 oomAdj = Integer.toString(r.setAdj);
10034 }
10035 String schedGroup;
10036 switch (r.setSchedGroup) {
10037 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10038 schedGroup = "B";
10039 break;
10040 case Process.THREAD_GROUP_DEFAULT:
10041 schedGroup = "F";
10042 break;
10043 default:
10044 schedGroup = Integer.toString(r.setSchedGroup);
10045 break;
10046 }
10047 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010048 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010049 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010050 if (r.adjSource != null || r.adjTarget != null) {
10051 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010052 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010054 } else {
10055 pw.println(String.format("%s%s #%2d: %s",
10056 prefix, (r.persistent ? persistentLabel : normalLabel),
10057 i, r.toString()));
10058 }
10059 if (r.persistent) {
10060 numPers++;
10061 }
10062 }
10063 return numPers;
10064 }
10065
10066 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
10067 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010068 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010069 long uptime = SystemClock.uptimeMillis();
10070 long realtime = SystemClock.elapsedRealtime();
10071
10072 if (isCheckinRequest) {
10073 // short checkin version
10074 pw.println(uptime + "," + realtime);
10075 pw.flush();
10076 } else {
10077 pw.println("Applications Memory Usage (kB):");
10078 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10079 }
10080 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10081 ProcessRecord r = (ProcessRecord)list.get(i);
10082 if (r.thread != null) {
10083 if (!isCheckinRequest) {
10084 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10085 pw.flush();
10086 }
10087 try {
10088 r.thread.asBinder().dump(fd, args);
10089 } catch (RemoteException e) {
10090 if (!isCheckinRequest) {
10091 pw.println("Got RemoteException!");
10092 pw.flush();
10093 }
10094 }
10095 }
10096 }
10097 }
10098
10099 /**
10100 * Searches array of arguments for the specified string
10101 * @param args array of argument strings
10102 * @param value value to search for
10103 * @return true if the value is contained in the array
10104 */
10105 private static boolean scanArgs(String[] args, String value) {
10106 if (args != null) {
10107 for (String arg : args) {
10108 if (value.equals(arg)) {
10109 return true;
10110 }
10111 }
10112 }
10113 return false;
10114 }
10115
Dianne Hackborn75b03852009-06-12 15:43:26 -070010116 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010117 int count = mHistory.size();
10118
10119 // convert the token to an entry in the history.
10120 HistoryRecord r = null;
10121 int index = -1;
10122 for (int i=count-1; i>=0; i--) {
10123 Object o = mHistory.get(i);
10124 if (o == token) {
10125 r = (HistoryRecord)o;
10126 index = i;
10127 break;
10128 }
10129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010130
10131 return index;
10132 }
10133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010134 private final void killServicesLocked(ProcessRecord app,
10135 boolean allowRestart) {
10136 // Report disconnected services.
10137 if (false) {
10138 // XXX we are letting the client link to the service for
10139 // death notifications.
10140 if (app.services.size() > 0) {
10141 Iterator it = app.services.iterator();
10142 while (it.hasNext()) {
10143 ServiceRecord r = (ServiceRecord)it.next();
10144 if (r.connections.size() > 0) {
10145 Iterator<ConnectionRecord> jt
10146 = r.connections.values().iterator();
10147 while (jt.hasNext()) {
10148 ConnectionRecord c = jt.next();
10149 if (c.binding.client != app) {
10150 try {
10151 //c.conn.connected(r.className, null);
10152 } catch (Exception e) {
10153 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010154 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155 + r.shortName
10156 + " from app " + app.processName, e);
10157 }
10158 }
10159 }
10160 }
10161 }
10162 }
10163 }
10164
10165 // Clean up any connections this application has to other services.
10166 if (app.connections.size() > 0) {
10167 Iterator<ConnectionRecord> it = app.connections.iterator();
10168 while (it.hasNext()) {
10169 ConnectionRecord r = it.next();
10170 removeConnectionLocked(r, app, null);
10171 }
10172 }
10173 app.connections.clear();
10174
10175 if (app.services.size() != 0) {
10176 // Any services running in the application need to be placed
10177 // back in the pending list.
10178 Iterator it = app.services.iterator();
10179 while (it.hasNext()) {
10180 ServiceRecord sr = (ServiceRecord)it.next();
10181 synchronized (sr.stats.getBatteryStats()) {
10182 sr.stats.stopLaunchedLocked();
10183 }
10184 sr.app = null;
10185 sr.executeNesting = 0;
10186 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010187
10188 boolean hasClients = sr.bindings.size() > 0;
10189 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010190 Iterator<IntentBindRecord> bindings
10191 = sr.bindings.values().iterator();
10192 while (bindings.hasNext()) {
10193 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010194 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010195 + ": shouldUnbind=" + b.hasBound);
10196 b.binder = null;
10197 b.requested = b.received = b.hasBound = false;
10198 }
10199 }
10200
10201 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010202 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010204 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010205 sr.crashCount, sr.shortName, app.pid);
10206 bringDownServiceLocked(sr, true);
10207 } else if (!allowRestart) {
10208 bringDownServiceLocked(sr, true);
10209 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010210 boolean canceled = scheduleServiceRestartLocked(sr, true);
10211
10212 // Should the service remain running? Note that in the
10213 // extreme case of so many attempts to deliver a command
10214 // that it failed, that we also will stop it here.
10215 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10216 if (sr.pendingStarts.size() == 0) {
10217 sr.startRequested = false;
10218 if (!hasClients) {
10219 // Whoops, no reason to restart!
10220 bringDownServiceLocked(sr, true);
10221 }
10222 }
10223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010224 }
10225 }
10226
10227 if (!allowRestart) {
10228 app.services.clear();
10229 }
10230 }
10231
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010232 // Make sure we have no more records on the stopping list.
10233 int i = mStoppingServices.size();
10234 while (i > 0) {
10235 i--;
10236 ServiceRecord sr = mStoppingServices.get(i);
10237 if (sr.app == app) {
10238 mStoppingServices.remove(i);
10239 }
10240 }
10241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 app.executingServices.clear();
10243 }
10244
10245 private final void removeDyingProviderLocked(ProcessRecord proc,
10246 ContentProviderRecord cpr) {
10247 synchronized (cpr) {
10248 cpr.launchingApp = null;
10249 cpr.notifyAll();
10250 }
10251
10252 mProvidersByClass.remove(cpr.info.name);
10253 String names[] = cpr.info.authority.split(";");
10254 for (int j = 0; j < names.length; j++) {
10255 mProvidersByName.remove(names[j]);
10256 }
10257
10258 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10259 while (cit.hasNext()) {
10260 ProcessRecord capp = cit.next();
10261 if (!capp.persistent && capp.thread != null
10262 && capp.pid != 0
10263 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010264 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010265 + " (pid " + capp.pid
10266 + ") because provider " + cpr.info.name
10267 + " is in dying process " + proc.processName);
10268 Process.killProcess(capp.pid);
10269 }
10270 }
10271
10272 mLaunchingProviders.remove(cpr);
10273 }
10274
10275 /**
10276 * Main code for cleaning up a process when it has gone away. This is
10277 * called both as a result of the process dying, or directly when stopping
10278 * a process when running in single process mode.
10279 */
10280 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10281 boolean restarting, int index) {
10282 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010283 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 }
10285
Dianne Hackborn36124872009-10-08 16:22:03 -070010286 mProcessesToGc.remove(app);
10287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010288 // Dismiss any open dialogs.
10289 if (app.crashDialog != null) {
10290 app.crashDialog.dismiss();
10291 app.crashDialog = null;
10292 }
10293 if (app.anrDialog != null) {
10294 app.anrDialog.dismiss();
10295 app.anrDialog = null;
10296 }
10297 if (app.waitDialog != null) {
10298 app.waitDialog.dismiss();
10299 app.waitDialog = null;
10300 }
10301
10302 app.crashing = false;
10303 app.notResponding = false;
10304
10305 app.resetPackageList();
10306 app.thread = null;
10307 app.forcingToForeground = null;
10308 app.foregroundServices = false;
10309
10310 killServicesLocked(app, true);
10311
10312 boolean restart = false;
10313
10314 int NL = mLaunchingProviders.size();
10315
10316 // Remove published content providers.
10317 if (!app.pubProviders.isEmpty()) {
10318 Iterator it = app.pubProviders.values().iterator();
10319 while (it.hasNext()) {
10320 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10321 cpr.provider = null;
10322 cpr.app = null;
10323
10324 // See if someone is waiting for this provider... in which
10325 // case we don't remove it, but just let it restart.
10326 int i = 0;
10327 if (!app.bad) {
10328 for (; i<NL; i++) {
10329 if (mLaunchingProviders.get(i) == cpr) {
10330 restart = true;
10331 break;
10332 }
10333 }
10334 } else {
10335 i = NL;
10336 }
10337
10338 if (i >= NL) {
10339 removeDyingProviderLocked(app, cpr);
10340 NL = mLaunchingProviders.size();
10341 }
10342 }
10343 app.pubProviders.clear();
10344 }
10345
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010346 // Take care of any launching providers waiting for this process.
10347 if (checkAppInLaunchingProvidersLocked(app, false)) {
10348 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010349 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010351 // Unregister from connected content providers.
10352 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010353 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 while (it.hasNext()) {
10355 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10356 cpr.clients.remove(app);
10357 }
10358 app.conProviders.clear();
10359 }
10360
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010361 // At this point there may be remaining entries in mLaunchingProviders
10362 // where we were the only one waiting, so they are no longer of use.
10363 // Look for these and clean up if found.
10364 // XXX Commented out for now. Trying to figure out a way to reproduce
10365 // the actual situation to identify what is actually going on.
10366 if (false) {
10367 for (int i=0; i<NL; i++) {
10368 ContentProviderRecord cpr = (ContentProviderRecord)
10369 mLaunchingProviders.get(i);
10370 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10371 synchronized (cpr) {
10372 cpr.launchingApp = null;
10373 cpr.notifyAll();
10374 }
10375 }
10376 }
10377 }
10378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010379 skipCurrentReceiverLocked(app);
10380
10381 // Unregister any receivers.
10382 if (app.receivers.size() > 0) {
10383 Iterator<ReceiverList> it = app.receivers.iterator();
10384 while (it.hasNext()) {
10385 removeReceiverLocked(it.next());
10386 }
10387 app.receivers.clear();
10388 }
10389
Christopher Tate181fafa2009-05-14 11:12:14 -070010390 // If the app is undergoing backup, tell the backup manager about it
10391 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010392 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010393 try {
10394 IBackupManager bm = IBackupManager.Stub.asInterface(
10395 ServiceManager.getService(Context.BACKUP_SERVICE));
10396 bm.agentDisconnected(app.info.packageName);
10397 } catch (RemoteException e) {
10398 // can't happen; backup manager is local
10399 }
10400 }
10401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 // If the caller is restarting this app, then leave it in its
10403 // current lists and let the caller take care of it.
10404 if (restarting) {
10405 return;
10406 }
10407
10408 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010409 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010410 "Removing non-persistent process during cleanup: " + app);
10411 mProcessNames.remove(app.processName, app.info.uid);
10412 } else if (!app.removed) {
10413 // This app is persistent, so we need to keep its record around.
10414 // If it is not already on the pending app list, add it there
10415 // and start a new process for it.
10416 app.thread = null;
10417 app.forcingToForeground = null;
10418 app.foregroundServices = false;
10419 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10420 mPersistentStartingProcesses.add(app);
10421 restart = true;
10422 }
10423 }
10424 mProcessesOnHold.remove(app);
10425
The Android Open Source Project4df24232009-03-05 14:34:35 -080010426 if (app == mHomeProcess) {
10427 mHomeProcess = null;
10428 }
10429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 if (restart) {
10431 // We have components that still need to be running in the
10432 // process, so re-launch it.
10433 mProcessNames.put(app.processName, app.info.uid, app);
10434 startProcessLocked(app, "restart", app.processName);
10435 } else if (app.pid > 0 && app.pid != MY_PID) {
10436 // Goodbye!
10437 synchronized (mPidsSelfLocked) {
10438 mPidsSelfLocked.remove(app.pid);
10439 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10440 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010441 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010442 }
10443 }
10444
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010445 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10446 // Look through the content providers we are waiting to have launched,
10447 // and if any run in this process then either schedule a restart of
10448 // the process or kill the client waiting for it if this process has
10449 // gone bad.
10450 int NL = mLaunchingProviders.size();
10451 boolean restart = false;
10452 for (int i=0; i<NL; i++) {
10453 ContentProviderRecord cpr = (ContentProviderRecord)
10454 mLaunchingProviders.get(i);
10455 if (cpr.launchingApp == app) {
10456 if (!alwaysBad && !app.bad) {
10457 restart = true;
10458 } else {
10459 removeDyingProviderLocked(app, cpr);
10460 NL = mLaunchingProviders.size();
10461 }
10462 }
10463 }
10464 return restart;
10465 }
10466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010467 // =========================================================
10468 // SERVICES
10469 // =========================================================
10470
10471 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10472 ActivityManager.RunningServiceInfo info =
10473 new ActivityManager.RunningServiceInfo();
10474 info.service = r.name;
10475 if (r.app != null) {
10476 info.pid = r.app.pid;
10477 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010478 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 info.process = r.processName;
10480 info.foreground = r.isForeground;
10481 info.activeSince = r.createTime;
10482 info.started = r.startRequested;
10483 info.clientCount = r.connections.size();
10484 info.crashCount = r.crashCount;
10485 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010486 if (r.isForeground) {
10487 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10488 }
10489 if (r.startRequested) {
10490 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10491 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010492 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010493 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10494 }
10495 if (r.app != null && r.app.persistent) {
10496 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10497 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010498 for (ConnectionRecord conn : r.connections.values()) {
10499 if (conn.clientLabel != 0) {
10500 info.clientPackage = conn.binding.client.info.packageName;
10501 info.clientLabel = conn.clientLabel;
10502 break;
10503 }
10504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010505 return info;
10506 }
10507
10508 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10509 int flags) {
10510 synchronized (this) {
10511 ArrayList<ActivityManager.RunningServiceInfo> res
10512 = new ArrayList<ActivityManager.RunningServiceInfo>();
10513
10514 if (mServices.size() > 0) {
10515 Iterator<ServiceRecord> it = mServices.values().iterator();
10516 while (it.hasNext() && res.size() < maxNum) {
10517 res.add(makeRunningServiceInfoLocked(it.next()));
10518 }
10519 }
10520
10521 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10522 ServiceRecord r = mRestartingServices.get(i);
10523 ActivityManager.RunningServiceInfo info =
10524 makeRunningServiceInfoLocked(r);
10525 info.restarting = r.nextRestartTime;
10526 res.add(info);
10527 }
10528
10529 return res;
10530 }
10531 }
10532
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010533 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10534 synchronized (this) {
10535 ServiceRecord r = mServices.get(name);
10536 if (r != null) {
10537 for (ConnectionRecord conn : r.connections.values()) {
10538 if (conn.clientIntent != null) {
10539 return conn.clientIntent;
10540 }
10541 }
10542 }
10543 }
10544 return null;
10545 }
10546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010547 private final ServiceRecord findServiceLocked(ComponentName name,
10548 IBinder token) {
10549 ServiceRecord r = mServices.get(name);
10550 return r == token ? r : null;
10551 }
10552
10553 private final class ServiceLookupResult {
10554 final ServiceRecord record;
10555 final String permission;
10556
10557 ServiceLookupResult(ServiceRecord _record, String _permission) {
10558 record = _record;
10559 permission = _permission;
10560 }
10561 };
10562
10563 private ServiceLookupResult findServiceLocked(Intent service,
10564 String resolvedType) {
10565 ServiceRecord r = null;
10566 if (service.getComponent() != null) {
10567 r = mServices.get(service.getComponent());
10568 }
10569 if (r == null) {
10570 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10571 r = mServicesByIntent.get(filter);
10572 }
10573
10574 if (r == null) {
10575 try {
10576 ResolveInfo rInfo =
10577 ActivityThread.getPackageManager().resolveService(
10578 service, resolvedType, 0);
10579 ServiceInfo sInfo =
10580 rInfo != null ? rInfo.serviceInfo : null;
10581 if (sInfo == null) {
10582 return null;
10583 }
10584
10585 ComponentName name = new ComponentName(
10586 sInfo.applicationInfo.packageName, sInfo.name);
10587 r = mServices.get(name);
10588 } catch (RemoteException ex) {
10589 // pm is in same process, this will never happen.
10590 }
10591 }
10592 if (r != null) {
10593 int callingPid = Binder.getCallingPid();
10594 int callingUid = Binder.getCallingUid();
10595 if (checkComponentPermission(r.permission,
10596 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10597 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010598 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010599 + " from pid=" + callingPid
10600 + ", uid=" + callingUid
10601 + " requires " + r.permission);
10602 return new ServiceLookupResult(null, r.permission);
10603 }
10604 return new ServiceLookupResult(r, null);
10605 }
10606 return null;
10607 }
10608
10609 private class ServiceRestarter implements Runnable {
10610 private ServiceRecord mService;
10611
10612 void setService(ServiceRecord service) {
10613 mService = service;
10614 }
10615
10616 public void run() {
10617 synchronized(ActivityManagerService.this) {
10618 performServiceRestartLocked(mService);
10619 }
10620 }
10621 }
10622
10623 private ServiceLookupResult retrieveServiceLocked(Intent service,
10624 String resolvedType, int callingPid, int callingUid) {
10625 ServiceRecord r = null;
10626 if (service.getComponent() != null) {
10627 r = mServices.get(service.getComponent());
10628 }
10629 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10630 r = mServicesByIntent.get(filter);
10631 if (r == null) {
10632 try {
10633 ResolveInfo rInfo =
10634 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010635 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010636 ServiceInfo sInfo =
10637 rInfo != null ? rInfo.serviceInfo : null;
10638 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010639 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 ": not found");
10641 return null;
10642 }
10643
10644 ComponentName name = new ComponentName(
10645 sInfo.applicationInfo.packageName, sInfo.name);
10646 r = mServices.get(name);
10647 if (r == null) {
10648 filter = new Intent.FilterComparison(service.cloneFilter());
10649 ServiceRestarter res = new ServiceRestarter();
10650 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10651 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10652 synchronized (stats) {
10653 ss = stats.getServiceStatsLocked(
10654 sInfo.applicationInfo.uid, sInfo.packageName,
10655 sInfo.name);
10656 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010657 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010658 res.setService(r);
10659 mServices.put(name, r);
10660 mServicesByIntent.put(filter, r);
10661
10662 // Make sure this component isn't in the pending list.
10663 int N = mPendingServices.size();
10664 for (int i=0; i<N; i++) {
10665 ServiceRecord pr = mPendingServices.get(i);
10666 if (pr.name.equals(name)) {
10667 mPendingServices.remove(i);
10668 i--;
10669 N--;
10670 }
10671 }
10672 }
10673 } catch (RemoteException ex) {
10674 // pm is in same process, this will never happen.
10675 }
10676 }
10677 if (r != null) {
10678 if (checkComponentPermission(r.permission,
10679 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10680 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010681 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010682 + " from pid=" + Binder.getCallingPid()
10683 + ", uid=" + Binder.getCallingUid()
10684 + " requires " + r.permission);
10685 return new ServiceLookupResult(null, r.permission);
10686 }
10687 return new ServiceLookupResult(r, null);
10688 }
10689 return null;
10690 }
10691
10692 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10693 long now = SystemClock.uptimeMillis();
10694 if (r.executeNesting == 0 && r.app != null) {
10695 if (r.app.executingServices.size() == 0) {
10696 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10697 msg.obj = r.app;
10698 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10699 }
10700 r.app.executingServices.add(r);
10701 }
10702 r.executeNesting++;
10703 r.executingStart = now;
10704 }
10705
10706 private final void sendServiceArgsLocked(ServiceRecord r,
10707 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010708 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010709 if (N == 0) {
10710 return;
10711 }
10712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010713 int i = 0;
10714 while (i < N) {
10715 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010716 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010717 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010718 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010719 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010720 // If somehow we got a dummy start at the front, then
10721 // just drop it here.
10722 i++;
10723 continue;
10724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725 bumpServiceExecutingLocked(r);
10726 if (!oomAdjusted) {
10727 oomAdjusted = true;
10728 updateOomAdjLocked(r.app);
10729 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010730 int flags = 0;
10731 if (si.deliveryCount > 0) {
10732 flags |= Service.START_FLAG_RETRY;
10733 }
10734 if (si.doneExecutingCount > 0) {
10735 flags |= Service.START_FLAG_REDELIVERY;
10736 }
10737 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10738 si.deliveredTime = SystemClock.uptimeMillis();
10739 r.deliveredStarts.add(si);
10740 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010741 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010742 } catch (RemoteException e) {
10743 // Remote process gone... we'll let the normal cleanup take
10744 // care of this.
10745 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010746 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010747 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010748 break;
10749 }
10750 }
10751 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010752 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 } else {
10754 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010756 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757 }
10758 }
10759 }
10760
10761 private final boolean requestServiceBindingLocked(ServiceRecord r,
10762 IntentBindRecord i, boolean rebind) {
10763 if (r.app == null || r.app.thread == null) {
10764 // If service is not currently running, can't yet bind.
10765 return false;
10766 }
10767 if ((!i.requested || rebind) && i.apps.size() > 0) {
10768 try {
10769 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010770 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010771 + ": shouldUnbind=" + i.hasBound);
10772 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10773 if (!rebind) {
10774 i.requested = true;
10775 }
10776 i.hasBound = true;
10777 i.doRebind = false;
10778 } catch (RemoteException e) {
10779 return false;
10780 }
10781 }
10782 return true;
10783 }
10784
10785 private final void requestServiceBindingsLocked(ServiceRecord r) {
10786 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10787 while (bindings.hasNext()) {
10788 IntentBindRecord i = bindings.next();
10789 if (!requestServiceBindingLocked(r, i, false)) {
10790 break;
10791 }
10792 }
10793 }
10794
10795 private final void realStartServiceLocked(ServiceRecord r,
10796 ProcessRecord app) throws RemoteException {
10797 if (app.thread == null) {
10798 throw new RemoteException();
10799 }
10800
10801 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010802 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010803
10804 app.services.add(r);
10805 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010806 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010807
10808 boolean created = false;
10809 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010810 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010811 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010812 mStringBuilder.setLength(0);
10813 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010814 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010815 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010816 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 synchronized (r.stats.getBatteryStats()) {
10818 r.stats.startLaunchedLocked();
10819 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010820 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010821 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010822 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010823 created = true;
10824 } finally {
10825 if (!created) {
10826 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010827 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010828 }
10829 }
10830
10831 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010832
10833 // If the service is in the started state, and there are no
10834 // pending arguments, then fake up one so its onStartCommand() will
10835 // be called.
10836 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10837 r.lastStartId++;
10838 if (r.lastStartId < 1) {
10839 r.lastStartId = 1;
10840 }
10841 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10842 }
10843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010844 sendServiceArgsLocked(r, true);
10845 }
10846
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010847 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10848 boolean allowCancel) {
10849 boolean canceled = false;
10850
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010851 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010852 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010853 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010854
10855 // Any delivered but not yet finished starts should be put back
10856 // on the pending list.
10857 final int N = r.deliveredStarts.size();
10858 if (N > 0) {
10859 for (int i=N-1; i>=0; i--) {
10860 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10861 if (si.intent == null) {
10862 // We'll generate this again if needed.
10863 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10864 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10865 r.pendingStarts.add(0, si);
10866 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10867 dur *= 2;
10868 if (minDuration < dur) minDuration = dur;
10869 if (resetTime < dur) resetTime = dur;
10870 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010871 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010872 + r.name);
10873 canceled = true;
10874 }
10875 }
10876 r.deliveredStarts.clear();
10877 }
10878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010879 r.totalRestartCount++;
10880 if (r.restartDelay == 0) {
10881 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010882 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010883 } else {
10884 // If it has been a "reasonably long time" since the service
10885 // was started, then reset our restart duration back to
10886 // the beginning, so we don't infinitely increase the duration
10887 // on a service that just occasionally gets killed (which is
10888 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010889 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010890 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010891 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010892 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010893 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010894 if (r.restartDelay < minDuration) {
10895 r.restartDelay = minDuration;
10896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010897 }
10898 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010899
10900 r.nextRestartTime = now + r.restartDelay;
10901
10902 // Make sure that we don't end up restarting a bunch of services
10903 // all at the same time.
10904 boolean repeat;
10905 do {
10906 repeat = false;
10907 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10908 ServiceRecord r2 = mRestartingServices.get(i);
10909 if (r2 != r && r.nextRestartTime
10910 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10911 && r.nextRestartTime
10912 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10913 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10914 r.restartDelay = r.nextRestartTime - now;
10915 repeat = true;
10916 break;
10917 }
10918 }
10919 } while (repeat);
10920
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 if (!mRestartingServices.contains(r)) {
10922 mRestartingServices.add(r);
10923 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010924
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010925 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010928 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010930 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010931 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010932 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010933 r.shortName, r.restartDelay);
10934
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010935 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936 }
10937
10938 final void performServiceRestartLocked(ServiceRecord r) {
10939 if (!mRestartingServices.contains(r)) {
10940 return;
10941 }
10942 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10943 }
10944
10945 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10946 if (r.restartDelay == 0) {
10947 return false;
10948 }
10949 r.resetRestartCounter();
10950 mRestartingServices.remove(r);
10951 mHandler.removeCallbacks(r.restarter);
10952 return true;
10953 }
10954
10955 private final boolean bringUpServiceLocked(ServiceRecord r,
10956 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010957 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010958 //r.dump(" ");
10959
Dianne Hackborn36124872009-10-08 16:22:03 -070010960 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961 sendServiceArgsLocked(r, false);
10962 return true;
10963 }
10964
10965 if (!whileRestarting && r.restartDelay > 0) {
10966 // If waiting for a restart, then do nothing.
10967 return true;
10968 }
10969
Joe Onorato8a9b2202010-02-26 18:56:32 -080010970 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010971 + " " + r.intent);
10972
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010973 // We are now bringing the service up, so no longer in the
10974 // restarting state.
10975 mRestartingServices.remove(r);
10976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010977 final String appName = r.processName;
10978 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10979 if (app != null && app.thread != null) {
10980 try {
10981 realStartServiceLocked(r, app);
10982 return true;
10983 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010984 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 }
10986
10987 // If a dead object exception was thrown -- fall through to
10988 // restart the application.
10989 }
10990
Dianne Hackborn36124872009-10-08 16:22:03 -070010991 // Not running -- get it started, and enqueue this service record
10992 // to be executed when the app comes up.
10993 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10994 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010995 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070010996 + r.appInfo.packageName + "/"
10997 + r.appInfo.uid + " for service "
10998 + r.intent.getIntent() + ": process is bad");
10999 bringDownServiceLocked(r, true);
11000 return false;
11001 }
11002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011003 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011004 mPendingServices.add(r);
11005 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011006
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007 return true;
11008 }
11009
11010 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011011 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011012 //r.dump(" ");
11013
11014 // Does it still need to run?
11015 if (!force && r.startRequested) {
11016 return;
11017 }
11018 if (r.connections.size() > 0) {
11019 if (!force) {
11020 // XXX should probably keep a count of the number of auto-create
11021 // connections directly in the service.
11022 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11023 while (it.hasNext()) {
11024 ConnectionRecord cr = it.next();
11025 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11026 return;
11027 }
11028 }
11029 }
11030
11031 // Report to all of the connections that the service is no longer
11032 // available.
11033 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11034 while (it.hasNext()) {
11035 ConnectionRecord c = it.next();
11036 try {
11037 // todo: shouldn't be a synchronous call!
11038 c.conn.connected(r.name, null);
11039 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011040 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 " to connection " + c.conn.asBinder() +
11042 " (in " + c.binding.client.processName + ")", e);
11043 }
11044 }
11045 }
11046
11047 // Tell the service that it has been unbound.
11048 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11049 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11050 while (it.hasNext()) {
11051 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011052 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 + ": hasBound=" + ibr.hasBound);
11054 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11055 try {
11056 bumpServiceExecutingLocked(r);
11057 updateOomAdjLocked(r.app);
11058 ibr.hasBound = false;
11059 r.app.thread.scheduleUnbindService(r,
11060 ibr.intent.getIntent());
11061 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011062 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011063 + r.shortName, e);
11064 serviceDoneExecutingLocked(r, true);
11065 }
11066 }
11067 }
11068 }
11069
Joe Onorato8a9b2202010-02-26 18:56:32 -080011070 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011071 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011072 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011073 System.identityHashCode(r), r.shortName,
11074 (r.app != null) ? r.app.pid : -1);
11075
11076 mServices.remove(r.name);
11077 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011078 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 r.totalRestartCount = 0;
11080 unscheduleServiceRestartLocked(r);
11081
11082 // Also make sure it is not on the pending list.
11083 int N = mPendingServices.size();
11084 for (int i=0; i<N; i++) {
11085 if (mPendingServices.get(i) == r) {
11086 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011087 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011088 TAG, "Removed pending service: " + r.shortName);
11089 i--;
11090 N--;
11091 }
11092 }
11093
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011094 r.cancelNotification();
11095 r.isForeground = false;
11096 r.foregroundId = 0;
11097 r.foregroundNoti = null;
11098
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011099 // Clear start entries.
11100 r.deliveredStarts.clear();
11101 r.pendingStarts.clear();
11102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011103 if (r.app != null) {
11104 synchronized (r.stats.getBatteryStats()) {
11105 r.stats.stopLaunchedLocked();
11106 }
11107 r.app.services.remove(r);
11108 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011110 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011111 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011112 bumpServiceExecutingLocked(r);
11113 mStoppingServices.add(r);
11114 updateOomAdjLocked(r.app);
11115 r.app.thread.scheduleStopService(r);
11116 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011117 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011118 + r.shortName, e);
11119 serviceDoneExecutingLocked(r, true);
11120 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011121 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011122 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011123 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011124 TAG, "Removed service that has no process: " + r.shortName);
11125 }
11126 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011127 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011128 TAG, "Removed service that is not running: " + r.shortName);
11129 }
11130 }
11131
11132 ComponentName startServiceLocked(IApplicationThread caller,
11133 Intent service, String resolvedType,
11134 int callingPid, int callingUid) {
11135 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011136 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011137 + " type=" + resolvedType + " args=" + service.getExtras());
11138
11139 if (caller != null) {
11140 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11141 if (callerApp == null) {
11142 throw new SecurityException(
11143 "Unable to find app for caller " + caller
11144 + " (pid=" + Binder.getCallingPid()
11145 + ") when starting service " + service);
11146 }
11147 }
11148
11149 ServiceLookupResult res =
11150 retrieveServiceLocked(service, resolvedType,
11151 callingPid, callingUid);
11152 if (res == null) {
11153 return null;
11154 }
11155 if (res.record == null) {
11156 return new ComponentName("!", res.permission != null
11157 ? res.permission : "private to package");
11158 }
11159 ServiceRecord r = res.record;
11160 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011161 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011162 + r.shortName);
11163 }
11164 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011165 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011166 r.lastStartId++;
11167 if (r.lastStartId < 1) {
11168 r.lastStartId = 1;
11169 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011170 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011171 r.lastActivity = SystemClock.uptimeMillis();
11172 synchronized (r.stats.getBatteryStats()) {
11173 r.stats.startRunningLocked();
11174 }
11175 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11176 return new ComponentName("!", "Service process is bad");
11177 }
11178 return r.name;
11179 }
11180 }
11181
11182 public ComponentName startService(IApplicationThread caller, Intent service,
11183 String resolvedType) {
11184 // Refuse possible leaked file descriptors
11185 if (service != null && service.hasFileDescriptors() == true) {
11186 throw new IllegalArgumentException("File descriptors passed in Intent");
11187 }
11188
11189 synchronized(this) {
11190 final int callingPid = Binder.getCallingPid();
11191 final int callingUid = Binder.getCallingUid();
11192 final long origId = Binder.clearCallingIdentity();
11193 ComponentName res = startServiceLocked(caller, service,
11194 resolvedType, callingPid, callingUid);
11195 Binder.restoreCallingIdentity(origId);
11196 return res;
11197 }
11198 }
11199
11200 ComponentName startServiceInPackage(int uid,
11201 Intent service, String resolvedType) {
11202 synchronized(this) {
11203 final long origId = Binder.clearCallingIdentity();
11204 ComponentName res = startServiceLocked(null, service,
11205 resolvedType, -1, uid);
11206 Binder.restoreCallingIdentity(origId);
11207 return res;
11208 }
11209 }
11210
11211 public int stopService(IApplicationThread caller, Intent service,
11212 String resolvedType) {
11213 // Refuse possible leaked file descriptors
11214 if (service != null && service.hasFileDescriptors() == true) {
11215 throw new IllegalArgumentException("File descriptors passed in Intent");
11216 }
11217
11218 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011219 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 + " type=" + resolvedType);
11221
11222 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11223 if (caller != null && callerApp == null) {
11224 throw new SecurityException(
11225 "Unable to find app for caller " + caller
11226 + " (pid=" + Binder.getCallingPid()
11227 + ") when stopping service " + service);
11228 }
11229
11230 // If this service is active, make sure it is stopped.
11231 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11232 if (r != null) {
11233 if (r.record != null) {
11234 synchronized (r.record.stats.getBatteryStats()) {
11235 r.record.stats.stopRunningLocked();
11236 }
11237 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011238 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011239 final long origId = Binder.clearCallingIdentity();
11240 bringDownServiceLocked(r.record, false);
11241 Binder.restoreCallingIdentity(origId);
11242 return 1;
11243 }
11244 return -1;
11245 }
11246 }
11247
11248 return 0;
11249 }
11250
11251 public IBinder peekService(Intent service, String resolvedType) {
11252 // Refuse possible leaked file descriptors
11253 if (service != null && service.hasFileDescriptors() == true) {
11254 throw new IllegalArgumentException("File descriptors passed in Intent");
11255 }
11256
11257 IBinder ret = null;
11258
11259 synchronized(this) {
11260 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11261
11262 if (r != null) {
11263 // r.record is null if findServiceLocked() failed the caller permission check
11264 if (r.record == null) {
11265 throw new SecurityException(
11266 "Permission Denial: Accessing service " + r.record.name
11267 + " from pid=" + Binder.getCallingPid()
11268 + ", uid=" + Binder.getCallingUid()
11269 + " requires " + r.permission);
11270 }
11271 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11272 if (ib != null) {
11273 ret = ib.binder;
11274 }
11275 }
11276 }
11277
11278 return ret;
11279 }
11280
11281 public boolean stopServiceToken(ComponentName className, IBinder token,
11282 int startId) {
11283 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011284 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 + " " + token + " startId=" + startId);
11286 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011287 if (r != null) {
11288 if (startId >= 0) {
11289 // Asked to only stop if done with all work. Note that
11290 // to avoid leaks, we will take this as dropping all
11291 // start items up to and including this one.
11292 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11293 if (si != null) {
11294 while (r.deliveredStarts.size() > 0) {
11295 if (r.deliveredStarts.remove(0) == si) {
11296 break;
11297 }
11298 }
11299 }
11300
11301 if (r.lastStartId != startId) {
11302 return false;
11303 }
11304
11305 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011306 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011307 + " is last, but have " + r.deliveredStarts.size()
11308 + " remaining args");
11309 }
11310 }
11311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 synchronized (r.stats.getBatteryStats()) {
11313 r.stats.stopRunningLocked();
11314 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011315 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011316 }
11317 final long origId = Binder.clearCallingIdentity();
11318 bringDownServiceLocked(r, false);
11319 Binder.restoreCallingIdentity(origId);
11320 return true;
11321 }
11322 }
11323 return false;
11324 }
11325
11326 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011327 int id, Notification notification, boolean removeNotification) {
11328 final long origId = Binder.clearCallingIdentity();
11329 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011330 synchronized(this) {
11331 ServiceRecord r = findServiceLocked(className, token);
11332 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011333 if (id != 0) {
11334 if (notification == null) {
11335 throw new IllegalArgumentException("null notification");
11336 }
11337 if (r.foregroundId != id) {
11338 r.cancelNotification();
11339 r.foregroundId = id;
11340 }
11341 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11342 r.foregroundNoti = notification;
11343 r.isForeground = true;
11344 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011345 if (r.app != null) {
11346 updateServiceForegroundLocked(r.app, true);
11347 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011348 } else {
11349 if (r.isForeground) {
11350 r.isForeground = false;
11351 if (r.app != null) {
11352 updateServiceForegroundLocked(r.app, true);
11353 }
11354 }
11355 if (removeNotification) {
11356 r.cancelNotification();
11357 r.foregroundId = 0;
11358 r.foregroundNoti = null;
11359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 }
11361 }
11362 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011363 } finally {
11364 Binder.restoreCallingIdentity(origId);
11365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011366 }
11367
11368 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11369 boolean anyForeground = false;
11370 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11371 if (sr.isForeground) {
11372 anyForeground = true;
11373 break;
11374 }
11375 }
11376 if (anyForeground != proc.foregroundServices) {
11377 proc.foregroundServices = anyForeground;
11378 if (oomAdj) {
11379 updateOomAdjLocked();
11380 }
11381 }
11382 }
11383
11384 public int bindService(IApplicationThread caller, IBinder token,
11385 Intent service, String resolvedType,
11386 IServiceConnection connection, int flags) {
11387 // Refuse possible leaked file descriptors
11388 if (service != null && service.hasFileDescriptors() == true) {
11389 throw new IllegalArgumentException("File descriptors passed in Intent");
11390 }
11391
11392 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011393 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011394 + " type=" + resolvedType + " conn=" + connection.asBinder()
11395 + " flags=0x" + Integer.toHexString(flags));
11396 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11397 if (callerApp == null) {
11398 throw new SecurityException(
11399 "Unable to find app for caller " + caller
11400 + " (pid=" + Binder.getCallingPid()
11401 + ") when binding service " + service);
11402 }
11403
11404 HistoryRecord activity = null;
11405 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011406 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011407 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011408 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011409 return 0;
11410 }
11411 activity = (HistoryRecord)mHistory.get(aindex);
11412 }
11413
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011414 int clientLabel = 0;
11415 PendingIntent clientIntent = null;
11416
11417 if (callerApp.info.uid == Process.SYSTEM_UID) {
11418 // Hacky kind of thing -- allow system stuff to tell us
11419 // what they are, so we can report this elsewhere for
11420 // others to know why certain services are running.
11421 try {
11422 clientIntent = (PendingIntent)service.getParcelableExtra(
11423 Intent.EXTRA_CLIENT_INTENT);
11424 } catch (RuntimeException e) {
11425 }
11426 if (clientIntent != null) {
11427 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11428 if (clientLabel != 0) {
11429 // There are no useful extras in the intent, trash them.
11430 // System code calling with this stuff just needs to know
11431 // this will happen.
11432 service = service.cloneFilter();
11433 }
11434 }
11435 }
11436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011437 ServiceLookupResult res =
11438 retrieveServiceLocked(service, resolvedType,
11439 Binder.getCallingPid(), Binder.getCallingUid());
11440 if (res == null) {
11441 return 0;
11442 }
11443 if (res.record == null) {
11444 return -1;
11445 }
11446 ServiceRecord s = res.record;
11447
11448 final long origId = Binder.clearCallingIdentity();
11449
11450 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011451 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011452 + s.shortName);
11453 }
11454
11455 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11456 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011457 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011458
11459 IBinder binder = connection.asBinder();
11460 s.connections.put(binder, c);
11461 b.connections.add(c);
11462 if (activity != null) {
11463 if (activity.connections == null) {
11464 activity.connections = new HashSet<ConnectionRecord>();
11465 }
11466 activity.connections.add(c);
11467 }
11468 b.client.connections.add(c);
11469 mServiceConnections.put(binder, c);
11470
11471 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11472 s.lastActivity = SystemClock.uptimeMillis();
11473 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11474 return 0;
11475 }
11476 }
11477
11478 if (s.app != null) {
11479 // This could have made the service more important.
11480 updateOomAdjLocked(s.app);
11481 }
11482
Joe Onorato8a9b2202010-02-26 18:56:32 -080011483 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011484 + ": received=" + b.intent.received
11485 + " apps=" + b.intent.apps.size()
11486 + " doRebind=" + b.intent.doRebind);
11487
11488 if (s.app != null && b.intent.received) {
11489 // Service is already running, so we can immediately
11490 // publish the connection.
11491 try {
11492 c.conn.connected(s.name, b.intent.binder);
11493 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011494 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011495 + " to connection " + c.conn.asBinder()
11496 + " (in " + c.binding.client.processName + ")", e);
11497 }
11498
11499 // If this is the first app connected back to this binding,
11500 // and the service had previously asked to be told when
11501 // rebound, then do so.
11502 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11503 requestServiceBindingLocked(s, b.intent, true);
11504 }
11505 } else if (!b.intent.requested) {
11506 requestServiceBindingLocked(s, b.intent, false);
11507 }
11508
11509 Binder.restoreCallingIdentity(origId);
11510 }
11511
11512 return 1;
11513 }
11514
11515 private void removeConnectionLocked(
11516 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11517 IBinder binder = c.conn.asBinder();
11518 AppBindRecord b = c.binding;
11519 ServiceRecord s = b.service;
11520 s.connections.remove(binder);
11521 b.connections.remove(c);
11522 if (c.activity != null && c.activity != skipAct) {
11523 if (c.activity.connections != null) {
11524 c.activity.connections.remove(c);
11525 }
11526 }
11527 if (b.client != skipApp) {
11528 b.client.connections.remove(c);
11529 }
11530 mServiceConnections.remove(binder);
11531
11532 if (b.connections.size() == 0) {
11533 b.intent.apps.remove(b.client);
11534 }
11535
Joe Onorato8a9b2202010-02-26 18:56:32 -080011536 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011537 + ": shouldUnbind=" + b.intent.hasBound);
11538 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11539 && b.intent.hasBound) {
11540 try {
11541 bumpServiceExecutingLocked(s);
11542 updateOomAdjLocked(s.app);
11543 b.intent.hasBound = false;
11544 // Assume the client doesn't want to know about a rebind;
11545 // we will deal with that later if it asks for one.
11546 b.intent.doRebind = false;
11547 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11548 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011549 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011550 serviceDoneExecutingLocked(s, true);
11551 }
11552 }
11553
11554 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11555 bringDownServiceLocked(s, false);
11556 }
11557 }
11558
11559 public boolean unbindService(IServiceConnection connection) {
11560 synchronized (this) {
11561 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011562 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 ConnectionRecord r = mServiceConnections.get(binder);
11564 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011565 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566 + connection.asBinder());
11567 return false;
11568 }
11569
11570 final long origId = Binder.clearCallingIdentity();
11571
11572 removeConnectionLocked(r, null, null);
11573
11574 if (r.binding.service.app != null) {
11575 // This could have made the service less important.
11576 updateOomAdjLocked(r.binding.service.app);
11577 }
11578
11579 Binder.restoreCallingIdentity(origId);
11580 }
11581
11582 return true;
11583 }
11584
11585 public void publishService(IBinder token, Intent intent, IBinder service) {
11586 // Refuse possible leaked file descriptors
11587 if (intent != null && intent.hasFileDescriptors() == true) {
11588 throw new IllegalArgumentException("File descriptors passed in Intent");
11589 }
11590
11591 synchronized(this) {
11592 if (!(token instanceof ServiceRecord)) {
11593 throw new IllegalArgumentException("Invalid service token");
11594 }
11595 ServiceRecord r = (ServiceRecord)token;
11596
11597 final long origId = Binder.clearCallingIdentity();
11598
Joe Onorato8a9b2202010-02-26 18:56:32 -080011599 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011600 + " " + intent + ": " + service);
11601 if (r != null) {
11602 Intent.FilterComparison filter
11603 = new Intent.FilterComparison(intent);
11604 IntentBindRecord b = r.bindings.get(filter);
11605 if (b != null && !b.received) {
11606 b.binder = service;
11607 b.requested = true;
11608 b.received = true;
11609 if (r.connections.size() > 0) {
11610 Iterator<ConnectionRecord> it
11611 = r.connections.values().iterator();
11612 while (it.hasNext()) {
11613 ConnectionRecord c = it.next();
11614 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011615 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011617 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011618 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011619 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 TAG, "Published intent: " + intent);
11621 continue;
11622 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011623 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011624 try {
11625 c.conn.connected(r.name, service);
11626 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011627 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 " to connection " + c.conn.asBinder() +
11629 " (in " + c.binding.client.processName + ")", e);
11630 }
11631 }
11632 }
11633 }
11634
11635 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11636
11637 Binder.restoreCallingIdentity(origId);
11638 }
11639 }
11640 }
11641
11642 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11643 // Refuse possible leaked file descriptors
11644 if (intent != null && intent.hasFileDescriptors() == true) {
11645 throw new IllegalArgumentException("File descriptors passed in Intent");
11646 }
11647
11648 synchronized(this) {
11649 if (!(token instanceof ServiceRecord)) {
11650 throw new IllegalArgumentException("Invalid service token");
11651 }
11652 ServiceRecord r = (ServiceRecord)token;
11653
11654 final long origId = Binder.clearCallingIdentity();
11655
11656 if (r != null) {
11657 Intent.FilterComparison filter
11658 = new Intent.FilterComparison(intent);
11659 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011660 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011661 + " at " + b + ": apps="
11662 + (b != null ? b.apps.size() : 0));
11663 if (b != null) {
11664 if (b.apps.size() > 0) {
11665 // Applications have already bound since the last
11666 // unbind, so just rebind right here.
11667 requestServiceBindingLocked(r, b, true);
11668 } else {
11669 // Note to tell the service the next time there is
11670 // a new client.
11671 b.doRebind = true;
11672 }
11673 }
11674
11675 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11676
11677 Binder.restoreCallingIdentity(origId);
11678 }
11679 }
11680 }
11681
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011682 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011683 synchronized(this) {
11684 if (!(token instanceof ServiceRecord)) {
11685 throw new IllegalArgumentException("Invalid service token");
11686 }
11687 ServiceRecord r = (ServiceRecord)token;
11688 boolean inStopping = mStoppingServices.contains(token);
11689 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011690 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011691 + ": nesting=" + r.executeNesting
11692 + ", inStopping=" + inStopping);
11693 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011694 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011695 + " with incorrect token: given " + token
11696 + ", expected " + r);
11697 return;
11698 }
11699
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011700 if (type == 1) {
11701 // This is a call from a service start... take care of
11702 // book-keeping.
11703 r.callStart = true;
11704 switch (res) {
11705 case Service.START_STICKY_COMPATIBILITY:
11706 case Service.START_STICKY: {
11707 // We are done with the associated start arguments.
11708 r.findDeliveredStart(startId, true);
11709 // Don't stop if killed.
11710 r.stopIfKilled = false;
11711 break;
11712 }
11713 case Service.START_NOT_STICKY: {
11714 // We are done with the associated start arguments.
11715 r.findDeliveredStart(startId, true);
11716 if (r.lastStartId == startId) {
11717 // There is no more work, and this service
11718 // doesn't want to hang around if killed.
11719 r.stopIfKilled = true;
11720 }
11721 break;
11722 }
11723 case Service.START_REDELIVER_INTENT: {
11724 // We'll keep this item until they explicitly
11725 // call stop for it, but keep track of the fact
11726 // that it was delivered.
11727 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11728 if (si != null) {
11729 si.deliveryCount = 0;
11730 si.doneExecutingCount++;
11731 // Don't stop if killed.
11732 r.stopIfKilled = true;
11733 }
11734 break;
11735 }
11736 default:
11737 throw new IllegalArgumentException(
11738 "Unknown service start result: " + res);
11739 }
11740 if (res == Service.START_STICKY_COMPATIBILITY) {
11741 r.callStart = false;
11742 }
11743 }
11744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011745 final long origId = Binder.clearCallingIdentity();
11746 serviceDoneExecutingLocked(r, inStopping);
11747 Binder.restoreCallingIdentity(origId);
11748 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011749 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750 + " with token " + token);
11751 }
11752 }
11753 }
11754
11755 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11756 r.executeNesting--;
11757 if (r.executeNesting <= 0 && r.app != null) {
11758 r.app.executingServices.remove(r);
11759 if (r.app.executingServices.size() == 0) {
11760 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11761 }
11762 if (inStopping) {
11763 mStoppingServices.remove(r);
11764 }
11765 updateOomAdjLocked(r.app);
11766 }
11767 }
11768
11769 void serviceTimeout(ProcessRecord proc) {
11770 synchronized(this) {
11771 if (proc.executingServices.size() == 0 || proc.thread == null) {
11772 return;
11773 }
11774 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11775 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11776 ServiceRecord timeout = null;
11777 long nextTime = 0;
11778 while (it.hasNext()) {
11779 ServiceRecord sr = it.next();
11780 if (sr.executingStart < maxTime) {
11781 timeout = sr;
11782 break;
11783 }
11784 if (sr.executingStart > nextTime) {
11785 nextTime = sr.executingStart;
11786 }
11787 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011788 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011789 Slog.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011790 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011791 } else {
11792 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11793 msg.obj = proc;
11794 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11795 }
11796 }
11797 }
11798
11799 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011800 // BACKUP AND RESTORE
11801 // =========================================================
11802
11803 // Cause the target app to be launched if necessary and its backup agent
11804 // instantiated. The backup agent will invoke backupAgentCreated() on the
11805 // activity manager to announce its creation.
11806 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011807 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011808 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11809
11810 synchronized(this) {
11811 // !!! TODO: currently no check here that we're already bound
11812 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11813 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11814 synchronized (stats) {
11815 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11816 }
11817
11818 BackupRecord r = new BackupRecord(ss, app, backupMode);
11819 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11820 // startProcessLocked() returns existing proc's record if it's already running
11821 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011822 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011823 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011824 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011825 return false;
11826 }
11827
11828 r.app = proc;
11829 mBackupTarget = r;
11830 mBackupAppName = app.packageName;
11831
Christopher Tate6fa95972009-06-05 18:43:55 -070011832 // Try not to kill the process during backup
11833 updateOomAdjLocked(proc);
11834
Christopher Tate181fafa2009-05-14 11:12:14 -070011835 // If the process is already attached, schedule the creation of the backup agent now.
11836 // If it is not yet live, this will be done when it attaches to the framework.
11837 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011838 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011839 try {
11840 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11841 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011842 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011843 }
11844 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011845 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011846 }
11847 // Invariants: at this point, the target app process exists and the application
11848 // is either already running or in the process of coming up. mBackupTarget and
11849 // mBackupAppName describe the app, so that when it binds back to the AM we
11850 // know that it's scheduled for a backup-agent operation.
11851 }
11852
11853 return true;
11854 }
11855
11856 // A backup agent has just come up
11857 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011858 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011859 + " = " + agent);
11860
11861 synchronized(this) {
11862 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011863 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011864 return;
11865 }
11866
Christopher Tate043dadc2009-06-02 16:11:00 -070011867 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011868 try {
11869 IBackupManager bm = IBackupManager.Stub.asInterface(
11870 ServiceManager.getService(Context.BACKUP_SERVICE));
11871 bm.agentConnected(agentPackageName, agent);
11872 } catch (RemoteException e) {
11873 // can't happen; the backup manager service is local
11874 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011875 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070011876 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011877 } finally {
11878 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011879 }
11880 }
11881 }
11882
11883 // done with this agent
11884 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011885 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011886 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011887 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011888 return;
11889 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011890
11891 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011892 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011893 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011894 return;
11895 }
11896
Christopher Tate181fafa2009-05-14 11:12:14 -070011897 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011898 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011899 return;
11900 }
11901
Christopher Tate6fa95972009-06-05 18:43:55 -070011902 ProcessRecord proc = mBackupTarget.app;
11903 mBackupTarget = null;
11904 mBackupAppName = null;
11905
11906 // Not backing this app up any more; reset its OOM adjustment
11907 updateOomAdjLocked(proc);
11908
Christopher Tatec7b31e32009-06-10 15:49:30 -070011909 // If the app crashed during backup, 'thread' will be null here
11910 if (proc.thread != null) {
11911 try {
11912 proc.thread.scheduleDestroyBackupAgent(appInfo);
11913 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011914 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070011915 e.printStackTrace();
11916 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011917 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011918 }
11919 }
11920 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011921 // BROADCASTS
11922 // =========================================================
11923
11924 private final List getStickies(String action, IntentFilter filter,
11925 List cur) {
11926 final ContentResolver resolver = mContext.getContentResolver();
11927 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11928 if (list == null) {
11929 return cur;
11930 }
11931 int N = list.size();
11932 for (int i=0; i<N; i++) {
11933 Intent intent = list.get(i);
11934 if (filter.match(resolver, intent, true, TAG) >= 0) {
11935 if (cur == null) {
11936 cur = new ArrayList<Intent>();
11937 }
11938 cur.add(intent);
11939 }
11940 }
11941 return cur;
11942 }
11943
11944 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011945 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011946 + mBroadcastsScheduled);
11947
11948 if (mBroadcastsScheduled) {
11949 return;
11950 }
11951 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11952 mBroadcastsScheduled = true;
11953 }
11954
11955 public Intent registerReceiver(IApplicationThread caller,
11956 IIntentReceiver receiver, IntentFilter filter, String permission) {
11957 synchronized(this) {
11958 ProcessRecord callerApp = null;
11959 if (caller != null) {
11960 callerApp = getRecordForAppLocked(caller);
11961 if (callerApp == null) {
11962 throw new SecurityException(
11963 "Unable to find app for caller " + caller
11964 + " (pid=" + Binder.getCallingPid()
11965 + ") when registering receiver " + receiver);
11966 }
11967 }
11968
11969 List allSticky = null;
11970
11971 // Look for any matching sticky broadcasts...
11972 Iterator actions = filter.actionsIterator();
11973 if (actions != null) {
11974 while (actions.hasNext()) {
11975 String action = (String)actions.next();
11976 allSticky = getStickies(action, filter, allSticky);
11977 }
11978 } else {
11979 allSticky = getStickies(null, filter, allSticky);
11980 }
11981
11982 // The first sticky in the list is returned directly back to
11983 // the client.
11984 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11985
Joe Onorato8a9b2202010-02-26 18:56:32 -080011986 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011987 + ": " + sticky);
11988
11989 if (receiver == null) {
11990 return sticky;
11991 }
11992
11993 ReceiverList rl
11994 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11995 if (rl == null) {
11996 rl = new ReceiverList(this, callerApp,
11997 Binder.getCallingPid(),
11998 Binder.getCallingUid(), receiver);
11999 if (rl.app != null) {
12000 rl.app.receivers.add(rl);
12001 } else {
12002 try {
12003 receiver.asBinder().linkToDeath(rl, 0);
12004 } catch (RemoteException e) {
12005 return sticky;
12006 }
12007 rl.linkedToDeath = true;
12008 }
12009 mRegisteredReceivers.put(receiver.asBinder(), rl);
12010 }
12011 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12012 rl.add(bf);
12013 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012014 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012015 }
12016 mReceiverResolver.addFilter(bf);
12017
12018 // Enqueue broadcasts for all existing stickies that match
12019 // this filter.
12020 if (allSticky != null) {
12021 ArrayList receivers = new ArrayList();
12022 receivers.add(bf);
12023
12024 int N = allSticky.size();
12025 for (int i=0; i<N; i++) {
12026 Intent intent = (Intent)allSticky.get(i);
12027 BroadcastRecord r = new BroadcastRecord(intent, null,
12028 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012029 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012030 if (mParallelBroadcasts.size() == 0) {
12031 scheduleBroadcastsLocked();
12032 }
12033 mParallelBroadcasts.add(r);
12034 }
12035 }
12036
12037 return sticky;
12038 }
12039 }
12040
12041 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012042 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012043
12044 boolean doNext = false;
12045
12046 synchronized(this) {
12047 ReceiverList rl
12048 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12049 if (rl != null) {
12050 if (rl.curBroadcast != null) {
12051 BroadcastRecord r = rl.curBroadcast;
12052 doNext = finishReceiverLocked(
12053 receiver.asBinder(), r.resultCode, r.resultData,
12054 r.resultExtras, r.resultAbort, true);
12055 }
12056
12057 if (rl.app != null) {
12058 rl.app.receivers.remove(rl);
12059 }
12060 removeReceiverLocked(rl);
12061 if (rl.linkedToDeath) {
12062 rl.linkedToDeath = false;
12063 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12064 }
12065 }
12066 }
12067
12068 if (!doNext) {
12069 return;
12070 }
12071
12072 final long origId = Binder.clearCallingIdentity();
12073 processNextBroadcast(false);
12074 trimApplications();
12075 Binder.restoreCallingIdentity(origId);
12076 }
12077
12078 void removeReceiverLocked(ReceiverList rl) {
12079 mRegisteredReceivers.remove(rl.receiver.asBinder());
12080 int N = rl.size();
12081 for (int i=0; i<N; i++) {
12082 mReceiverResolver.removeFilter(rl.get(i));
12083 }
12084 }
12085
12086 private final int broadcastIntentLocked(ProcessRecord callerApp,
12087 String callerPackage, Intent intent, String resolvedType,
12088 IIntentReceiver resultTo, int resultCode, String resultData,
12089 Bundle map, String requiredPermission,
12090 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12091 intent = new Intent(intent);
12092
Joe Onorato8a9b2202010-02-26 18:56:32 -080012093 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12095 + " ordered=" + ordered);
12096 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012097 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012098 }
12099
12100 // Handle special intents: if this broadcast is from the package
12101 // manager about a package being removed, we need to remove all of
12102 // its activities from the history stack.
12103 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12104 intent.getAction());
12105 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12106 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012107 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012108 || uidRemoved) {
12109 if (checkComponentPermission(
12110 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12111 callingPid, callingUid, -1)
12112 == PackageManager.PERMISSION_GRANTED) {
12113 if (uidRemoved) {
12114 final Bundle intentExtras = intent.getExtras();
12115 final int uid = intentExtras != null
12116 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12117 if (uid >= 0) {
12118 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12119 synchronized (bs) {
12120 bs.removeUidStatsLocked(uid);
12121 }
12122 }
12123 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012124 // If resources are unvailble just force stop all
12125 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012126 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012127 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12128 if (list != null && (list.length > 0)) {
12129 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012130 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012131 }
12132 }
12133 } else {
12134 Uri data = intent.getData();
12135 String ssp;
12136 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12137 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12138 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012139 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012141 }
12142 }
12143 }
12144 } else {
12145 String msg = "Permission Denial: " + intent.getAction()
12146 + " broadcast from " + callerPackage + " (pid=" + callingPid
12147 + ", uid=" + callingUid + ")"
12148 + " requires "
12149 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012150 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012151 throw new SecurityException(msg);
12152 }
12153 }
12154
12155 /*
12156 * If this is the time zone changed action, queue up a message that will reset the timezone
12157 * of all currently running processes. This message will get queued up before the broadcast
12158 * happens.
12159 */
12160 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12161 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12162 }
12163
Dianne Hackborn854060af2009-07-09 18:14:31 -070012164 /*
12165 * Prevent non-system code (defined here to be non-persistent
12166 * processes) from sending protected broadcasts.
12167 */
12168 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12169 || callingUid == Process.SHELL_UID || callingUid == 0) {
12170 // Always okay.
12171 } else if (callerApp == null || !callerApp.persistent) {
12172 try {
12173 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12174 intent.getAction())) {
12175 String msg = "Permission Denial: not allowed to send broadcast "
12176 + intent.getAction() + " from pid="
12177 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012178 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012179 throw new SecurityException(msg);
12180 }
12181 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012182 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012183 return BROADCAST_SUCCESS;
12184 }
12185 }
12186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012187 // Add to the sticky list if requested.
12188 if (sticky) {
12189 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12190 callingPid, callingUid)
12191 != PackageManager.PERMISSION_GRANTED) {
12192 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12193 + callingPid + ", uid=" + callingUid
12194 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012195 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012196 throw new SecurityException(msg);
12197 }
12198 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012199 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012200 + " and enforce permission " + requiredPermission);
12201 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12202 }
12203 if (intent.getComponent() != null) {
12204 throw new SecurityException(
12205 "Sticky broadcasts can't target a specific component");
12206 }
12207 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12208 if (list == null) {
12209 list = new ArrayList<Intent>();
12210 mStickyBroadcasts.put(intent.getAction(), list);
12211 }
12212 int N = list.size();
12213 int i;
12214 for (i=0; i<N; i++) {
12215 if (intent.filterEquals(list.get(i))) {
12216 // This sticky already exists, replace it.
12217 list.set(i, new Intent(intent));
12218 break;
12219 }
12220 }
12221 if (i >= N) {
12222 list.add(new Intent(intent));
12223 }
12224 }
12225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 // Figure out who all will receive this broadcast.
12227 List receivers = null;
12228 List<BroadcastFilter> registeredReceivers = null;
12229 try {
12230 if (intent.getComponent() != null) {
12231 // Broadcast is going to one specific receiver class...
12232 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012233 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012234 if (ai != null) {
12235 receivers = new ArrayList();
12236 ResolveInfo ri = new ResolveInfo();
12237 ri.activityInfo = ai;
12238 receivers.add(ri);
12239 }
12240 } else {
12241 // Need to resolve the intent to interested receivers...
12242 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12243 == 0) {
12244 receivers =
12245 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012246 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012247 }
Mihai Preda074edef2009-05-18 17:13:31 +020012248 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012249 }
12250 } catch (RemoteException ex) {
12251 // pm is in same process, this will never happen.
12252 }
12253
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012254 final boolean replacePending =
12255 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12256
Joe Onorato8a9b2202010-02-26 18:56:32 -080012257 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012258 + " replacePending=" + replacePending);
12259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012260 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12261 if (!ordered && NR > 0) {
12262 // If we are not serializing this broadcast, then send the
12263 // registered receivers separately so they don't wait for the
12264 // components to be launched.
12265 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12266 callerPackage, callingPid, callingUid, requiredPermission,
12267 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012268 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012269 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012270 TAG, "Enqueueing parallel broadcast " + r
12271 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012272 boolean replaced = false;
12273 if (replacePending) {
12274 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12275 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012276 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012277 "***** DROPPING PARALLEL: " + intent);
12278 mParallelBroadcasts.set(i, r);
12279 replaced = true;
12280 break;
12281 }
12282 }
12283 }
12284 if (!replaced) {
12285 mParallelBroadcasts.add(r);
12286 scheduleBroadcastsLocked();
12287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012288 registeredReceivers = null;
12289 NR = 0;
12290 }
12291
12292 // Merge into one list.
12293 int ir = 0;
12294 if (receivers != null) {
12295 // A special case for PACKAGE_ADDED: do not allow the package
12296 // being added to see this broadcast. This prevents them from
12297 // using this as a back door to get run as soon as they are
12298 // installed. Maybe in the future we want to have a special install
12299 // broadcast or such for apps, but we'd like to deliberately make
12300 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012301 String skipPackages[] = null;
12302 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12303 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12304 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12305 Uri data = intent.getData();
12306 if (data != null) {
12307 String pkgName = data.getSchemeSpecificPart();
12308 if (pkgName != null) {
12309 skipPackages = new String[] { pkgName };
12310 }
12311 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012312 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012313 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012314 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012315 if (skipPackages != null && (skipPackages.length > 0)) {
12316 for (String skipPackage : skipPackages) {
12317 if (skipPackage != null) {
12318 int NT = receivers.size();
12319 for (int it=0; it<NT; it++) {
12320 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12321 if (curt.activityInfo.packageName.equals(skipPackage)) {
12322 receivers.remove(it);
12323 it--;
12324 NT--;
12325 }
12326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012327 }
12328 }
12329 }
12330
12331 int NT = receivers != null ? receivers.size() : 0;
12332 int it = 0;
12333 ResolveInfo curt = null;
12334 BroadcastFilter curr = null;
12335 while (it < NT && ir < NR) {
12336 if (curt == null) {
12337 curt = (ResolveInfo)receivers.get(it);
12338 }
12339 if (curr == null) {
12340 curr = registeredReceivers.get(ir);
12341 }
12342 if (curr.getPriority() >= curt.priority) {
12343 // Insert this broadcast record into the final list.
12344 receivers.add(it, curr);
12345 ir++;
12346 curr = null;
12347 it++;
12348 NT++;
12349 } else {
12350 // Skip to the next ResolveInfo in the final list.
12351 it++;
12352 curt = null;
12353 }
12354 }
12355 }
12356 while (ir < NR) {
12357 if (receivers == null) {
12358 receivers = new ArrayList();
12359 }
12360 receivers.add(registeredReceivers.get(ir));
12361 ir++;
12362 }
12363
12364 if ((receivers != null && receivers.size() > 0)
12365 || resultTo != null) {
12366 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12367 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012368 receivers, resultTo, resultCode, resultData, map, ordered,
12369 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012370 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012371 TAG, "Enqueueing ordered broadcast " + r
12372 + ": prev had " + mOrderedBroadcasts.size());
12373 if (DEBUG_BROADCAST) {
12374 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012375 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012376 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012377 boolean replaced = false;
12378 if (replacePending) {
12379 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12380 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012381 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012382 "***** DROPPING ORDERED: " + intent);
12383 mOrderedBroadcasts.set(i, r);
12384 replaced = true;
12385 break;
12386 }
12387 }
12388 }
12389 if (!replaced) {
12390 mOrderedBroadcasts.add(r);
12391 scheduleBroadcastsLocked();
12392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012393 }
12394
12395 return BROADCAST_SUCCESS;
12396 }
12397
12398 public final int broadcastIntent(IApplicationThread caller,
12399 Intent intent, String resolvedType, IIntentReceiver resultTo,
12400 int resultCode, String resultData, Bundle map,
12401 String requiredPermission, boolean serialized, boolean sticky) {
12402 // Refuse possible leaked file descriptors
12403 if (intent != null && intent.hasFileDescriptors() == true) {
12404 throw new IllegalArgumentException("File descriptors passed in Intent");
12405 }
12406
12407 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012408 int flags = intent.getFlags();
12409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012410 if (!mSystemReady) {
12411 // if the caller really truly claims to know what they're doing, go
12412 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012413 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12414 intent = new Intent(intent);
12415 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12416 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012417 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012418 + " before boot completion");
12419 throw new IllegalStateException("Cannot broadcast before boot completed");
12420 }
12421 }
12422
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012423 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12424 throw new IllegalArgumentException(
12425 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12426 }
12427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012428 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12429 final int callingPid = Binder.getCallingPid();
12430 final int callingUid = Binder.getCallingUid();
12431 final long origId = Binder.clearCallingIdentity();
12432 int res = broadcastIntentLocked(callerApp,
12433 callerApp != null ? callerApp.info.packageName : null,
12434 intent, resolvedType, resultTo,
12435 resultCode, resultData, map, requiredPermission, serialized,
12436 sticky, callingPid, callingUid);
12437 Binder.restoreCallingIdentity(origId);
12438 return res;
12439 }
12440 }
12441
12442 int broadcastIntentInPackage(String packageName, int uid,
12443 Intent intent, String resolvedType, IIntentReceiver resultTo,
12444 int resultCode, String resultData, Bundle map,
12445 String requiredPermission, boolean serialized, boolean sticky) {
12446 synchronized(this) {
12447 final long origId = Binder.clearCallingIdentity();
12448 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12449 resultTo, resultCode, resultData, map, requiredPermission,
12450 serialized, sticky, -1, uid);
12451 Binder.restoreCallingIdentity(origId);
12452 return res;
12453 }
12454 }
12455
12456 public final void unbroadcastIntent(IApplicationThread caller,
12457 Intent intent) {
12458 // Refuse possible leaked file descriptors
12459 if (intent != null && intent.hasFileDescriptors() == true) {
12460 throw new IllegalArgumentException("File descriptors passed in Intent");
12461 }
12462
12463 synchronized(this) {
12464 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12465 != PackageManager.PERMISSION_GRANTED) {
12466 String msg = "Permission Denial: unbroadcastIntent() from pid="
12467 + Binder.getCallingPid()
12468 + ", uid=" + Binder.getCallingUid()
12469 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012470 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012471 throw new SecurityException(msg);
12472 }
12473 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12474 if (list != null) {
12475 int N = list.size();
12476 int i;
12477 for (i=0; i<N; i++) {
12478 if (intent.filterEquals(list.get(i))) {
12479 list.remove(i);
12480 break;
12481 }
12482 }
12483 }
12484 }
12485 }
12486
12487 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12488 String resultData, Bundle resultExtras, boolean resultAbort,
12489 boolean explicit) {
12490 if (mOrderedBroadcasts.size() == 0) {
12491 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012492 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012493 }
12494 return false;
12495 }
12496 BroadcastRecord r = mOrderedBroadcasts.get(0);
12497 if (r.receiver == null) {
12498 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012499 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012500 }
12501 return false;
12502 }
12503 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012504 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012505 return false;
12506 }
12507 int state = r.state;
12508 r.state = r.IDLE;
12509 if (state == r.IDLE) {
12510 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012511 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012512 }
12513 }
12514 r.receiver = null;
12515 r.intent.setComponent(null);
12516 if (r.curApp != null) {
12517 r.curApp.curReceiver = null;
12518 }
12519 if (r.curFilter != null) {
12520 r.curFilter.receiverList.curBroadcast = null;
12521 }
12522 r.curFilter = null;
12523 r.curApp = null;
12524 r.curComponent = null;
12525 r.curReceiver = null;
12526 mPendingBroadcast = null;
12527
12528 r.resultCode = resultCode;
12529 r.resultData = resultData;
12530 r.resultExtras = resultExtras;
12531 r.resultAbort = resultAbort;
12532
12533 // We will process the next receiver right now if this is finishing
12534 // an app receiver (which is always asynchronous) or after we have
12535 // come back from calling a receiver.
12536 return state == BroadcastRecord.APP_RECEIVE
12537 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12538 }
12539
12540 public void finishReceiver(IBinder who, int resultCode, String resultData,
12541 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012542 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012543
12544 // Refuse possible leaked file descriptors
12545 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12546 throw new IllegalArgumentException("File descriptors passed in Bundle");
12547 }
12548
12549 boolean doNext;
12550
12551 final long origId = Binder.clearCallingIdentity();
12552
12553 synchronized(this) {
12554 doNext = finishReceiverLocked(
12555 who, resultCode, resultData, resultExtras, resultAbort, true);
12556 }
12557
12558 if (doNext) {
12559 processNextBroadcast(false);
12560 }
12561 trimApplications();
12562
12563 Binder.restoreCallingIdentity(origId);
12564 }
12565
12566 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12567 if (r.nextReceiver > 0) {
12568 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12569 if (curReceiver instanceof BroadcastFilter) {
12570 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012571 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012572 System.identityHashCode(r),
12573 r.intent.getAction(),
12574 r.nextReceiver - 1,
12575 System.identityHashCode(bf));
12576 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012577 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 System.identityHashCode(r),
12579 r.intent.getAction(),
12580 r.nextReceiver - 1,
12581 ((ResolveInfo)curReceiver).toString());
12582 }
12583 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012584 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012585 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012586 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012587 System.identityHashCode(r),
12588 r.intent.getAction(),
12589 r.nextReceiver,
12590 "NONE");
12591 }
12592 }
12593
12594 private final void broadcastTimeout() {
12595 synchronized (this) {
12596 if (mOrderedBroadcasts.size() == 0) {
12597 return;
12598 }
12599 long now = SystemClock.uptimeMillis();
12600 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012601 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012602 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012603 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012604 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012605 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012606 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012607 return;
12608 }
12609
Joe Onorato8a9b2202010-02-26 18:56:32 -080012610 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012611 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012612 r.anrCount++;
12613
12614 // Current receiver has passed its expiration date.
12615 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012616 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012617 return;
12618 }
12619
12620 ProcessRecord app = null;
12621
12622 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012623 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012624 logBroadcastReceiverDiscard(r);
12625 if (curReceiver instanceof BroadcastFilter) {
12626 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12627 if (bf.receiverList.pid != 0
12628 && bf.receiverList.pid != MY_PID) {
12629 synchronized (this.mPidsSelfLocked) {
12630 app = this.mPidsSelfLocked.get(
12631 bf.receiverList.pid);
12632 }
12633 }
12634 } else {
12635 app = r.curApp;
12636 }
12637
12638 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012639 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012640 }
12641
12642 if (mPendingBroadcast == r) {
12643 mPendingBroadcast = null;
12644 }
12645
12646 // Move on to the next receiver.
12647 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12648 r.resultExtras, r.resultAbort, true);
12649 scheduleBroadcastsLocked();
12650 }
12651 }
12652
12653 private final void processCurBroadcastLocked(BroadcastRecord r,
12654 ProcessRecord app) throws RemoteException {
12655 if (app.thread == null) {
12656 throw new RemoteException();
12657 }
12658 r.receiver = app.thread.asBinder();
12659 r.curApp = app;
12660 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012661 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012662
12663 // Tell the application to launch this receiver.
12664 r.intent.setComponent(r.curComponent);
12665
12666 boolean started = false;
12667 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012668 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012669 "Delivering to component " + r.curComponent
12670 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012671 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012672 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12673 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12674 started = true;
12675 } finally {
12676 if (!started) {
12677 r.receiver = null;
12678 r.curApp = null;
12679 app.curReceiver = null;
12680 }
12681 }
12682
12683 }
12684
12685 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012686 Intent intent, int resultCode, String data, Bundle extras,
12687 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012688 if (app != null && app.thread != null) {
12689 // If we have an app thread, do the call through that so it is
12690 // correctly ordered with other one-way calls.
12691 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012692 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012693 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012694 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012695 }
12696 }
12697
12698 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12699 BroadcastFilter filter, boolean ordered) {
12700 boolean skip = false;
12701 if (filter.requiredPermission != null) {
12702 int perm = checkComponentPermission(filter.requiredPermission,
12703 r.callingPid, r.callingUid, -1);
12704 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012705 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012706 + r.intent.toString()
12707 + " from " + r.callerPackage + " (pid="
12708 + r.callingPid + ", uid=" + r.callingUid + ")"
12709 + " requires " + filter.requiredPermission
12710 + " due to registered receiver " + filter);
12711 skip = true;
12712 }
12713 }
12714 if (r.requiredPermission != null) {
12715 int perm = checkComponentPermission(r.requiredPermission,
12716 filter.receiverList.pid, filter.receiverList.uid, -1);
12717 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012718 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012719 + r.intent.toString()
12720 + " to " + filter.receiverList.app
12721 + " (pid=" + filter.receiverList.pid
12722 + ", uid=" + filter.receiverList.uid + ")"
12723 + " requires " + r.requiredPermission
12724 + " due to sender " + r.callerPackage
12725 + " (uid " + r.callingUid + ")");
12726 skip = true;
12727 }
12728 }
12729
12730 if (!skip) {
12731 // If this is not being sent as an ordered broadcast, then we
12732 // don't want to touch the fields that keep track of the current
12733 // state of ordered broadcasts.
12734 if (ordered) {
12735 r.receiver = filter.receiverList.receiver.asBinder();
12736 r.curFilter = filter;
12737 filter.receiverList.curBroadcast = r;
12738 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012739 if (filter.receiverList.app != null) {
12740 // Bump hosting application to no longer be in background
12741 // scheduling class. Note that we can't do that if there
12742 // isn't an app... but we can only be in that case for
12743 // things that directly call the IActivityManager API, which
12744 // are already core system stuff so don't matter for this.
12745 r.curApp = filter.receiverList.app;
12746 filter.receiverList.app.curReceiver = r;
12747 updateOomAdjLocked();
12748 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012749 }
12750 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012751 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012752 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012753 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012754 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012755 }
12756 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12757 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012758 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012759 if (ordered) {
12760 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12761 }
12762 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012763 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012764 if (ordered) {
12765 r.receiver = null;
12766 r.curFilter = null;
12767 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012768 if (filter.receiverList.app != null) {
12769 filter.receiverList.app.curReceiver = null;
12770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012771 }
12772 }
12773 }
12774 }
12775
Dianne Hackborn12527f92009-11-11 17:39:50 -080012776 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12777 if (r.callingUid < 0) {
12778 // This was from a registerReceiver() call; ignore it.
12779 return;
12780 }
12781 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12782 MAX_BROADCAST_HISTORY-1);
12783 r.finishTime = SystemClock.uptimeMillis();
12784 mBroadcastHistory[0] = r;
12785 }
12786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012787 private final void processNextBroadcast(boolean fromMsg) {
12788 synchronized(this) {
12789 BroadcastRecord r;
12790
Joe Onorato8a9b2202010-02-26 18:56:32 -080012791 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012792 + mParallelBroadcasts.size() + " broadcasts, "
12793 + mOrderedBroadcasts.size() + " serialized broadcasts");
12794
12795 updateCpuStats();
12796
12797 if (fromMsg) {
12798 mBroadcastsScheduled = false;
12799 }
12800
12801 // First, deliver any non-serialized broadcasts right away.
12802 while (mParallelBroadcasts.size() > 0) {
12803 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012804 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012805 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012806 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012807 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012808 for (int i=0; i<N; i++) {
12809 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012810 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012811 "Delivering non-serialized to registered "
12812 + target + ": " + r);
12813 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12814 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012815 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012816 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012817 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012818 }
12819
12820 // Now take care of the next serialized one...
12821
12822 // If we are waiting for a process to come up to handle the next
12823 // broadcast, then do nothing at this point. Just in case, we
12824 // check that the process we're waiting for still exists.
12825 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012826 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012827 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012828 + mPendingBroadcast.curApp);
12829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012830
12831 boolean isDead;
12832 synchronized (mPidsSelfLocked) {
12833 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12834 }
12835 if (!isDead) {
12836 // It's still alive, so keep waiting
12837 return;
12838 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012839 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012840 + " died before responding to broadcast");
12841 mPendingBroadcast = null;
12842 }
12843 }
12844
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012845 boolean looped = false;
12846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012847 do {
12848 if (mOrderedBroadcasts.size() == 0) {
12849 // No more broadcasts pending, so all done!
12850 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012851 if (looped) {
12852 // If we had finished the last ordered broadcast, then
12853 // make sure all processes have correct oom and sched
12854 // adjustments.
12855 updateOomAdjLocked();
12856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012857 return;
12858 }
12859 r = mOrderedBroadcasts.get(0);
12860 boolean forceReceive = false;
12861
12862 // Ensure that even if something goes awry with the timeout
12863 // detection, we catch "hung" broadcasts here, discard them,
12864 // and continue to make progress.
12865 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12866 long now = SystemClock.uptimeMillis();
12867 if (r.dispatchTime > 0) {
12868 if ((numReceivers > 0) &&
12869 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012870 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012871 + " now=" + now
12872 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012873 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012874 + " intent=" + r.intent
12875 + " numReceivers=" + numReceivers
12876 + " nextReceiver=" + r.nextReceiver
12877 + " state=" + r.state);
12878 broadcastTimeout(); // forcibly finish this broadcast
12879 forceReceive = true;
12880 r.state = BroadcastRecord.IDLE;
12881 }
12882 }
12883
12884 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012885 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012886 "processNextBroadcast() called when not idle (state="
12887 + r.state + ")");
12888 return;
12889 }
12890
12891 if (r.receivers == null || r.nextReceiver >= numReceivers
12892 || r.resultAbort || forceReceive) {
12893 // No more receivers for this broadcast! Send the final
12894 // result if requested...
12895 if (r.resultTo != null) {
12896 try {
12897 if (DEBUG_BROADCAST) {
12898 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012899 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012900 + " seq=" + seq + " app=" + r.callerApp);
12901 }
12902 performReceive(r.callerApp, r.resultTo,
12903 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012904 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012905 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012906 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012907 }
12908 }
12909
Joe Onorato8a9b2202010-02-26 18:56:32 -080012910 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012911 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12912
Joe Onorato8a9b2202010-02-26 18:56:32 -080012913 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012914 + r);
12915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012916 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012917 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012918 mOrderedBroadcasts.remove(0);
12919 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012920 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012921 continue;
12922 }
12923 } while (r == null);
12924
12925 // Get the next receiver...
12926 int recIdx = r.nextReceiver++;
12927
12928 // Keep track of when this receiver started, and make sure there
12929 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012930 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012931 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012932 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012933
Joe Onorato8a9b2202010-02-26 18:56:32 -080012934 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012935 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012936 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012937 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012938 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012939 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012940 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012941 }
12942
12943 Object nextReceiver = r.receivers.get(recIdx);
12944 if (nextReceiver instanceof BroadcastFilter) {
12945 // Simple case: this is a registered receiver who gets
12946 // a direct call.
12947 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012948 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012949 "Delivering serialized to registered "
12950 + filter + ": " + r);
12951 deliverToRegisteredReceiver(r, filter, r.ordered);
12952 if (r.receiver == null || !r.ordered) {
12953 // The receiver has already finished, so schedule to
12954 // process the next one.
12955 r.state = BroadcastRecord.IDLE;
12956 scheduleBroadcastsLocked();
12957 }
12958 return;
12959 }
12960
12961 // Hard case: need to instantiate the receiver, possibly
12962 // starting its application process to host it.
12963
12964 ResolveInfo info =
12965 (ResolveInfo)nextReceiver;
12966
12967 boolean skip = false;
12968 int perm = checkComponentPermission(info.activityInfo.permission,
12969 r.callingPid, r.callingUid,
12970 info.activityInfo.exported
12971 ? -1 : info.activityInfo.applicationInfo.uid);
12972 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012973 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012974 + r.intent.toString()
12975 + " from " + r.callerPackage + " (pid=" + r.callingPid
12976 + ", uid=" + r.callingUid + ")"
12977 + " requires " + info.activityInfo.permission
12978 + " due to receiver " + info.activityInfo.packageName
12979 + "/" + info.activityInfo.name);
12980 skip = true;
12981 }
12982 if (r.callingUid != Process.SYSTEM_UID &&
12983 r.requiredPermission != null) {
12984 try {
12985 perm = ActivityThread.getPackageManager().
12986 checkPermission(r.requiredPermission,
12987 info.activityInfo.applicationInfo.packageName);
12988 } catch (RemoteException e) {
12989 perm = PackageManager.PERMISSION_DENIED;
12990 }
12991 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012992 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012993 + r.intent + " to "
12994 + info.activityInfo.applicationInfo.packageName
12995 + " requires " + r.requiredPermission
12996 + " due to sender " + r.callerPackage
12997 + " (uid " + r.callingUid + ")");
12998 skip = true;
12999 }
13000 }
13001 if (r.curApp != null && r.curApp.crashing) {
13002 // If the target process is crashing, just skip it.
13003 skip = true;
13004 }
13005
13006 if (skip) {
13007 r.receiver = null;
13008 r.curFilter = null;
13009 r.state = BroadcastRecord.IDLE;
13010 scheduleBroadcastsLocked();
13011 return;
13012 }
13013
13014 r.state = BroadcastRecord.APP_RECEIVE;
13015 String targetProcess = info.activityInfo.processName;
13016 r.curComponent = new ComponentName(
13017 info.activityInfo.applicationInfo.packageName,
13018 info.activityInfo.name);
13019 r.curReceiver = info.activityInfo;
13020
13021 // Is this receiver's application already running?
13022 ProcessRecord app = getProcessRecordLocked(targetProcess,
13023 info.activityInfo.applicationInfo.uid);
13024 if (app != null && app.thread != null) {
13025 try {
13026 processCurBroadcastLocked(r, app);
13027 return;
13028 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013029 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013030 + r.curComponent, e);
13031 }
13032
13033 // If a dead object exception was thrown -- fall through to
13034 // restart the application.
13035 }
13036
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013037 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013038 if ((r.curApp=startProcessLocked(targetProcess,
13039 info.activityInfo.applicationInfo, true,
13040 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013041 "broadcast", r.curComponent,
13042 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13043 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013044 // Ah, this recipient is unavailable. Finish it if necessary,
13045 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013046 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013047 + info.activityInfo.applicationInfo.packageName + "/"
13048 + info.activityInfo.applicationInfo.uid + " for broadcast "
13049 + r.intent + ": process is bad");
13050 logBroadcastReceiverDiscard(r);
13051 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13052 r.resultExtras, r.resultAbort, true);
13053 scheduleBroadcastsLocked();
13054 r.state = BroadcastRecord.IDLE;
13055 return;
13056 }
13057
13058 mPendingBroadcast = r;
13059 }
13060 }
13061
13062 // =========================================================
13063 // INSTRUMENTATION
13064 // =========================================================
13065
13066 public boolean startInstrumentation(ComponentName className,
13067 String profileFile, int flags, Bundle arguments,
13068 IInstrumentationWatcher watcher) {
13069 // Refuse possible leaked file descriptors
13070 if (arguments != null && arguments.hasFileDescriptors()) {
13071 throw new IllegalArgumentException("File descriptors passed in Bundle");
13072 }
13073
13074 synchronized(this) {
13075 InstrumentationInfo ii = null;
13076 ApplicationInfo ai = null;
13077 try {
13078 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013079 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013080 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013081 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013082 } catch (PackageManager.NameNotFoundException e) {
13083 }
13084 if (ii == null) {
13085 reportStartInstrumentationFailure(watcher, className,
13086 "Unable to find instrumentation info for: " + className);
13087 return false;
13088 }
13089 if (ai == null) {
13090 reportStartInstrumentationFailure(watcher, className,
13091 "Unable to find instrumentation target package: " + ii.targetPackage);
13092 return false;
13093 }
13094
13095 int match = mContext.getPackageManager().checkSignatures(
13096 ii.targetPackage, ii.packageName);
13097 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13098 String msg = "Permission Denial: starting instrumentation "
13099 + className + " from pid="
13100 + Binder.getCallingPid()
13101 + ", uid=" + Binder.getCallingPid()
13102 + " not allowed because package " + ii.packageName
13103 + " does not have a signature matching the target "
13104 + ii.targetPackage;
13105 reportStartInstrumentationFailure(watcher, className, msg);
13106 throw new SecurityException(msg);
13107 }
13108
13109 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013110 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013111 ProcessRecord app = addAppLocked(ai);
13112 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013113 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013114 app.instrumentationProfileFile = profileFile;
13115 app.instrumentationArguments = arguments;
13116 app.instrumentationWatcher = watcher;
13117 app.instrumentationResultClass = className;
13118 Binder.restoreCallingIdentity(origId);
13119 }
13120
13121 return true;
13122 }
13123
13124 /**
13125 * Report errors that occur while attempting to start Instrumentation. Always writes the
13126 * error to the logs, but if somebody is watching, send the report there too. This enables
13127 * the "am" command to report errors with more information.
13128 *
13129 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13130 * @param cn The component name of the instrumentation.
13131 * @param report The error report.
13132 */
13133 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13134 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013135 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013136 try {
13137 if (watcher != null) {
13138 Bundle results = new Bundle();
13139 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13140 results.putString("Error", report);
13141 watcher.instrumentationStatus(cn, -1, results);
13142 }
13143 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013144 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013145 }
13146 }
13147
13148 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13149 if (app.instrumentationWatcher != null) {
13150 try {
13151 // NOTE: IInstrumentationWatcher *must* be oneway here
13152 app.instrumentationWatcher.instrumentationFinished(
13153 app.instrumentationClass,
13154 resultCode,
13155 results);
13156 } catch (RemoteException e) {
13157 }
13158 }
13159 app.instrumentationWatcher = null;
13160 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013161 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013162 app.instrumentationProfileFile = null;
13163 app.instrumentationArguments = null;
13164
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013165 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013166 }
13167
13168 public void finishInstrumentation(IApplicationThread target,
13169 int resultCode, Bundle results) {
13170 // Refuse possible leaked file descriptors
13171 if (results != null && results.hasFileDescriptors()) {
13172 throw new IllegalArgumentException("File descriptors passed in Intent");
13173 }
13174
13175 synchronized(this) {
13176 ProcessRecord app = getRecordForAppLocked(target);
13177 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013178 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013179 return;
13180 }
13181 final long origId = Binder.clearCallingIdentity();
13182 finishInstrumentationLocked(app, resultCode, results);
13183 Binder.restoreCallingIdentity(origId);
13184 }
13185 }
13186
13187 // =========================================================
13188 // CONFIGURATION
13189 // =========================================================
13190
13191 public ConfigurationInfo getDeviceConfigurationInfo() {
13192 ConfigurationInfo config = new ConfigurationInfo();
13193 synchronized (this) {
13194 config.reqTouchScreen = mConfiguration.touchscreen;
13195 config.reqKeyboardType = mConfiguration.keyboard;
13196 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013197 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13198 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013199 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13200 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013201 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13202 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13204 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013205 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013206 }
13207 return config;
13208 }
13209
13210 public Configuration getConfiguration() {
13211 Configuration ci;
13212 synchronized(this) {
13213 ci = new Configuration(mConfiguration);
13214 }
13215 return ci;
13216 }
13217
13218 public void updateConfiguration(Configuration values) {
13219 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13220 "updateConfiguration()");
13221
13222 synchronized(this) {
13223 if (values == null && mWindowManager != null) {
13224 // sentinel: fetch the current configuration from the window manager
13225 values = mWindowManager.computeNewConfiguration();
13226 }
13227
13228 final long origId = Binder.clearCallingIdentity();
13229 updateConfigurationLocked(values, null);
13230 Binder.restoreCallingIdentity(origId);
13231 }
13232 }
13233
13234 /**
13235 * Do either or both things: (1) change the current configuration, and (2)
13236 * make sure the given activity is running with the (now) current
13237 * configuration. Returns true if the activity has been left running, or
13238 * false if <var>starting</var> is being destroyed to match the new
13239 * configuration.
13240 */
13241 public boolean updateConfigurationLocked(Configuration values,
13242 HistoryRecord starting) {
13243 int changes = 0;
13244
13245 boolean kept = true;
13246
13247 if (values != null) {
13248 Configuration newConfig = new Configuration(mConfiguration);
13249 changes = newConfig.updateFrom(values);
13250 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013251 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013252 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013253 }
13254
Doug Zongker2bec3d42009-12-04 12:52:44 -080013255 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013256
13257 if (values.locale != null) {
13258 saveLocaleLocked(values.locale,
13259 !values.locale.equals(mConfiguration.locale),
13260 values.userSetLocale);
13261 }
13262
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013263 mConfigurationSeq++;
13264 if (mConfigurationSeq <= 0) {
13265 mConfigurationSeq = 1;
13266 }
13267 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013268 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013269 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013270
13271 AttributeCache ac = AttributeCache.instance();
13272 if (ac != null) {
13273 ac.updateConfiguration(mConfiguration);
13274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013275
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013276 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13277 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13278 msg.obj = new Configuration(mConfiguration);
13279 mHandler.sendMessage(msg);
13280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013281
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013282 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13283 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013284 try {
13285 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013286 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013287 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013288 app.thread.scheduleConfigurationChanged(mConfiguration);
13289 }
13290 } catch (Exception e) {
13291 }
13292 }
13293 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013294 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13295 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013296 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13297 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013298 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13299 broadcastIntentLocked(null, null,
13300 new Intent(Intent.ACTION_LOCALE_CHANGED),
13301 null, null, 0, null, null,
13302 null, false, false, MY_PID, Process.SYSTEM_UID);
13303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013304 }
13305 }
13306
13307 if (changes != 0 && starting == null) {
13308 // If the configuration changed, and the caller is not already
13309 // in the process of starting an activity, then find the top
13310 // activity to check if its configuration needs to change.
13311 starting = topRunningActivityLocked(null);
13312 }
13313
13314 if (starting != null) {
13315 kept = ensureActivityConfigurationLocked(starting, changes);
13316 if (kept) {
13317 // If this didn't result in the starting activity being
13318 // destroyed, then we need to make sure at this point that all
13319 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013320 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013321 + ", ensuring others are correct.");
13322 ensureActivitiesVisibleLocked(starting, changes);
13323 }
13324 }
13325
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013326 if (values != null && mWindowManager != null) {
13327 mWindowManager.setNewConfiguration(mConfiguration);
13328 }
13329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013330 return kept;
13331 }
13332
13333 private final boolean relaunchActivityLocked(HistoryRecord r,
13334 int changes, boolean andResume) {
13335 List<ResultInfo> results = null;
13336 List<Intent> newIntents = null;
13337 if (andResume) {
13338 results = r.results;
13339 newIntents = r.newIntents;
13340 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013341 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013342 + " with results=" + results + " newIntents=" + newIntents
13343 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013344 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13345 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013346 r.task.taskId, r.shortComponentName);
13347
13348 r.startFreezingScreenLocked(r.app, 0);
13349
13350 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013351 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013352 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013353 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013354 // Note: don't need to call pauseIfSleepingLocked() here, because
13355 // the caller will only pass in 'andResume' if this activity is
13356 // currently resumed, which implies we aren't sleeping.
13357 } catch (RemoteException e) {
13358 return false;
13359 }
13360
13361 if (andResume) {
13362 r.results = null;
13363 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013364 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013365 }
13366
13367 return true;
13368 }
13369
13370 /**
13371 * Make sure the given activity matches the current configuration. Returns
13372 * false if the activity had to be destroyed. Returns true if the
13373 * configuration is the same, or the activity will remain running as-is
13374 * for whatever reason. Ensures the HistoryRecord is updated with the
13375 * correct configuration and all other bookkeeping is handled.
13376 */
13377 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13378 int globalChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013379 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013380 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381
13382 // Short circuit: if the two configurations are the exact same
13383 // object (the common case), then there is nothing to do.
13384 Configuration newConfig = mConfiguration;
13385 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013386 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013387 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013388 return true;
13389 }
13390
13391 // We don't worry about activities that are finishing.
13392 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013393 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013394 "Configuration doesn't matter in finishing " + r);
13395 r.stopFreezingScreenLocked(false);
13396 return true;
13397 }
13398
13399 // Okay we now are going to make this activity have the new config.
13400 // But then we need to figure out how it needs to deal with that.
13401 Configuration oldConfig = r.configuration;
13402 r.configuration = newConfig;
13403
13404 // If the activity isn't currently running, just leave the new
13405 // configuration and it will pick that up next time it starts.
13406 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013407 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013408 "Configuration doesn't matter not running " + r);
13409 r.stopFreezingScreenLocked(false);
13410 return true;
13411 }
13412
13413 // If the activity isn't persistent, there is a chance we will
13414 // need to restart it.
13415 if (!r.persistent) {
13416
13417 // Figure out what has changed between the two configurations.
13418 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013419 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013420 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013421 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013422 + Integer.toHexString(r.info.configChanges)
13423 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013424 }
13425 if ((changes&(~r.info.configChanges)) != 0) {
13426 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13427 r.configChangeFlags |= changes;
13428 r.startFreezingScreenLocked(r.app, globalChanges);
13429 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013430 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013431 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013432 destroyActivityLocked(r, true);
13433 } else if (r.state == ActivityState.PAUSING) {
13434 // A little annoying: we are waiting for this activity to
13435 // finish pausing. Let's not do anything now, but just
13436 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013437 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013438 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013439 r.configDestroy = true;
13440 return true;
13441 } else if (r.state == ActivityState.RESUMED) {
13442 // Try to optimize this case: the configuration is changing
13443 // and we need to restart the top, resumed activity.
13444 // Instead of doing the normal handshaking, just say
13445 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013446 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013447 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013448 relaunchActivityLocked(r, r.configChangeFlags, true);
13449 r.configChangeFlags = 0;
13450 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013451 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013452 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013453 relaunchActivityLocked(r, r.configChangeFlags, false);
13454 r.configChangeFlags = 0;
13455 }
13456
13457 // All done... tell the caller we weren't able to keep this
13458 // activity around.
13459 return false;
13460 }
13461 }
13462
13463 // Default case: the activity can handle this new configuration, so
13464 // hand it over. Note that we don't need to give it the new
13465 // configuration, since we always send configuration changes to all
13466 // process when they happen so it can just use whatever configuration
13467 // it last got.
13468 if (r.app != null && r.app.thread != null) {
13469 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013470 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013471 r.app.thread.scheduleActivityConfigurationChanged(r);
13472 } catch (RemoteException e) {
13473 // If process died, whatever.
13474 }
13475 }
13476 r.stopFreezingScreenLocked(false);
13477
13478 return true;
13479 }
13480
13481 /**
13482 * Save the locale. You must be inside a synchronized (this) block.
13483 */
13484 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13485 if(isDiff) {
13486 SystemProperties.set("user.language", l.getLanguage());
13487 SystemProperties.set("user.region", l.getCountry());
13488 }
13489
13490 if(isPersist) {
13491 SystemProperties.set("persist.sys.language", l.getLanguage());
13492 SystemProperties.set("persist.sys.country", l.getCountry());
13493 SystemProperties.set("persist.sys.localevar", l.getVariant());
13494 }
13495 }
13496
13497 // =========================================================
13498 // LIFETIME MANAGEMENT
13499 // =========================================================
13500
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013501 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13502 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013503 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013504 // This adjustment has already been computed. If we are calling
13505 // from the top, we may have already computed our adjustment with
13506 // an earlier hidden adjustment that isn't really for us... if
13507 // so, use the new hidden adjustment.
13508 if (!recursed && app.hidden) {
13509 app.curAdj = hiddenAdj;
13510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013511 return app.curAdj;
13512 }
13513
13514 if (app.thread == null) {
13515 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013516 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013517 return (app.curAdj=EMPTY_APP_ADJ);
13518 }
13519
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013520 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13521 // The max adjustment doesn't allow this app to be anything
13522 // below foreground, so it is not worth doing work for it.
13523 app.adjType = "fixed";
13524 app.adjSeq = mAdjSeq;
13525 app.curRawAdj = app.maxAdj;
13526 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13527 return (app.curAdj=app.maxAdj);
13528 }
13529
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013530 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013531 app.adjSource = null;
13532 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013533 app.empty = false;
13534 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013535
The Android Open Source Project4df24232009-03-05 14:34:35 -080013536 // Determine the importance of the process, starting with most
13537 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013538 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013539 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013540 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013541 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013542 // The last app on the list is the foreground app.
13543 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013544 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013545 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013546 } else if (app.instrumentationClass != null) {
13547 // Don't want to kill running instrumentation.
13548 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013549 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013550 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013551 } else if (app.persistentActivities > 0) {
13552 // Special persistent activities... shouldn't be used these days.
13553 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013554 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013555 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013556 } else if (app.curReceiver != null ||
13557 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13558 // An app that is currently receiving a broadcast also
13559 // counts as being in the foreground.
13560 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013561 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013562 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013563 } else if (app.executingServices.size() > 0) {
13564 // An app that is currently executing a service callback also
13565 // counts as being in the foreground.
13566 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013567 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013568 app.adjType = "exec-service";
13569 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013570 // The user is aware of this app, so make it visible.
13571 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013572 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013573 app.adjType = "foreground-service";
13574 } else if (app.forcingToForeground != null) {
13575 // The user is aware of this app, so make it visible.
13576 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013577 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013578 app.adjType = "force-foreground";
13579 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013580 } else if (app == mHomeProcess) {
13581 // This process is hosting what we currently consider to be the
13582 // home app, so we don't want to let it go into the background.
13583 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013584 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013585 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013586 } else if ((N=app.activities.size()) != 0) {
13587 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013588 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013589 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013590 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013591 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013592 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013593 for (int j=0; j<N; j++) {
13594 if (((HistoryRecord)app.activities.get(j)).visible) {
13595 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013596 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013597 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013598 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013599 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013600 break;
13601 }
13602 }
13603 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013604 // A very not-needed process. If this is lower in the lru list,
13605 // we will push it in to the empty bucket.
13606 app.hidden = true;
13607 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013608 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013609 adj = hiddenAdj;
13610 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013611 }
13612
Joe Onorato8a9b2202010-02-26 18:56:32 -080013613 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013614
The Android Open Source Project4df24232009-03-05 14:34:35 -080013615 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013616 // there are applications dependent on our services or providers, but
13617 // this gives us a baseline and makes sure we don't get into an
13618 // infinite recursion.
13619 app.adjSeq = mAdjSeq;
13620 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013621
Christopher Tate6fa95972009-06-05 18:43:55 -070013622 if (mBackupTarget != null && app == mBackupTarget.app) {
13623 // If possible we want to avoid killing apps while they're being backed up
13624 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013625 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013626 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013627 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013628 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013629 }
13630 }
13631
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013632 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13633 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013634 final long now = SystemClock.uptimeMillis();
13635 // This process is more important if the top activity is
13636 // bound to the service.
13637 Iterator jt = app.services.iterator();
13638 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13639 ServiceRecord s = (ServiceRecord)jt.next();
13640 if (s.startRequested) {
13641 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13642 // This service has seen some activity within
13643 // recent memory, so we will keep its process ahead
13644 // of the background processes.
13645 if (adj > SECONDARY_SERVER_ADJ) {
13646 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013647 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013648 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013649 }
13650 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013651 // If we have let the service slide into the background
13652 // state, still have some text describing what it is doing
13653 // even though the service no longer has an impact.
13654 if (adj > SECONDARY_SERVER_ADJ) {
13655 app.adjType = "started-bg-services";
13656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013657 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013658 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13659 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013660 Iterator<ConnectionRecord> kt
13661 = s.connections.values().iterator();
13662 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13663 // XXX should compute this based on the max of
13664 // all connected clients.
13665 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013666 if (cr.binding.client == app) {
13667 // Binding to ourself is not interesting.
13668 continue;
13669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013670 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13671 ProcessRecord client = cr.binding.client;
13672 int myHiddenAdj = hiddenAdj;
13673 if (myHiddenAdj > client.hiddenAdj) {
13674 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13675 myHiddenAdj = client.hiddenAdj;
13676 } else {
13677 myHiddenAdj = VISIBLE_APP_ADJ;
13678 }
13679 }
13680 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013681 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013682 if (adj > clientAdj) {
13683 adj = clientAdj > VISIBLE_APP_ADJ
13684 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013685 if (!client.hidden) {
13686 app.hidden = false;
13687 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013688 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013689 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13690 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013691 app.adjSource = cr.binding.client;
13692 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013693 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013694 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13695 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13696 schedGroup = Process.THREAD_GROUP_DEFAULT;
13697 }
13698 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013699 }
13700 HistoryRecord a = cr.activity;
13701 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013702 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013703 //}
13704 if (a != null && adj > FOREGROUND_APP_ADJ &&
13705 (a.state == ActivityState.RESUMED
13706 || a.state == ActivityState.PAUSING)) {
13707 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013708 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013709 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013710 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013711 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13712 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013713 app.adjSource = a;
13714 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013715 }
13716 }
13717 }
13718 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013719
13720 // Finally, f this process has active services running in it, we
13721 // would like to avoid killing it unless it would prevent the current
13722 // application from running. By default we put the process in
13723 // with the rest of the background processes; as we scan through
13724 // its services we may bump it up from there.
13725 if (adj > hiddenAdj) {
13726 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013727 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013728 app.adjType = "bg-services";
13729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013730 }
13731
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013732 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13733 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013734 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013735 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13736 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013737 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13738 if (cpr.clients.size() != 0) {
13739 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13740 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13741 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013742 if (client == app) {
13743 // Being our own client is not interesting.
13744 continue;
13745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013746 int myHiddenAdj = hiddenAdj;
13747 if (myHiddenAdj > client.hiddenAdj) {
13748 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13749 myHiddenAdj = client.hiddenAdj;
13750 } else {
13751 myHiddenAdj = FOREGROUND_APP_ADJ;
13752 }
13753 }
13754 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013755 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013756 if (adj > clientAdj) {
13757 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013758 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013759 if (!client.hidden) {
13760 app.hidden = false;
13761 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013762 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013763 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13764 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013765 app.adjSource = client;
13766 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013767 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013768 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13769 schedGroup = Process.THREAD_GROUP_DEFAULT;
13770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013771 }
13772 }
13773 // If the provider has external (non-framework) process
13774 // dependencies, ensure that its adjustment is at least
13775 // FOREGROUND_APP_ADJ.
13776 if (cpr.externals != 0) {
13777 if (adj > FOREGROUND_APP_ADJ) {
13778 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013779 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013780 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013781 app.adjType = "provider";
13782 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013783 }
13784 }
13785 }
13786 }
13787
13788 app.curRawAdj = adj;
13789
Joe Onorato8a9b2202010-02-26 18:56:32 -080013790 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013791 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13792 if (adj > app.maxAdj) {
13793 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013794 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13795 schedGroup = Process.THREAD_GROUP_DEFAULT;
13796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013797 }
13798
13799 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013800 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013802 return adj;
13803 }
13804
13805 /**
13806 * Ask a given process to GC right now.
13807 */
13808 final void performAppGcLocked(ProcessRecord app) {
13809 try {
13810 app.lastRequestedGc = SystemClock.uptimeMillis();
13811 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013812 if (app.reportLowMemory) {
13813 app.reportLowMemory = false;
13814 app.thread.scheduleLowMemory();
13815 } else {
13816 app.thread.processInBackground();
13817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013818 }
13819 } catch (Exception e) {
13820 // whatever.
13821 }
13822 }
13823
13824 /**
13825 * Returns true if things are idle enough to perform GCs.
13826 */
13827 private final boolean canGcNow() {
13828 return mParallelBroadcasts.size() == 0
13829 && mOrderedBroadcasts.size() == 0
13830 && (mSleeping || (mResumedActivity != null &&
13831 mResumedActivity.idle));
13832 }
13833
13834 /**
13835 * Perform GCs on all processes that are waiting for it, but only
13836 * if things are idle.
13837 */
13838 final void performAppGcsLocked() {
13839 final int N = mProcessesToGc.size();
13840 if (N <= 0) {
13841 return;
13842 }
13843 if (canGcNow()) {
13844 while (mProcessesToGc.size() > 0) {
13845 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013846 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13847 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13848 <= SystemClock.uptimeMillis()) {
13849 // To avoid spamming the system, we will GC processes one
13850 // at a time, waiting a few seconds between each.
13851 performAppGcLocked(proc);
13852 scheduleAppGcsLocked();
13853 return;
13854 } else {
13855 // It hasn't been long enough since we last GCed this
13856 // process... put it in the list to wait for its time.
13857 addProcessToGcListLocked(proc);
13858 break;
13859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013860 }
13861 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013862
13863 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013864 }
13865 }
13866
13867 /**
13868 * If all looks good, perform GCs on all processes waiting for them.
13869 */
13870 final void performAppGcsIfAppropriateLocked() {
13871 if (canGcNow()) {
13872 performAppGcsLocked();
13873 return;
13874 }
13875 // Still not idle, wait some more.
13876 scheduleAppGcsLocked();
13877 }
13878
13879 /**
13880 * Schedule the execution of all pending app GCs.
13881 */
13882 final void scheduleAppGcsLocked() {
13883 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013884
13885 if (mProcessesToGc.size() > 0) {
13886 // Schedule a GC for the time to the next process.
13887 ProcessRecord proc = mProcessesToGc.get(0);
13888 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13889
13890 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13891 long now = SystemClock.uptimeMillis();
13892 if (when < (now+GC_TIMEOUT)) {
13893 when = now + GC_TIMEOUT;
13894 }
13895 mHandler.sendMessageAtTime(msg, when);
13896 }
13897 }
13898
13899 /**
13900 * Add a process to the array of processes waiting to be GCed. Keeps the
13901 * list in sorted order by the last GC time. The process can't already be
13902 * on the list.
13903 */
13904 final void addProcessToGcListLocked(ProcessRecord proc) {
13905 boolean added = false;
13906 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13907 if (mProcessesToGc.get(i).lastRequestedGc <
13908 proc.lastRequestedGc) {
13909 added = true;
13910 mProcessesToGc.add(i+1, proc);
13911 break;
13912 }
13913 }
13914 if (!added) {
13915 mProcessesToGc.add(0, proc);
13916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013917 }
13918
13919 /**
13920 * Set up to ask a process to GC itself. This will either do it
13921 * immediately, or put it on the list of processes to gc the next
13922 * time things are idle.
13923 */
13924 final void scheduleAppGcLocked(ProcessRecord app) {
13925 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013926 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013927 return;
13928 }
13929 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013930 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013931 scheduleAppGcsLocked();
13932 }
13933 }
13934
13935 private final boolean updateOomAdjLocked(
13936 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13937 app.hiddenAdj = hiddenAdj;
13938
13939 if (app.thread == null) {
13940 return true;
13941 }
13942
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013943 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013944
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013945 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013946 if (app.curRawAdj != app.setRawAdj) {
13947 if (app.curRawAdj > FOREGROUND_APP_ADJ
13948 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13949 // If this app is transitioning from foreground to
13950 // non-foreground, have it do a gc.
13951 scheduleAppGcLocked(app);
13952 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13953 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13954 // Likewise do a gc when an app is moving in to the
13955 // background (such as a service stopping).
13956 scheduleAppGcLocked(app);
13957 }
13958 app.setRawAdj = app.curRawAdj;
13959 }
13960 if (adj != app.setAdj) {
13961 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013962 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013963 TAG, "Set app " + app.processName +
13964 " oom adj to " + adj);
13965 app.setAdj = adj;
13966 } else {
13967 return false;
13968 }
13969 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013970 if (app.setSchedGroup != app.curSchedGroup) {
13971 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013972 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013973 "Setting process group of " + app.processName
13974 + " to " + app.curSchedGroup);
13975 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013976 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013977 try {
13978 Process.setProcessGroup(app.pid, app.curSchedGroup);
13979 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013980 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013981 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013982 e.printStackTrace();
13983 } finally {
13984 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013985 }
13986 }
13987 if (false) {
13988 if (app.thread != null) {
13989 try {
13990 app.thread.setSchedulingGroup(app.curSchedGroup);
13991 } catch (RemoteException e) {
13992 }
13993 }
13994 }
13995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013996 }
13997
13998 return true;
13999 }
14000
14001 private final HistoryRecord resumedAppLocked() {
14002 HistoryRecord resumedActivity = mResumedActivity;
14003 if (resumedActivity == null || resumedActivity.app == null) {
14004 resumedActivity = mPausingActivity;
14005 if (resumedActivity == null || resumedActivity.app == null) {
14006 resumedActivity = topRunningActivityLocked(null);
14007 }
14008 }
14009 return resumedActivity;
14010 }
14011
14012 private final boolean updateOomAdjLocked(ProcessRecord app) {
14013 final HistoryRecord TOP_ACT = resumedAppLocked();
14014 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14015 int curAdj = app.curAdj;
14016 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14017 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14018
14019 mAdjSeq++;
14020
14021 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14022 if (res) {
14023 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14024 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14025 if (nowHidden != wasHidden) {
14026 // Changed to/from hidden state, so apps after it in the LRU
14027 // list may also be changed.
14028 updateOomAdjLocked();
14029 }
14030 }
14031 return res;
14032 }
14033
14034 private final boolean updateOomAdjLocked() {
14035 boolean didOomAdj = true;
14036 final HistoryRecord TOP_ACT = resumedAppLocked();
14037 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14038
14039 if (false) {
14040 RuntimeException e = new RuntimeException();
14041 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014042 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014043 }
14044
14045 mAdjSeq++;
14046
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014047 // Let's determine how many processes we have running vs.
14048 // how many slots we have for background processes; we may want
14049 // to put multiple processes in a slot of there are enough of
14050 // them.
14051 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14052 int factor = (mLruProcesses.size()-4)/numSlots;
14053 if (factor < 1) factor = 1;
14054 int step = 0;
14055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014056 // First try updating the OOM adjustment for each of the
14057 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014058 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014059 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14060 while (i > 0) {
14061 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014062 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014063 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014064 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014065 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014066 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014067 step++;
14068 if (step >= factor) {
14069 step = 0;
14070 curHiddenAdj++;
14071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014072 }
14073 } else {
14074 didOomAdj = false;
14075 }
14076 }
14077
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014078 // If we return false, we will fall back on killing processes to
14079 // have a fixed limit. Do this if a limit has been requested; else
14080 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014081 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14082 }
14083
14084 private final void trimApplications() {
14085 synchronized (this) {
14086 int i;
14087
14088 // First remove any unused application processes whose package
14089 // has been removed.
14090 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14091 final ProcessRecord app = mRemovedProcesses.get(i);
14092 if (app.activities.size() == 0
14093 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014094 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014095 TAG, "Exiting empty application process "
14096 + app.processName + " ("
14097 + (app.thread != null ? app.thread.asBinder() : null)
14098 + ")\n");
14099 if (app.pid > 0 && app.pid != MY_PID) {
14100 Process.killProcess(app.pid);
14101 } else {
14102 try {
14103 app.thread.scheduleExit();
14104 } catch (Exception e) {
14105 // Ignore exceptions.
14106 }
14107 }
14108 cleanUpApplicationRecordLocked(app, false, -1);
14109 mRemovedProcesses.remove(i);
14110
14111 if (app.persistent) {
14112 if (app.persistent) {
14113 addAppLocked(app.info);
14114 }
14115 }
14116 }
14117 }
14118
14119 // Now try updating the OOM adjustment for each of the
14120 // application processes based on their current state.
14121 // If the setOomAdj() API is not supported, then go with our
14122 // back-up plan...
14123 if (!updateOomAdjLocked()) {
14124
14125 // Count how many processes are running services.
14126 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014127 for (i=mLruProcesses.size()-1; i>=0; i--) {
14128 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014129
14130 if (app.persistent || app.services.size() != 0
14131 || app.curReceiver != null
14132 || app.persistentActivities > 0) {
14133 // Don't count processes holding services against our
14134 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014135 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014136 TAG, "Not trimming app " + app + " with services: "
14137 + app.services);
14138 numServiceProcs++;
14139 }
14140 }
14141
14142 int curMaxProcs = mProcessLimit;
14143 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14144 if (mAlwaysFinishActivities) {
14145 curMaxProcs = 1;
14146 }
14147 curMaxProcs += numServiceProcs;
14148
14149 // Quit as many processes as we can to get down to the desired
14150 // process count. First remove any processes that no longer
14151 // have activites running in them.
14152 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014153 i<mLruProcesses.size()
14154 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014155 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014156 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014157 // Quit an application only if it is not currently
14158 // running any activities.
14159 if (!app.persistent && app.activities.size() == 0
14160 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014161 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014162 TAG, "Exiting empty application process "
14163 + app.processName + " ("
14164 + (app.thread != null ? app.thread.asBinder() : null)
14165 + ")\n");
14166 if (app.pid > 0 && app.pid != MY_PID) {
14167 Process.killProcess(app.pid);
14168 } else {
14169 try {
14170 app.thread.scheduleExit();
14171 } catch (Exception e) {
14172 // Ignore exceptions.
14173 }
14174 }
14175 // todo: For now we assume the application is not buggy
14176 // or evil, and will quit as a result of our request.
14177 // Eventually we need to drive this off of the death
14178 // notification, and kill the process if it takes too long.
14179 cleanUpApplicationRecordLocked(app, false, i);
14180 i--;
14181 }
14182 }
14183
14184 // If we still have too many processes, now from the least
14185 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014186 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014187 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014188 " of " + curMaxProcs + " processes");
14189 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014190 i<mLruProcesses.size()
14191 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014192 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014193 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014194 // Quit the application only if we have a state saved for
14195 // all of its activities.
14196 boolean canQuit = !app.persistent && app.curReceiver == null
14197 && app.services.size() == 0
14198 && app.persistentActivities == 0;
14199 int NUMA = app.activities.size();
14200 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014201 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014202 TAG, "Looking to quit " + app.processName);
14203 for (j=0; j<NUMA && canQuit; j++) {
14204 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014205 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014206 TAG, " " + r.intent.getComponent().flattenToShortString()
14207 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14208 canQuit = (r.haveState || !r.stateNotNeeded)
14209 && !r.visible && r.stopped;
14210 }
14211 if (canQuit) {
14212 // Finish all of the activities, and then the app itself.
14213 for (j=0; j<NUMA; j++) {
14214 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14215 if (!r.finishing) {
14216 destroyActivityLocked(r, false);
14217 }
14218 r.resultTo = null;
14219 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014220 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014221 + app.processName + " ("
14222 + (app.thread != null ? app.thread.asBinder() : null)
14223 + ")\n");
14224 if (app.pid > 0 && app.pid != MY_PID) {
14225 Process.killProcess(app.pid);
14226 } else {
14227 try {
14228 app.thread.scheduleExit();
14229 } catch (Exception e) {
14230 // Ignore exceptions.
14231 }
14232 }
14233 // todo: For now we assume the application is not buggy
14234 // or evil, and will quit as a result of our request.
14235 // Eventually we need to drive this off of the death
14236 // notification, and kill the process if it takes too long.
14237 cleanUpApplicationRecordLocked(app, false, i);
14238 i--;
14239 //dump();
14240 }
14241 }
14242
14243 }
14244
14245 int curMaxActivities = MAX_ACTIVITIES;
14246 if (mAlwaysFinishActivities) {
14247 curMaxActivities = 1;
14248 }
14249
14250 // Finally, if there are too many activities now running, try to
14251 // finish as many as we can to get back down to the limit.
14252 for ( i=0;
14253 i<mLRUActivities.size()
14254 && mLRUActivities.size() > curMaxActivities;
14255 i++) {
14256 final HistoryRecord r
14257 = (HistoryRecord)mLRUActivities.get(i);
14258
14259 // We can finish this one if we have its icicle saved and
14260 // it is not persistent.
14261 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14262 && r.stopped && !r.persistent && !r.finishing) {
14263 final int origSize = mLRUActivities.size();
14264 destroyActivityLocked(r, true);
14265
14266 // This will remove it from the LRU list, so keep
14267 // our index at the same value. Note that this check to
14268 // see if the size changes is just paranoia -- if
14269 // something unexpected happens, we don't want to end up
14270 // in an infinite loop.
14271 if (origSize > mLRUActivities.size()) {
14272 i--;
14273 }
14274 }
14275 }
14276 }
14277 }
14278
14279 /** This method sends the specified signal to each of the persistent apps */
14280 public void signalPersistentProcesses(int sig) throws RemoteException {
14281 if (sig != Process.SIGNAL_USR1) {
14282 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14283 }
14284
14285 synchronized (this) {
14286 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14287 != PackageManager.PERMISSION_GRANTED) {
14288 throw new SecurityException("Requires permission "
14289 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14290 }
14291
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014292 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14293 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014294 if (r.thread != null && r.persistent) {
14295 Process.sendSignal(r.pid, sig);
14296 }
14297 }
14298 }
14299 }
14300
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014301 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014302 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014303
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014304 try {
14305 synchronized (this) {
14306 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14307 // its own permission.
14308 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14309 != PackageManager.PERMISSION_GRANTED) {
14310 throw new SecurityException("Requires permission "
14311 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014312 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014313
14314 if (start && fd == null) {
14315 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014316 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014317
14318 ProcessRecord proc = null;
14319 try {
14320 int pid = Integer.parseInt(process);
14321 synchronized (mPidsSelfLocked) {
14322 proc = mPidsSelfLocked.get(pid);
14323 }
14324 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014325 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014326
14327 if (proc == null) {
14328 HashMap<String, SparseArray<ProcessRecord>> all
14329 = mProcessNames.getMap();
14330 SparseArray<ProcessRecord> procs = all.get(process);
14331 if (procs != null && procs.size() > 0) {
14332 proc = procs.valueAt(0);
14333 }
14334 }
14335
14336 if (proc == null || proc.thread == null) {
14337 throw new IllegalArgumentException("Unknown process: " + process);
14338 }
14339
14340 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14341 if (isSecure) {
14342 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14343 throw new SecurityException("Process not debuggable: " + proc);
14344 }
14345 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014346
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014347 proc.thread.profilerControl(start, path, fd);
14348 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014349 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014350 }
14351 } catch (RemoteException e) {
14352 throw new IllegalStateException("Process disappeared");
14353 } finally {
14354 if (fd != null) {
14355 try {
14356 fd.close();
14357 } catch (IOException e) {
14358 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014359 }
14360 }
14361 }
14362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014363 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14364 public void monitor() {
14365 synchronized (this) { }
14366 }
14367}