blob: b6064e816086876f01187c2a8c491480e5cef2db [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 Hackborn061d58a2010-03-12 15:07:06 -08004271 public boolean willActivityBeVisible(IBinder token) {
4272 synchronized(this) {
4273 int i;
4274 for (i=mHistory.size()-1; i>=0; i--) {
4275 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4276 if (r == token) {
4277 return true;
4278 }
4279 if (r.fullscreen && !r.finishing) {
4280 return false;
4281 }
4282 }
4283 return true;
4284 }
4285 }
4286
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004287 public void overridePendingTransition(IBinder token, String packageName,
4288 int enterAnim, int exitAnim) {
4289 synchronized(this) {
4290 int index = indexOfTokenLocked(token);
4291 if (index < 0) {
4292 return;
4293 }
4294 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4295
4296 final long origId = Binder.clearCallingIdentity();
4297
4298 if (self.state == ActivityState.RESUMED
4299 || self.state == ActivityState.PAUSING) {
4300 mWindowManager.overridePendingAppTransition(packageName,
4301 enterAnim, exitAnim);
4302 }
4303
4304 Binder.restoreCallingIdentity(origId);
4305 }
4306 }
4307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004308 /**
4309 * Perform clean-up of service connections in an activity record.
4310 */
4311 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4312 // Throw away any services that have been bound by this activity.
4313 if (r.connections != null) {
4314 Iterator<ConnectionRecord> it = r.connections.iterator();
4315 while (it.hasNext()) {
4316 ConnectionRecord c = it.next();
4317 removeConnectionLocked(c, null, r);
4318 }
4319 r.connections = null;
4320 }
4321 }
4322
4323 /**
4324 * Perform the common clean-up of an activity record. This is called both
4325 * as part of destroyActivityLocked() (when destroying the client-side
4326 * representation) and cleaning things up as a result of its hosting
4327 * processing going away, in which case there is no remaining client-side
4328 * state to destroy so only the cleanup here is needed.
4329 */
4330 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4331 if (mResumedActivity == r) {
4332 mResumedActivity = null;
4333 }
4334 if (mFocusedActivity == r) {
4335 mFocusedActivity = null;
4336 }
4337
4338 r.configDestroy = false;
4339 r.frozenBeforeDestroy = false;
4340
4341 // Make sure this record is no longer in the pending finishes list.
4342 // This could happen, for example, if we are trimming activities
4343 // down to the max limit while they are still waiting to finish.
4344 mFinishingActivities.remove(r);
4345 mWaitingVisibleActivities.remove(r);
4346
4347 // Remove any pending results.
4348 if (r.finishing && r.pendingResults != null) {
4349 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4350 PendingIntentRecord rec = apr.get();
4351 if (rec != null) {
4352 cancelIntentSenderLocked(rec, false);
4353 }
4354 }
4355 r.pendingResults = null;
4356 }
4357
4358 if (cleanServices) {
4359 cleanUpActivityServicesLocked(r);
4360 }
4361
4362 if (mPendingThumbnails.size() > 0) {
4363 // There are clients waiting to receive thumbnails so, in case
4364 // this is an activity that someone is waiting for, add it
4365 // to the pending list so we can correctly update the clients.
4366 mCancelledThumbnails.add(r);
4367 }
4368
4369 // Get rid of any pending idle timeouts.
4370 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4371 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4372 }
4373
4374 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4375 if (r.state != ActivityState.DESTROYED) {
4376 mHistory.remove(r);
4377 r.inHistory = false;
4378 r.state = ActivityState.DESTROYED;
4379 mWindowManager.removeAppToken(r);
4380 if (VALIDATE_TOKENS) {
4381 mWindowManager.validateAppTokens(mHistory);
4382 }
4383 cleanUpActivityServicesLocked(r);
4384 removeActivityUriPermissionsLocked(r);
4385 }
4386 }
4387
4388 /**
4389 * Destroy the current CLIENT SIDE instance of an activity. This may be
4390 * called both when actually finishing an activity, or when performing
4391 * a configuration switch where we destroy the current client-side object
4392 * but then create a new client-side object for this same HistoryRecord.
4393 */
4394 private final boolean destroyActivityLocked(HistoryRecord r,
4395 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004396 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 TAG, "Removing activity: token=" + r
4398 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004399 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400 System.identityHashCode(r),
4401 r.task.taskId, r.shortComponentName);
4402
4403 boolean removedFromHistory = false;
4404
4405 cleanUpActivityLocked(r, false);
4406
Dianne Hackborn03abb812010-01-04 18:43:19 -08004407 final boolean hadApp = r.app != null;
4408
4409 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 if (removeFromApp) {
4411 int idx = r.app.activities.indexOf(r);
4412 if (idx >= 0) {
4413 r.app.activities.remove(idx);
4414 }
4415 if (r.persistent) {
4416 decPersistentCountLocked(r.app);
4417 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004418 if (r.app.activities.size() == 0) {
4419 // No longer have activities, so update location in
4420 // LRU list.
4421 updateLruProcessLocked(r.app, true, false);
4422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 }
4424
4425 boolean skipDestroy = false;
4426
4427 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004428 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4430 r.configChangeFlags);
4431 } catch (Exception e) {
4432 // We can just ignore exceptions here... if the process
4433 // has crashed, our death notification will clean things
4434 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004435 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 if (r.finishing) {
4437 removeActivityFromHistoryLocked(r);
4438 removedFromHistory = true;
4439 skipDestroy = true;
4440 }
4441 }
4442
4443 r.app = null;
4444 r.nowVisible = false;
4445
4446 if (r.finishing && !skipDestroy) {
4447 r.state = ActivityState.DESTROYING;
4448 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4449 msg.obj = r;
4450 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4451 } else {
4452 r.state = ActivityState.DESTROYED;
4453 }
4454 } else {
4455 // remove this record from the history.
4456 if (r.finishing) {
4457 removeActivityFromHistoryLocked(r);
4458 removedFromHistory = true;
4459 } else {
4460 r.state = ActivityState.DESTROYED;
4461 }
4462 }
4463
4464 r.configChangeFlags = 0;
4465
Dianne Hackborn03abb812010-01-04 18:43:19 -08004466 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004467 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 }
4469
4470 return removedFromHistory;
4471 }
4472
Dianne Hackborn03abb812010-01-04 18:43:19 -08004473 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004474 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004475 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 TAG, "Removing app " + app + " from list " + list
4477 + " with " + i + " entries");
4478 while (i > 0) {
4479 i--;
4480 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004481 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4483 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004484 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 list.remove(i);
4486 }
4487 }
4488 }
4489
4490 /**
4491 * Main function for removing an existing process from the activity manager
4492 * as a result of that process going away. Clears out all connections
4493 * to the process.
4494 */
4495 private final void handleAppDiedLocked(ProcessRecord app,
4496 boolean restarting) {
4497 cleanUpApplicationRecordLocked(app, restarting, -1);
4498 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004499 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 }
4501
4502 // Just in case...
4503 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004504 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 mPausingActivity = null;
4506 }
4507 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4508 mLastPausedActivity = null;
4509 }
4510
4511 // Remove this application's activities from active lists.
4512 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4513 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4514 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4515 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4516
4517 boolean atTop = true;
4518 boolean hasVisibleActivities = false;
4519
4520 // Clean out the history list.
4521 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004522 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004523 TAG, "Removing app " + app + " from history with " + i + " entries");
4524 while (i > 0) {
4525 i--;
4526 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004527 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004528 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4529 if (r.app == app) {
4530 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004531 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004532 TAG, "Removing this entry! frozen=" + r.haveState
4533 + " finishing=" + r.finishing);
4534 mHistory.remove(i);
4535
4536 r.inHistory = false;
4537 mWindowManager.removeAppToken(r);
4538 if (VALIDATE_TOKENS) {
4539 mWindowManager.validateAppTokens(mHistory);
4540 }
4541 removeActivityUriPermissionsLocked(r);
4542
4543 } else {
4544 // We have the current state for this activity, so
4545 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004546 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004547 TAG, "Keeping entry, setting app to null");
4548 if (r.visible) {
4549 hasVisibleActivities = true;
4550 }
4551 r.app = null;
4552 r.nowVisible = false;
4553 if (!r.haveState) {
4554 r.icicle = null;
4555 }
4556 }
4557
4558 cleanUpActivityLocked(r, true);
4559 r.state = ActivityState.STOPPED;
4560 }
4561 atTop = false;
4562 }
4563
4564 app.activities.clear();
4565
4566 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004567 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 + " running instrumentation " + app.instrumentationClass);
4569 Bundle info = new Bundle();
4570 info.putString("shortMsg", "Process crashed.");
4571 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4572 }
4573
4574 if (!restarting) {
4575 if (!resumeTopActivityLocked(null)) {
4576 // If there was nothing to resume, and we are not already
4577 // restarting this process, but there is a visible activity that
4578 // is hosted by the process... then make sure all visible
4579 // activities are running, taking care of restarting this
4580 // process.
4581 if (hasVisibleActivities) {
4582 ensureActivitiesVisibleLocked(null, 0);
4583 }
4584 }
4585 }
4586 }
4587
4588 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4589 IBinder threadBinder = thread.asBinder();
4590
4591 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004592 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4593 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4595 return i;
4596 }
4597 }
4598 return -1;
4599 }
4600
4601 private final ProcessRecord getRecordForAppLocked(
4602 IApplicationThread thread) {
4603 if (thread == null) {
4604 return null;
4605 }
4606
4607 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004608 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 }
4610
4611 private final void appDiedLocked(ProcessRecord app, int pid,
4612 IApplicationThread thread) {
4613
4614 mProcDeaths[0]++;
4615
Magnus Edlund7bb25812010-02-24 15:45:06 +01004616 // Clean up already done if the process has been re-started.
4617 if (app.pid == pid && app.thread != null &&
4618 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004619 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004620 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004621 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004622 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 TAG, "Dying app: " + app + ", pid: " + pid
4624 + ", thread: " + thread.asBinder());
4625 boolean doLowMem = app.instrumentationClass == null;
4626 handleAppDiedLocked(app, false);
4627
4628 if (doLowMem) {
4629 // If there are no longer any background processes running,
4630 // and the app that died was not running instrumentation,
4631 // then tell everyone we are now low on memory.
4632 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004633 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4634 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4636 haveBg = true;
4637 break;
4638 }
4639 }
4640
4641 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004642 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004643 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004644 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004645 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4646 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004647 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004648 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4649 // The low memory report is overriding any current
4650 // state for a GC request. Make sure to do
4651 // visible/foreground processes first.
4652 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4653 rec.lastRequestedGc = 0;
4654 } else {
4655 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004657 rec.reportLowMemory = true;
4658 rec.lastLowMemory = now;
4659 mProcessesToGc.remove(rec);
4660 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004661 }
4662 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004663 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004664 }
4665 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004666 } else if (app.pid != pid) {
4667 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004668 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004669 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004670 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004671 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004672 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004673 + thread.asBinder());
4674 }
4675 }
4676
Dan Egnor42471dd2010-01-07 17:25:22 -08004677 /**
4678 * If a stack trace dump file is configured, dump process stack traces.
4679 * @param pids of dalvik VM processes to dump stack traces for
4680 * @return file containing stack traces, or null if no dump file is configured
4681 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004682 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004683 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4684 if (tracesPath == null || tracesPath.length() == 0) {
4685 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004686 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004687
4688 File tracesFile = new File(tracesPath);
4689 try {
4690 File tracesDir = tracesFile.getParentFile();
4691 if (!tracesDir.exists()) tracesFile.mkdirs();
4692 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4693
4694 if (tracesFile.exists()) tracesFile.delete();
4695 tracesFile.createNewFile();
4696 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4697 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004698 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004699 return null;
4700 }
4701
4702 // Use a FileObserver to detect when traces finish writing.
4703 // The order of traces is considered important to maintain for legibility.
4704 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4705 public synchronized void onEvent(int event, String path) { notify(); }
4706 };
4707
4708 try {
4709 observer.startWatching();
4710 int num = pids.size();
4711 for (int i = 0; i < num; i++) {
4712 synchronized (observer) {
4713 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4714 observer.wait(200); // Wait for write-close, give up after 200msec
4715 }
4716 }
4717 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004718 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004719 } finally {
4720 observer.stopWatching();
4721 }
4722
4723 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 }
4725
Dan Egnor42471dd2010-01-07 17:25:22 -08004726 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4727 HistoryRecord parent, final String annotation) {
Mike Lockwoodb62f9592010-03-12 07:55:23 -05004728 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4729 if (mShuttingDown || app.notResponding || app.crashing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730 return;
4731 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004734 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4735 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004736
Dan Egnor42471dd2010-01-07 17:25:22 -08004737 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4738 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4739 pids.add(app.pid);
4740
4741 int parentPid = app.pid;
4742 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4743 if (parentPid != app.pid) pids.add(parentPid);
4744
4745 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4746
4747 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4748 ProcessRecord r = mLruProcesses.get(i);
4749 if (r != null && r.thread != null) {
4750 int pid = r.pid;
4751 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752 }
4753 }
4754
Dan Egnor42471dd2010-01-07 17:25:22 -08004755 File tracesFile = dumpStackTraces(pids);
4756
4757 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004758 StringBuilder info = mStringBuilder;
4759 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004760 info.append("ANR in ").append(app.processName);
4761 if (activity != null && activity.shortComponentName != null) {
4762 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004763 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004764 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004766 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004768 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004769 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771
Dan Egnor42471dd2010-01-07 17:25:22 -08004772 String cpuInfo = null;
4773 if (MONITOR_CPU_USAGE) {
4774 updateCpuStatsNow();
4775 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4776 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 }
4778
Joe Onorato8a9b2202010-02-26 18:56:32 -08004779 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004780 if (tracesFile == null) {
4781 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4782 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4783 }
4784
4785 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4786
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004787 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004789 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4790 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004792 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4793 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004794 }
4795 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004796 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 }
4798 }
4799
Dan Egnor42471dd2010-01-07 17:25:22 -08004800 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4801 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4802 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4803 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4804 Process.killProcess(app.pid);
4805 return;
4806 }
4807
4808 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 makeAppNotRespondingLocked(app,
4810 activity != null ? activity.shortComponentName : null,
4811 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004812 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004813
4814 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 Message msg = Message.obtain();
4816 HashMap map = new HashMap();
4817 msg.what = SHOW_NOT_RESPONDING_MSG;
4818 msg.obj = map;
4819 map.put("app", app);
4820 if (activity != null) {
4821 map.put("activity", activity);
4822 }
4823
4824 mHandler.sendMessage(msg);
4825 return;
4826 }
4827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828 private final void decPersistentCountLocked(ProcessRecord app)
4829 {
4830 app.persistentActivities--;
4831 if (app.persistentActivities > 0) {
4832 // Still more of 'em...
4833 return;
4834 }
4835 if (app.persistent) {
4836 // Ah, but the application itself is persistent. Whatever!
4837 return;
4838 }
4839
4840 // App is no longer persistent... make sure it and the ones
4841 // following it in the LRU list have the correc oom_adj.
4842 updateOomAdjLocked();
4843 }
4844
4845 public void setPersistent(IBinder token, boolean isPersistent) {
4846 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4847 != PackageManager.PERMISSION_GRANTED) {
4848 String msg = "Permission Denial: setPersistent() from pid="
4849 + Binder.getCallingPid()
4850 + ", uid=" + Binder.getCallingUid()
4851 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004852 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 throw new SecurityException(msg);
4854 }
4855
4856 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004857 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 if (index < 0) {
4859 return;
4860 }
4861 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4862 ProcessRecord app = r.app;
4863
Joe Onorato8a9b2202010-02-26 18:56:32 -08004864 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 TAG, "Setting persistence " + isPersistent + ": " + r);
4866
4867 if (isPersistent) {
4868 if (r.persistent) {
4869 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004870 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004871 return;
4872 }
4873 r.persistent = true;
4874 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004875 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 if (app.persistentActivities > 1) {
4877 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004878 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 return;
4880 }
4881 if (app.persistent) {
4882 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004883 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004884 return;
4885 }
4886
4887 // App is now persistent... make sure it and the ones
4888 // following it now have the correct oom_adj.
4889 final long origId = Binder.clearCallingIdentity();
4890 updateOomAdjLocked();
4891 Binder.restoreCallingIdentity(origId);
4892
4893 } else {
4894 if (!r.persistent) {
4895 // Okay okay, I heard you already!
4896 return;
4897 }
4898 r.persistent = false;
4899 final long origId = Binder.clearCallingIdentity();
4900 decPersistentCountLocked(app);
4901 Binder.restoreCallingIdentity(origId);
4902
4903 }
4904 }
4905 }
4906
4907 public boolean clearApplicationUserData(final String packageName,
4908 final IPackageDataObserver observer) {
4909 int uid = Binder.getCallingUid();
4910 int pid = Binder.getCallingPid();
4911 long callingId = Binder.clearCallingIdentity();
4912 try {
4913 IPackageManager pm = ActivityThread.getPackageManager();
4914 int pkgUid = -1;
4915 synchronized(this) {
4916 try {
4917 pkgUid = pm.getPackageUid(packageName);
4918 } catch (RemoteException e) {
4919 }
4920 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004921 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004922 return false;
4923 }
4924 if (uid == pkgUid || checkComponentPermission(
4925 android.Manifest.permission.CLEAR_APP_USER_DATA,
4926 pid, uid, -1)
4927 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004928 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 } else {
4930 throw new SecurityException(pid+" does not have permission:"+
4931 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4932 "for process:"+packageName);
4933 }
4934 }
4935
4936 try {
4937 //clear application user data
4938 pm.clearApplicationUserData(packageName, observer);
4939 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4940 Uri.fromParts("package", packageName, null));
4941 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4942 broadcastIntentLocked(null, null, intent,
4943 null, null, 0, null, null, null,
4944 false, false, MY_PID, Process.SYSTEM_UID);
4945 } catch (RemoteException e) {
4946 }
4947 } finally {
4948 Binder.restoreCallingIdentity(callingId);
4949 }
4950 return true;
4951 }
4952
Dianne Hackborn03abb812010-01-04 18:43:19 -08004953 public void killBackgroundProcesses(final String packageName) {
4954 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4955 != PackageManager.PERMISSION_GRANTED &&
4956 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4957 != PackageManager.PERMISSION_GRANTED) {
4958 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 + Binder.getCallingPid()
4960 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004961 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004962 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 throw new SecurityException(msg);
4964 }
4965
4966 long callingId = Binder.clearCallingIdentity();
4967 try {
4968 IPackageManager pm = ActivityThread.getPackageManager();
4969 int pkgUid = -1;
4970 synchronized(this) {
4971 try {
4972 pkgUid = pm.getPackageUid(packageName);
4973 } catch (RemoteException e) {
4974 }
4975 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004976 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 return;
4978 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004979 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004980 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004981 }
4982 } finally {
4983 Binder.restoreCallingIdentity(callingId);
4984 }
4985 }
4986
4987 public void forceStopPackage(final String packageName) {
4988 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4989 != PackageManager.PERMISSION_GRANTED) {
4990 String msg = "Permission Denial: forceStopPackage() from pid="
4991 + Binder.getCallingPid()
4992 + ", uid=" + Binder.getCallingUid()
4993 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004994 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004995 throw new SecurityException(msg);
4996 }
4997
4998 long callingId = Binder.clearCallingIdentity();
4999 try {
5000 IPackageManager pm = ActivityThread.getPackageManager();
5001 int pkgUid = -1;
5002 synchronized(this) {
5003 try {
5004 pkgUid = pm.getPackageUid(packageName);
5005 } catch (RemoteException e) {
5006 }
5007 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005008 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005009 return;
5010 }
5011 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005012 }
5013 } finally {
5014 Binder.restoreCallingIdentity(callingId);
5015 }
5016 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005017
5018 /*
5019 * The pkg name and uid have to be specified.
5020 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5021 */
5022 public void killApplicationWithUid(String pkg, int uid) {
5023 if (pkg == null) {
5024 return;
5025 }
5026 // Make sure the uid is valid.
5027 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005028 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005029 return;
5030 }
5031 int callerUid = Binder.getCallingUid();
5032 // Only the system server can kill an application
5033 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005034 // Post an aysnc message to kill the application
5035 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5036 msg.arg1 = uid;
5037 msg.arg2 = 0;
5038 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005039 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005040 } else {
5041 throw new SecurityException(callerUid + " cannot kill pkg: " +
5042 pkg);
5043 }
5044 }
5045
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005046 public void closeSystemDialogs(String reason) {
5047 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5048 if (reason != null) {
5049 intent.putExtra("reason", reason);
5050 }
5051
5052 final int uid = Binder.getCallingUid();
5053 final long origId = Binder.clearCallingIdentity();
5054 synchronized (this) {
5055 int i = mWatchers.beginBroadcast();
5056 while (i > 0) {
5057 i--;
5058 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5059 if (w != null) {
5060 try {
5061 w.closingSystemDialogs(reason);
5062 } catch (RemoteException e) {
5063 }
5064 }
5065 }
5066 mWatchers.finishBroadcast();
5067
Dianne Hackbornffa42482009-09-23 22:20:11 -07005068 mWindowManager.closeSystemDialogs(reason);
5069
5070 for (i=mHistory.size()-1; i>=0; i--) {
5071 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5072 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5073 finishActivityLocked(r, i,
5074 Activity.RESULT_CANCELED, null, "close-sys");
5075 }
5076 }
5077
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005078 broadcastIntentLocked(null, null, intent, null,
5079 null, 0, null, null, null, false, false, -1, uid);
5080 }
5081 Binder.restoreCallingIdentity(origId);
5082 }
5083
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005084 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005085 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005086 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5087 for (int i=pids.length-1; i>=0; i--) {
5088 infos[i] = new Debug.MemoryInfo();
5089 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005090 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005091 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005092 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005093
5094 public void killApplicationProcess(String processName, int uid) {
5095 if (processName == null) {
5096 return;
5097 }
5098
5099 int callerUid = Binder.getCallingUid();
5100 // Only the system server can kill an application
5101 if (callerUid == Process.SYSTEM_UID) {
5102 synchronized (this) {
5103 ProcessRecord app = getProcessRecordLocked(processName, uid);
5104 if (app != null) {
5105 try {
5106 app.thread.scheduleSuicide();
5107 } catch (RemoteException e) {
5108 // If the other end already died, then our work here is done.
5109 }
5110 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005111 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005112 + processName + " / " + uid);
5113 }
5114 }
5115 } else {
5116 throw new SecurityException(callerUid + " cannot kill app process: " +
5117 processName);
5118 }
5119 }
5120
Dianne Hackborn03abb812010-01-04 18:43:19 -08005121 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005122 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005123 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5124 Uri.fromParts("package", packageName, null));
5125 intent.putExtra(Intent.EXTRA_UID, uid);
5126 broadcastIntentLocked(null, null, intent,
5127 null, null, 0, null, null, null,
5128 false, false, MY_PID, Process.SYSTEM_UID);
5129 }
5130
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005131 private final boolean killPackageProcessesLocked(String packageName, int uid,
5132 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005133 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134
Dianne Hackborn03abb812010-01-04 18:43:19 -08005135 // Remove all processes this package may have touched: all with the
5136 // same UID (except for the system or root user), and all whose name
5137 // matches the package name.
5138 final String procNamePrefix = packageName + ":";
5139 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5140 final int NA = apps.size();
5141 for (int ia=0; ia<NA; ia++) {
5142 ProcessRecord app = apps.valueAt(ia);
5143 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005144 if (doit) {
5145 procs.add(app);
5146 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005147 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5148 || app.processName.equals(packageName)
5149 || app.processName.startsWith(procNamePrefix)) {
5150 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005151 if (!doit) {
5152 return true;
5153 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005154 app.removed = true;
5155 procs.add(app);
5156 }
5157 }
5158 }
5159 }
5160
5161 int N = procs.size();
5162 for (int i=0; i<N; i++) {
5163 removeProcessLocked(procs.get(i), callerWillRestart);
5164 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005165 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005166 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005167
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005168 private final boolean forceStopPackageLocked(String name, int uid,
5169 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005170 int i, N;
5171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172 if (uid < 0) {
5173 try {
5174 uid = ActivityThread.getPackageManager().getPackageUid(name);
5175 } catch (RemoteException e) {
5176 }
5177 }
5178
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005179 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005180 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005181
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005182 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5183 while (badApps.hasNext()) {
5184 SparseArray<Long> ba = badApps.next();
5185 if (ba.get(uid) != null) {
5186 badApps.remove();
5187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005188 }
5189 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005190
5191 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5192 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193
5194 for (i=mHistory.size()-1; i>=0; i--) {
5195 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5196 if (r.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 finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 if (r.app != null) {
5203 r.app.removed = true;
5204 }
5205 r.app = null;
5206 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5207 }
5208 }
5209
5210 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5211 for (ServiceRecord service : mServices.values()) {
5212 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005213 if (!doit) {
5214 return true;
5215 }
5216 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005217 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 if (service.app != null) {
5219 service.app.removed = true;
5220 }
5221 service.app = null;
5222 services.add(service);
5223 }
5224 }
5225
5226 N = services.size();
5227 for (i=0; i<N; i++) {
5228 bringDownServiceLocked(services.get(i), true);
5229 }
5230
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005231 if (doit) {
5232 if (purgeCache) {
5233 AttributeCache ac = AttributeCache.instance();
5234 if (ac != null) {
5235 ac.removePackage(name);
5236 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005237 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005238 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005239 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005240
5241 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005242 }
5243
5244 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5245 final String name = app.processName;
5246 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005247 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 TAG, "Force removing process " + app + " (" + name
5249 + "/" + uid + ")");
5250
5251 mProcessNames.remove(name, uid);
5252 boolean needRestart = false;
5253 if (app.pid > 0 && app.pid != MY_PID) {
5254 int pid = app.pid;
5255 synchronized (mPidsSelfLocked) {
5256 mPidsSelfLocked.remove(pid);
5257 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5258 }
5259 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005260 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005261 Process.killProcess(pid);
5262
5263 if (app.persistent) {
5264 if (!callerWillRestart) {
5265 addAppLocked(app.info);
5266 } else {
5267 needRestart = true;
5268 }
5269 }
5270 } else {
5271 mRemovedProcesses.add(app);
5272 }
5273
5274 return needRestart;
5275 }
5276
5277 private final void processStartTimedOutLocked(ProcessRecord app) {
5278 final int pid = app.pid;
5279 boolean gone = false;
5280 synchronized (mPidsSelfLocked) {
5281 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5282 if (knownApp != null && knownApp.thread == null) {
5283 mPidsSelfLocked.remove(pid);
5284 gone = true;
5285 }
5286 }
5287
5288 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005289 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005290 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005291 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005293 // Take care of any launching providers waiting for this process.
5294 checkAppInLaunchingProvidersLocked(app, true);
5295 // Take care of any services that are waiting for the process.
5296 for (int i=0; i<mPendingServices.size(); i++) {
5297 ServiceRecord sr = mPendingServices.get(i);
5298 if (app.info.uid == sr.appInfo.uid
5299 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005300 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005301 mPendingServices.remove(i);
5302 i--;
5303 bringDownServiceLocked(sr, true);
5304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005306 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005307 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005308 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005309 try {
5310 IBackupManager bm = IBackupManager.Stub.asInterface(
5311 ServiceManager.getService(Context.BACKUP_SERVICE));
5312 bm.agentDisconnected(app.info.packageName);
5313 } catch (RemoteException e) {
5314 // Can't happen; the backup manager is local
5315 }
5316 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005317 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005318 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005319 mPendingBroadcast = null;
5320 scheduleBroadcastsLocked();
5321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005323 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 }
5325 }
5326
5327 private final boolean attachApplicationLocked(IApplicationThread thread,
5328 int pid) {
5329
5330 // Find the application record that is being attached... either via
5331 // the pid if we are running in multiple processes, or just pull the
5332 // next app record if we are emulating process with anonymous threads.
5333 ProcessRecord app;
5334 if (pid != MY_PID && pid >= 0) {
5335 synchronized (mPidsSelfLocked) {
5336 app = mPidsSelfLocked.get(pid);
5337 }
5338 } else if (mStartingProcesses.size() > 0) {
5339 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005340 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 } else {
5342 app = null;
5343 }
5344
5345 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005346 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005348 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 if (pid > 0 && pid != MY_PID) {
5350 Process.killProcess(pid);
5351 } else {
5352 try {
5353 thread.scheduleExit();
5354 } catch (Exception e) {
5355 // Ignore exceptions.
5356 }
5357 }
5358 return false;
5359 }
5360
5361 // If this application record is still attached to a previous
5362 // process, clean it up now.
5363 if (app.thread != null) {
5364 handleAppDiedLocked(app, true);
5365 }
5366
5367 // Tell the process all about itself.
5368
Joe Onorato8a9b2202010-02-26 18:56:32 -08005369 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005370 TAG, "Binding process pid " + pid + " to record " + app);
5371
5372 String processName = app.processName;
5373 try {
5374 thread.asBinder().linkToDeath(new AppDeathRecipient(
5375 app, pid, thread), 0);
5376 } catch (RemoteException e) {
5377 app.resetPackageList();
5378 startProcessLocked(app, "link fail", processName);
5379 return false;
5380 }
5381
Doug Zongker2bec3d42009-12-04 12:52:44 -08005382 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005383
5384 app.thread = thread;
5385 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005386 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5387 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 app.forcingToForeground = null;
5389 app.foregroundServices = false;
5390 app.debugging = false;
5391
5392 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5393
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005394 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5395 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005397 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005398 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005399 }
5400
Joe Onorato8a9b2202010-02-26 18:56:32 -08005401 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005402 TAG, "New app record " + app
5403 + " thread=" + thread.asBinder() + " pid=" + pid);
5404 try {
5405 int testMode = IApplicationThread.DEBUG_OFF;
5406 if (mDebugApp != null && mDebugApp.equals(processName)) {
5407 testMode = mWaitForDebugger
5408 ? IApplicationThread.DEBUG_WAIT
5409 : IApplicationThread.DEBUG_ON;
5410 app.debugging = true;
5411 if (mDebugTransient) {
5412 mDebugApp = mOrigDebugApp;
5413 mWaitForDebugger = mOrigWaitForDebugger;
5414 }
5415 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005416
Christopher Tate181fafa2009-05-14 11:12:14 -07005417 // If the app is being launched for restore or full backup, set it up specially
5418 boolean isRestrictedBackupMode = false;
5419 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5420 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5421 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5422 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005423
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005424 ensurePackageDexOpt(app.instrumentationInfo != null
5425 ? app.instrumentationInfo.packageName
5426 : app.info.packageName);
5427 if (app.instrumentationClass != null) {
5428 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005429 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005430 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005431 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005432 thread.bindApplication(processName, app.instrumentationInfo != null
5433 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005434 app.instrumentationClass, app.instrumentationProfileFile,
5435 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005436 isRestrictedBackupMode || !normalMode,
5437 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005438 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005439 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005440 } catch (Exception e) {
5441 // todo: Yikes! What should we do? For now we will try to
5442 // start another process, but that could easily get us in
5443 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005444 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005445
5446 app.resetPackageList();
5447 startProcessLocked(app, "bind fail", processName);
5448 return false;
5449 }
5450
5451 // Remove this record from the list of starting applications.
5452 mPersistentStartingProcesses.remove(app);
5453 mProcessesOnHold.remove(app);
5454
5455 boolean badApp = false;
5456 boolean didSomething = false;
5457
5458 // See if the top visible activity is waiting to run in this process...
5459 HistoryRecord hr = topRunningActivityLocked(null);
5460 if (hr != null) {
5461 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5462 && processName.equals(hr.processName)) {
5463 try {
5464 if (realStartActivityLocked(hr, app, true, true)) {
5465 didSomething = true;
5466 }
5467 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005468 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 + hr.intent.getComponent().flattenToShortString(), e);
5470 badApp = true;
5471 }
5472 } else {
5473 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5474 }
5475 }
5476
5477 // Find any services that should be running in this process...
5478 if (!badApp && mPendingServices.size() > 0) {
5479 ServiceRecord sr = null;
5480 try {
5481 for (int i=0; i<mPendingServices.size(); i++) {
5482 sr = mPendingServices.get(i);
5483 if (app.info.uid != sr.appInfo.uid
5484 || !processName.equals(sr.processName)) {
5485 continue;
5486 }
5487
5488 mPendingServices.remove(i);
5489 i--;
5490 realStartServiceLocked(sr, app);
5491 didSomething = true;
5492 }
5493 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005494 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005495 + sr.shortName, e);
5496 badApp = true;
5497 }
5498 }
5499
5500 // Check if the next broadcast receiver is in this process...
5501 BroadcastRecord br = mPendingBroadcast;
5502 if (!badApp && br != null && br.curApp == app) {
5503 try {
5504 mPendingBroadcast = null;
5505 processCurBroadcastLocked(br, app);
5506 didSomething = true;
5507 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005508 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 + br.curComponent.flattenToShortString(), e);
5510 badApp = true;
5511 logBroadcastReceiverDiscard(br);
5512 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5513 br.resultExtras, br.resultAbort, true);
5514 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005515 // We need to reset the state if we fails to start the receiver.
5516 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005517 }
5518 }
5519
Christopher Tate181fafa2009-05-14 11:12:14 -07005520 // Check whether the next backup agent is in this process...
5521 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005522 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005523 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005524 try {
5525 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5526 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005527 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005528 e.printStackTrace();
5529 }
5530 }
5531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005532 if (badApp) {
5533 // todo: Also need to kill application to deal with all
5534 // kinds of exceptions.
5535 handleAppDiedLocked(app, false);
5536 return false;
5537 }
5538
5539 if (!didSomething) {
5540 updateOomAdjLocked();
5541 }
5542
5543 return true;
5544 }
5545
5546 public final void attachApplication(IApplicationThread thread) {
5547 synchronized (this) {
5548 int callingPid = Binder.getCallingPid();
5549 final long origId = Binder.clearCallingIdentity();
5550 attachApplicationLocked(thread, callingPid);
5551 Binder.restoreCallingIdentity(origId);
5552 }
5553 }
5554
Dianne Hackborne88846e2009-09-30 21:34:25 -07005555 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005556 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005557 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 Binder.restoreCallingIdentity(origId);
5559 }
5560
5561 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5562 boolean remove) {
5563 int N = mStoppingActivities.size();
5564 if (N <= 0) return null;
5565
5566 ArrayList<HistoryRecord> stops = null;
5567
5568 final boolean nowVisible = mResumedActivity != null
5569 && mResumedActivity.nowVisible
5570 && !mResumedActivity.waitingVisible;
5571 for (int i=0; i<N; i++) {
5572 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005573 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005574 + nowVisible + " waitingVisible=" + s.waitingVisible
5575 + " finishing=" + s.finishing);
5576 if (s.waitingVisible && nowVisible) {
5577 mWaitingVisibleActivities.remove(s);
5578 s.waitingVisible = false;
5579 if (s.finishing) {
5580 // If this activity is finishing, it is sitting on top of
5581 // everyone else but we now know it is no longer needed...
5582 // so get rid of it. Otherwise, we need to go through the
5583 // normal flow and hide it once we determine that it is
5584 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005585 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 mWindowManager.setAppVisibility(s, false);
5587 }
5588 }
5589 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005590 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005591 if (stops == null) {
5592 stops = new ArrayList<HistoryRecord>();
5593 }
5594 stops.add(s);
5595 mStoppingActivities.remove(i);
5596 N--;
5597 i--;
5598 }
5599 }
5600
5601 return stops;
5602 }
5603
5604 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005605 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005606 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005607 mWindowManager.enableScreenAfterBoot();
5608 }
5609
Dianne Hackborne88846e2009-09-30 21:34:25 -07005610 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5611 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005612 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613
5614 ArrayList<HistoryRecord> stops = null;
5615 ArrayList<HistoryRecord> finishes = null;
5616 ArrayList<HistoryRecord> thumbnails = null;
5617 int NS = 0;
5618 int NF = 0;
5619 int NT = 0;
5620 IApplicationThread sendThumbnail = null;
5621 boolean booting = false;
5622 boolean enableScreen = false;
5623
5624 synchronized (this) {
5625 if (token != null) {
5626 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5627 }
5628
5629 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005630 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 if (index >= 0) {
5632 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5633
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005634 if (fromTimeout) {
5635 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5636 }
5637
Dianne Hackborne88846e2009-09-30 21:34:25 -07005638 // This is a hack to semi-deal with a race condition
5639 // in the client where it can be constructed with a
5640 // newer configuration from when we asked it to launch.
5641 // We'll update with whatever configuration it now says
5642 // it used to launch.
5643 if (config != null) {
5644 r.configuration = config;
5645 }
5646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 // No longer need to keep the device awake.
5648 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5649 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5650 mLaunchingActivity.release();
5651 }
5652
5653 // We are now idle. If someone is waiting for a thumbnail from
5654 // us, we can now deliver.
5655 r.idle = true;
5656 scheduleAppGcsLocked();
5657 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5658 sendThumbnail = r.app.thread;
5659 r.thumbnailNeeded = false;
5660 }
5661
5662 // If this activity is fullscreen, set up to hide those under it.
5663
Joe Onorato8a9b2202010-02-26 18:56:32 -08005664 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 ensureActivitiesVisibleLocked(null, 0);
5666
Joe Onorato8a9b2202010-02-26 18:56:32 -08005667 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005668 if (!mBooted && !fromTimeout) {
5669 mBooted = true;
5670 enableScreen = true;
5671 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005672
5673 } else if (fromTimeout) {
5674 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005675 }
5676
5677 // Atomically retrieve all of the other things to do.
5678 stops = processStoppingActivitiesLocked(true);
5679 NS = stops != null ? stops.size() : 0;
5680 if ((NF=mFinishingActivities.size()) > 0) {
5681 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5682 mFinishingActivities.clear();
5683 }
5684 if ((NT=mCancelledThumbnails.size()) > 0) {
5685 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5686 mCancelledThumbnails.clear();
5687 }
5688
5689 booting = mBooting;
5690 mBooting = false;
5691 }
5692
5693 int i;
5694
5695 // Send thumbnail if requested.
5696 if (sendThumbnail != null) {
5697 try {
5698 sendThumbnail.requestThumbnail(token);
5699 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005700 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 sendPendingThumbnail(null, token, null, null, true);
5702 }
5703 }
5704
5705 // Stop any activities that are scheduled to do so but have been
5706 // waiting for the next one to start.
5707 for (i=0; i<NS; i++) {
5708 HistoryRecord r = (HistoryRecord)stops.get(i);
5709 synchronized (this) {
5710 if (r.finishing) {
5711 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5712 } else {
5713 stopActivityLocked(r);
5714 }
5715 }
5716 }
5717
5718 // Finish any activities that are scheduled to do so but have been
5719 // waiting for the next one to start.
5720 for (i=0; i<NF; i++) {
5721 HistoryRecord r = (HistoryRecord)finishes.get(i);
5722 synchronized (this) {
5723 destroyActivityLocked(r, true);
5724 }
5725 }
5726
5727 // Report back to any thumbnail receivers.
5728 for (i=0; i<NT; i++) {
5729 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5730 sendPendingThumbnail(r, null, null, null, true);
5731 }
5732
5733 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005734 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005735 }
5736
5737 trimApplications();
5738 //dump();
5739 //mWindowManager.dump();
5740
5741 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005742 enableScreenAfterBoot();
5743 }
5744 }
5745
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005746 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005747 IntentFilter pkgFilter = new IntentFilter();
5748 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5749 pkgFilter.addDataScheme("package");
5750 mContext.registerReceiver(new BroadcastReceiver() {
5751 @Override
5752 public void onReceive(Context context, Intent intent) {
5753 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5754 if (pkgs != null) {
5755 for (String pkg : pkgs) {
5756 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5757 setResultCode(Activity.RESULT_OK);
5758 return;
5759 }
5760 }
5761 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005762 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005763 }, pkgFilter);
5764
5765 synchronized (this) {
5766 // Ensure that any processes we had put on hold are now started
5767 // up.
5768 final int NP = mProcessesOnHold.size();
5769 if (NP > 0) {
5770 ArrayList<ProcessRecord> procs =
5771 new ArrayList<ProcessRecord>(mProcessesOnHold);
5772 for (int ip=0; ip<NP; ip++) {
5773 this.startProcessLocked(procs.get(ip), "on-hold", null);
5774 }
5775 }
5776
5777 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5778 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005779 broadcastIntentLocked(null, null,
5780 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5781 null, null, 0, null, null,
5782 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5783 false, false, MY_PID, Process.SYSTEM_UID);
5784 }
5785 }
5786 }
5787
5788 final void ensureBootCompleted() {
5789 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005790 boolean enableScreen;
5791 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005792 booting = mBooting;
5793 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005794 enableScreen = !mBooted;
5795 mBooted = true;
5796 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005797
5798 if (booting) {
5799 finishBooting();
5800 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005801
5802 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005803 enableScreenAfterBoot();
5804 }
5805 }
5806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005807 public final void activityPaused(IBinder token, Bundle icicle) {
5808 // Refuse possible leaked file descriptors
5809 if (icicle != null && icicle.hasFileDescriptors()) {
5810 throw new IllegalArgumentException("File descriptors passed in Bundle");
5811 }
5812
5813 final long origId = Binder.clearCallingIdentity();
5814 activityPaused(token, icicle, false);
5815 Binder.restoreCallingIdentity(origId);
5816 }
5817
5818 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005819 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005820 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5821 + ", timeout=" + timeout);
5822
5823 HistoryRecord r = null;
5824
5825 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005826 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005827 if (index >= 0) {
5828 r = (HistoryRecord)mHistory.get(index);
5829 if (!timeout) {
5830 r.icicle = icicle;
5831 r.haveState = true;
5832 }
5833 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5834 if (mPausingActivity == r) {
5835 r.state = ActivityState.PAUSED;
5836 completePauseLocked();
5837 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005838 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005839 System.identityHashCode(r), r.shortComponentName,
5840 mPausingActivity != null
5841 ? mPausingActivity.shortComponentName : "(none)");
5842 }
5843 }
5844 }
5845 }
5846
5847 public final void activityStopped(IBinder token, Bitmap thumbnail,
5848 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005849 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005850 TAG, "Activity stopped: token=" + token);
5851
5852 HistoryRecord r = null;
5853
5854 final long origId = Binder.clearCallingIdentity();
5855
5856 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005857 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 if (index >= 0) {
5859 r = (HistoryRecord)mHistory.get(index);
5860 r.thumbnail = thumbnail;
5861 r.description = description;
5862 r.stopped = true;
5863 r.state = ActivityState.STOPPED;
5864 if (!r.finishing) {
5865 if (r.configDestroy) {
5866 destroyActivityLocked(r, true);
5867 resumeTopActivityLocked(null);
5868 }
5869 }
5870 }
5871 }
5872
5873 if (r != null) {
5874 sendPendingThumbnail(r, null, null, null, false);
5875 }
5876
5877 trimApplications();
5878
5879 Binder.restoreCallingIdentity(origId);
5880 }
5881
5882 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005883 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005884 synchronized (this) {
5885 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5886
Dianne Hackborn75b03852009-06-12 15:43:26 -07005887 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005888 if (index >= 0) {
5889 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5890 if (r.state == ActivityState.DESTROYING) {
5891 final long origId = Binder.clearCallingIdentity();
5892 removeActivityFromHistoryLocked(r);
5893 Binder.restoreCallingIdentity(origId);
5894 }
5895 }
5896 }
5897 }
5898
5899 public String getCallingPackage(IBinder token) {
5900 synchronized (this) {
5901 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005902 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 }
5904 }
5905
5906 public ComponentName getCallingActivity(IBinder token) {
5907 synchronized (this) {
5908 HistoryRecord r = getCallingRecordLocked(token);
5909 return r != null ? r.intent.getComponent() : null;
5910 }
5911 }
5912
5913 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005914 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 if (index >= 0) {
5916 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5917 if (r != null) {
5918 return r.resultTo;
5919 }
5920 }
5921 return null;
5922 }
5923
5924 public ComponentName getActivityClassForToken(IBinder token) {
5925 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005926 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005927 if (index >= 0) {
5928 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5929 return r.intent.getComponent();
5930 }
5931 return null;
5932 }
5933 }
5934
5935 public String getPackageForToken(IBinder token) {
5936 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005937 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 if (index >= 0) {
5939 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5940 return r.packageName;
5941 }
5942 return null;
5943 }
5944 }
5945
5946 public IIntentSender getIntentSender(int type,
5947 String packageName, IBinder token, String resultWho,
5948 int requestCode, Intent intent, String resolvedType, int flags) {
5949 // Refuse possible leaked file descriptors
5950 if (intent != null && intent.hasFileDescriptors() == true) {
5951 throw new IllegalArgumentException("File descriptors passed in Intent");
5952 }
5953
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005954 if (type == INTENT_SENDER_BROADCAST) {
5955 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5956 throw new IllegalArgumentException(
5957 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5958 }
5959 }
5960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005961 synchronized(this) {
5962 int callingUid = Binder.getCallingUid();
5963 try {
5964 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5965 Process.supportsProcesses()) {
5966 int uid = ActivityThread.getPackageManager()
5967 .getPackageUid(packageName);
5968 if (uid != Binder.getCallingUid()) {
5969 String msg = "Permission Denial: getIntentSender() from pid="
5970 + Binder.getCallingPid()
5971 + ", uid=" + Binder.getCallingUid()
5972 + ", (need uid=" + uid + ")"
5973 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005974 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975 throw new SecurityException(msg);
5976 }
5977 }
5978 } catch (RemoteException e) {
5979 throw new SecurityException(e);
5980 }
5981 HistoryRecord activity = null;
5982 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005983 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 if (index < 0) {
5985 return null;
5986 }
5987 activity = (HistoryRecord)mHistory.get(index);
5988 if (activity.finishing) {
5989 return null;
5990 }
5991 }
5992
5993 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5994 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5995 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5996 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5997 |PendingIntent.FLAG_UPDATE_CURRENT);
5998
5999 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6000 type, packageName, activity, resultWho,
6001 requestCode, intent, resolvedType, flags);
6002 WeakReference<PendingIntentRecord> ref;
6003 ref = mIntentSenderRecords.get(key);
6004 PendingIntentRecord rec = ref != null ? ref.get() : null;
6005 if (rec != null) {
6006 if (!cancelCurrent) {
6007 if (updateCurrent) {
6008 rec.key.requestIntent.replaceExtras(intent);
6009 }
6010 return rec;
6011 }
6012 rec.canceled = true;
6013 mIntentSenderRecords.remove(key);
6014 }
6015 if (noCreate) {
6016 return rec;
6017 }
6018 rec = new PendingIntentRecord(this, key, callingUid);
6019 mIntentSenderRecords.put(key, rec.ref);
6020 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6021 if (activity.pendingResults == null) {
6022 activity.pendingResults
6023 = new HashSet<WeakReference<PendingIntentRecord>>();
6024 }
6025 activity.pendingResults.add(rec.ref);
6026 }
6027 return rec;
6028 }
6029 }
6030
6031 public void cancelIntentSender(IIntentSender sender) {
6032 if (!(sender instanceof PendingIntentRecord)) {
6033 return;
6034 }
6035 synchronized(this) {
6036 PendingIntentRecord rec = (PendingIntentRecord)sender;
6037 try {
6038 int uid = ActivityThread.getPackageManager()
6039 .getPackageUid(rec.key.packageName);
6040 if (uid != Binder.getCallingUid()) {
6041 String msg = "Permission Denial: cancelIntentSender() from pid="
6042 + Binder.getCallingPid()
6043 + ", uid=" + Binder.getCallingUid()
6044 + " is not allowed to cancel packges "
6045 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006046 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 throw new SecurityException(msg);
6048 }
6049 } catch (RemoteException e) {
6050 throw new SecurityException(e);
6051 }
6052 cancelIntentSenderLocked(rec, true);
6053 }
6054 }
6055
6056 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6057 rec.canceled = true;
6058 mIntentSenderRecords.remove(rec.key);
6059 if (cleanActivity && rec.key.activity != null) {
6060 rec.key.activity.pendingResults.remove(rec.ref);
6061 }
6062 }
6063
6064 public String getPackageForIntentSender(IIntentSender pendingResult) {
6065 if (!(pendingResult instanceof PendingIntentRecord)) {
6066 return null;
6067 }
6068 synchronized(this) {
6069 try {
6070 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6071 return res.key.packageName;
6072 } catch (ClassCastException e) {
6073 }
6074 }
6075 return null;
6076 }
6077
6078 public void setProcessLimit(int max) {
6079 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6080 "setProcessLimit()");
6081 mProcessLimit = max;
6082 }
6083
6084 public int getProcessLimit() {
6085 return mProcessLimit;
6086 }
6087
6088 void foregroundTokenDied(ForegroundToken token) {
6089 synchronized (ActivityManagerService.this) {
6090 synchronized (mPidsSelfLocked) {
6091 ForegroundToken cur
6092 = mForegroundProcesses.get(token.pid);
6093 if (cur != token) {
6094 return;
6095 }
6096 mForegroundProcesses.remove(token.pid);
6097 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6098 if (pr == null) {
6099 return;
6100 }
6101 pr.forcingToForeground = null;
6102 pr.foregroundServices = false;
6103 }
6104 updateOomAdjLocked();
6105 }
6106 }
6107
6108 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6109 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6110 "setProcessForeground()");
6111 synchronized(this) {
6112 boolean changed = false;
6113
6114 synchronized (mPidsSelfLocked) {
6115 ProcessRecord pr = mPidsSelfLocked.get(pid);
6116 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006117 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006118 return;
6119 }
6120 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6121 if (oldToken != null) {
6122 oldToken.token.unlinkToDeath(oldToken, 0);
6123 mForegroundProcesses.remove(pid);
6124 pr.forcingToForeground = null;
6125 changed = true;
6126 }
6127 if (isForeground && token != null) {
6128 ForegroundToken newToken = new ForegroundToken() {
6129 public void binderDied() {
6130 foregroundTokenDied(this);
6131 }
6132 };
6133 newToken.pid = pid;
6134 newToken.token = token;
6135 try {
6136 token.linkToDeath(newToken, 0);
6137 mForegroundProcesses.put(pid, newToken);
6138 pr.forcingToForeground = token;
6139 changed = true;
6140 } catch (RemoteException e) {
6141 // If the process died while doing this, we will later
6142 // do the cleanup with the process death link.
6143 }
6144 }
6145 }
6146
6147 if (changed) {
6148 updateOomAdjLocked();
6149 }
6150 }
6151 }
6152
6153 // =========================================================
6154 // PERMISSIONS
6155 // =========================================================
6156
6157 static class PermissionController extends IPermissionController.Stub {
6158 ActivityManagerService mActivityManagerService;
6159 PermissionController(ActivityManagerService activityManagerService) {
6160 mActivityManagerService = activityManagerService;
6161 }
6162
6163 public boolean checkPermission(String permission, int pid, int uid) {
6164 return mActivityManagerService.checkPermission(permission, pid,
6165 uid) == PackageManager.PERMISSION_GRANTED;
6166 }
6167 }
6168
6169 /**
6170 * This can be called with or without the global lock held.
6171 */
6172 int checkComponentPermission(String permission, int pid, int uid,
6173 int reqUid) {
6174 // We might be performing an operation on behalf of an indirect binder
6175 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6176 // client identity accordingly before proceeding.
6177 Identity tlsIdentity = sCallerIdentity.get();
6178 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006179 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006180 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6181 uid = tlsIdentity.uid;
6182 pid = tlsIdentity.pid;
6183 }
6184
6185 // Root, system server and our own process get to do everything.
6186 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6187 !Process.supportsProcesses()) {
6188 return PackageManager.PERMISSION_GRANTED;
6189 }
6190 // If the target requires a specific UID, always fail for others.
6191 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006192 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006193 return PackageManager.PERMISSION_DENIED;
6194 }
6195 if (permission == null) {
6196 return PackageManager.PERMISSION_GRANTED;
6197 }
6198 try {
6199 return ActivityThread.getPackageManager()
6200 .checkUidPermission(permission, uid);
6201 } catch (RemoteException e) {
6202 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006203 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006204 }
6205 return PackageManager.PERMISSION_DENIED;
6206 }
6207
6208 /**
6209 * As the only public entry point for permissions checking, this method
6210 * can enforce the semantic that requesting a check on a null global
6211 * permission is automatically denied. (Internally a null permission
6212 * string is used when calling {@link #checkComponentPermission} in cases
6213 * when only uid-based security is needed.)
6214 *
6215 * This can be called with or without the global lock held.
6216 */
6217 public int checkPermission(String permission, int pid, int uid) {
6218 if (permission == null) {
6219 return PackageManager.PERMISSION_DENIED;
6220 }
6221 return checkComponentPermission(permission, pid, uid, -1);
6222 }
6223
6224 /**
6225 * Binder IPC calls go through the public entry point.
6226 * This can be called with or without the global lock held.
6227 */
6228 int checkCallingPermission(String permission) {
6229 return checkPermission(permission,
6230 Binder.getCallingPid(),
6231 Binder.getCallingUid());
6232 }
6233
6234 /**
6235 * This can be called with or without the global lock held.
6236 */
6237 void enforceCallingPermission(String permission, String func) {
6238 if (checkCallingPermission(permission)
6239 == PackageManager.PERMISSION_GRANTED) {
6240 return;
6241 }
6242
6243 String msg = "Permission Denial: " + func + " from pid="
6244 + Binder.getCallingPid()
6245 + ", uid=" + Binder.getCallingUid()
6246 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006247 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006248 throw new SecurityException(msg);
6249 }
6250
6251 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6252 ProviderInfo pi, int uid, int modeFlags) {
6253 try {
6254 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6255 if ((pi.readPermission != null) &&
6256 (pm.checkUidPermission(pi.readPermission, uid)
6257 != PackageManager.PERMISSION_GRANTED)) {
6258 return false;
6259 }
6260 }
6261 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6262 if ((pi.writePermission != null) &&
6263 (pm.checkUidPermission(pi.writePermission, uid)
6264 != PackageManager.PERMISSION_GRANTED)) {
6265 return false;
6266 }
6267 }
6268 return true;
6269 } catch (RemoteException e) {
6270 return false;
6271 }
6272 }
6273
6274 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6275 int modeFlags) {
6276 // Root gets to do everything.
6277 if (uid == 0 || !Process.supportsProcesses()) {
6278 return true;
6279 }
6280 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6281 if (perms == null) return false;
6282 UriPermission perm = perms.get(uri);
6283 if (perm == null) return false;
6284 return (modeFlags&perm.modeFlags) == modeFlags;
6285 }
6286
6287 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6288 // Another redirected-binder-call permissions check as in
6289 // {@link checkComponentPermission}.
6290 Identity tlsIdentity = sCallerIdentity.get();
6291 if (tlsIdentity != null) {
6292 uid = tlsIdentity.uid;
6293 pid = tlsIdentity.pid;
6294 }
6295
6296 // Our own process gets to do everything.
6297 if (pid == MY_PID) {
6298 return PackageManager.PERMISSION_GRANTED;
6299 }
6300 synchronized(this) {
6301 return checkUriPermissionLocked(uri, uid, modeFlags)
6302 ? PackageManager.PERMISSION_GRANTED
6303 : PackageManager.PERMISSION_DENIED;
6304 }
6305 }
6306
6307 private void grantUriPermissionLocked(int callingUid,
6308 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6309 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6310 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6311 if (modeFlags == 0) {
6312 return;
6313 }
6314
Joe Onorato8a9b2202010-02-26 18:56:32 -08006315 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006316 "Requested grant " + targetPkg + " permission to " + uri);
6317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006318 final IPackageManager pm = ActivityThread.getPackageManager();
6319
6320 // If this is not a content: uri, we can't do anything with it.
6321 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006322 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006323 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006324 return;
6325 }
6326
6327 String name = uri.getAuthority();
6328 ProviderInfo pi = null;
6329 ContentProviderRecord cpr
6330 = (ContentProviderRecord)mProvidersByName.get(name);
6331 if (cpr != null) {
6332 pi = cpr.info;
6333 } else {
6334 try {
6335 pi = pm.resolveContentProvider(name,
6336 PackageManager.GET_URI_PERMISSION_PATTERNS);
6337 } catch (RemoteException ex) {
6338 }
6339 }
6340 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006341 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 return;
6343 }
6344
6345 int targetUid;
6346 try {
6347 targetUid = pm.getPackageUid(targetPkg);
6348 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006349 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006350 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 return;
6352 }
6353 } catch (RemoteException ex) {
6354 return;
6355 }
6356
6357 // First... does the target actually need this permission?
6358 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6359 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006360 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006361 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006362 return;
6363 }
6364
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006365 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006366 if (!pi.grantUriPermissions) {
6367 throw new SecurityException("Provider " + pi.packageName
6368 + "/" + pi.name
6369 + " does not allow granting of Uri permissions (uri "
6370 + uri + ")");
6371 }
6372 if (pi.uriPermissionPatterns != null) {
6373 final int N = pi.uriPermissionPatterns.length;
6374 boolean allowed = false;
6375 for (int i=0; i<N; i++) {
6376 if (pi.uriPermissionPatterns[i] != null
6377 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6378 allowed = true;
6379 break;
6380 }
6381 }
6382 if (!allowed) {
6383 throw new SecurityException("Provider " + pi.packageName
6384 + "/" + pi.name
6385 + " does not allow granting of permission to path of Uri "
6386 + uri);
6387 }
6388 }
6389
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006390 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006391 // this uri?
6392 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6393 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6394 throw new SecurityException("Uid " + callingUid
6395 + " does not have permission to uri " + uri);
6396 }
6397 }
6398
6399 // Okay! So here we are: the caller has the assumed permission
6400 // to the uri, and the target doesn't. Let's now give this to
6401 // the target.
6402
Joe Onorato8a9b2202010-02-26 18:56:32 -08006403 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006404 "Granting " + targetPkg + " permission to " + uri);
6405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006406 HashMap<Uri, UriPermission> targetUris
6407 = mGrantedUriPermissions.get(targetUid);
6408 if (targetUris == null) {
6409 targetUris = new HashMap<Uri, UriPermission>();
6410 mGrantedUriPermissions.put(targetUid, targetUris);
6411 }
6412
6413 UriPermission perm = targetUris.get(uri);
6414 if (perm == null) {
6415 perm = new UriPermission(targetUid, uri);
6416 targetUris.put(uri, perm);
6417
6418 }
6419 perm.modeFlags |= modeFlags;
6420 if (activity == null) {
6421 perm.globalModeFlags |= modeFlags;
6422 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6423 perm.readActivities.add(activity);
6424 if (activity.readUriPermissions == null) {
6425 activity.readUriPermissions = new HashSet<UriPermission>();
6426 }
6427 activity.readUriPermissions.add(perm);
6428 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6429 perm.writeActivities.add(activity);
6430 if (activity.writeUriPermissions == null) {
6431 activity.writeUriPermissions = new HashSet<UriPermission>();
6432 }
6433 activity.writeUriPermissions.add(perm);
6434 }
6435 }
6436
6437 private void grantUriPermissionFromIntentLocked(int callingUid,
6438 String targetPkg, Intent intent, HistoryRecord activity) {
6439 if (intent == null) {
6440 return;
6441 }
6442 Uri data = intent.getData();
6443 if (data == null) {
6444 return;
6445 }
6446 grantUriPermissionLocked(callingUid, targetPkg, data,
6447 intent.getFlags(), activity);
6448 }
6449
6450 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6451 Uri uri, int modeFlags) {
6452 synchronized(this) {
6453 final ProcessRecord r = getRecordForAppLocked(caller);
6454 if (r == null) {
6455 throw new SecurityException("Unable to find app for caller "
6456 + caller
6457 + " when granting permission to uri " + uri);
6458 }
6459 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006460 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006461 return;
6462 }
6463 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006464 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 return;
6466 }
6467
6468 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6469 null);
6470 }
6471 }
6472
6473 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6474 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6475 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6476 HashMap<Uri, UriPermission> perms
6477 = mGrantedUriPermissions.get(perm.uid);
6478 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006479 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006480 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006481 perms.remove(perm.uri);
6482 if (perms.size() == 0) {
6483 mGrantedUriPermissions.remove(perm.uid);
6484 }
6485 }
6486 }
6487 }
6488
6489 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6490 if (activity.readUriPermissions != null) {
6491 for (UriPermission perm : activity.readUriPermissions) {
6492 perm.readActivities.remove(activity);
6493 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6494 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6495 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6496 removeUriPermissionIfNeededLocked(perm);
6497 }
6498 }
6499 }
6500 if (activity.writeUriPermissions != null) {
6501 for (UriPermission perm : activity.writeUriPermissions) {
6502 perm.writeActivities.remove(activity);
6503 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6504 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6505 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6506 removeUriPermissionIfNeededLocked(perm);
6507 }
6508 }
6509 }
6510 }
6511
6512 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6513 int modeFlags) {
6514 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6515 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6516 if (modeFlags == 0) {
6517 return;
6518 }
6519
Joe Onorato8a9b2202010-02-26 18:56:32 -08006520 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006521 "Revoking all granted permissions to " + uri);
6522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 final IPackageManager pm = ActivityThread.getPackageManager();
6524
6525 final String authority = uri.getAuthority();
6526 ProviderInfo pi = null;
6527 ContentProviderRecord cpr
6528 = (ContentProviderRecord)mProvidersByName.get(authority);
6529 if (cpr != null) {
6530 pi = cpr.info;
6531 } else {
6532 try {
6533 pi = pm.resolveContentProvider(authority,
6534 PackageManager.GET_URI_PERMISSION_PATTERNS);
6535 } catch (RemoteException ex) {
6536 }
6537 }
6538 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006539 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006540 return;
6541 }
6542
6543 // Does the caller have this permission on the URI?
6544 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6545 // Right now, if you are not the original owner of the permission,
6546 // you are not allowed to revoke it.
6547 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6548 throw new SecurityException("Uid " + callingUid
6549 + " does not have permission to uri " + uri);
6550 //}
6551 }
6552
6553 // Go through all of the permissions and remove any that match.
6554 final List<String> SEGMENTS = uri.getPathSegments();
6555 if (SEGMENTS != null) {
6556 final int NS = SEGMENTS.size();
6557 int N = mGrantedUriPermissions.size();
6558 for (int i=0; i<N; i++) {
6559 HashMap<Uri, UriPermission> perms
6560 = mGrantedUriPermissions.valueAt(i);
6561 Iterator<UriPermission> it = perms.values().iterator();
6562 toploop:
6563 while (it.hasNext()) {
6564 UriPermission perm = it.next();
6565 Uri targetUri = perm.uri;
6566 if (!authority.equals(targetUri.getAuthority())) {
6567 continue;
6568 }
6569 List<String> targetSegments = targetUri.getPathSegments();
6570 if (targetSegments == null) {
6571 continue;
6572 }
6573 if (targetSegments.size() < NS) {
6574 continue;
6575 }
6576 for (int j=0; j<NS; j++) {
6577 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6578 continue toploop;
6579 }
6580 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006581 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006582 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006583 perm.clearModes(modeFlags);
6584 if (perm.modeFlags == 0) {
6585 it.remove();
6586 }
6587 }
6588 if (perms.size() == 0) {
6589 mGrantedUriPermissions.remove(
6590 mGrantedUriPermissions.keyAt(i));
6591 N--;
6592 i--;
6593 }
6594 }
6595 }
6596 }
6597
6598 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6599 int modeFlags) {
6600 synchronized(this) {
6601 final ProcessRecord r = getRecordForAppLocked(caller);
6602 if (r == null) {
6603 throw new SecurityException("Unable to find app for caller "
6604 + caller
6605 + " when revoking permission to uri " + uri);
6606 }
6607 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006608 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006609 return;
6610 }
6611
6612 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6613 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6614 if (modeFlags == 0) {
6615 return;
6616 }
6617
6618 final IPackageManager pm = ActivityThread.getPackageManager();
6619
6620 final String authority = uri.getAuthority();
6621 ProviderInfo pi = null;
6622 ContentProviderRecord cpr
6623 = (ContentProviderRecord)mProvidersByName.get(authority);
6624 if (cpr != null) {
6625 pi = cpr.info;
6626 } else {
6627 try {
6628 pi = pm.resolveContentProvider(authority,
6629 PackageManager.GET_URI_PERMISSION_PATTERNS);
6630 } catch (RemoteException ex) {
6631 }
6632 }
6633 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006634 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006635 return;
6636 }
6637
6638 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6639 }
6640 }
6641
6642 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6643 synchronized (this) {
6644 ProcessRecord app =
6645 who != null ? getRecordForAppLocked(who) : null;
6646 if (app == null) return;
6647
6648 Message msg = Message.obtain();
6649 msg.what = WAIT_FOR_DEBUGGER_MSG;
6650 msg.obj = app;
6651 msg.arg1 = waiting ? 1 : 0;
6652 mHandler.sendMessage(msg);
6653 }
6654 }
6655
6656 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6657 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006658 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006659 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006660 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006661 }
6662
6663 // =========================================================
6664 // TASK MANAGEMENT
6665 // =========================================================
6666
6667 public List getTasks(int maxNum, int flags,
6668 IThumbnailReceiver receiver) {
6669 ArrayList list = new ArrayList();
6670
6671 PendingThumbnailsRecord pending = null;
6672 IApplicationThread topThumbnail = null;
6673 HistoryRecord topRecord = null;
6674
6675 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006676 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006677 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6678 + ", receiver=" + receiver);
6679
6680 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6681 != PackageManager.PERMISSION_GRANTED) {
6682 if (receiver != null) {
6683 // If the caller wants to wait for pending thumbnails,
6684 // it ain't gonna get them.
6685 try {
6686 receiver.finished();
6687 } catch (RemoteException ex) {
6688 }
6689 }
6690 String msg = "Permission Denial: getTasks() from pid="
6691 + Binder.getCallingPid()
6692 + ", uid=" + Binder.getCallingUid()
6693 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006694 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006695 throw new SecurityException(msg);
6696 }
6697
6698 int pos = mHistory.size()-1;
6699 HistoryRecord next =
6700 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6701 HistoryRecord top = null;
6702 CharSequence topDescription = null;
6703 TaskRecord curTask = null;
6704 int numActivities = 0;
6705 int numRunning = 0;
6706 while (pos >= 0 && maxNum > 0) {
6707 final HistoryRecord r = next;
6708 pos--;
6709 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6710
6711 // Initialize state for next task if needed.
6712 if (top == null ||
6713 (top.state == ActivityState.INITIALIZING
6714 && top.task == r.task)) {
6715 top = r;
6716 topDescription = r.description;
6717 curTask = r.task;
6718 numActivities = numRunning = 0;
6719 }
6720
6721 // Add 'r' into the current task.
6722 numActivities++;
6723 if (r.app != null && r.app.thread != null) {
6724 numRunning++;
6725 }
6726 if (topDescription == null) {
6727 topDescription = r.description;
6728 }
6729
Joe Onorato8a9b2202010-02-26 18:56:32 -08006730 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006731 TAG, r.intent.getComponent().flattenToShortString()
6732 + ": task=" + r.task);
6733
6734 // If the next one is a different task, generate a new
6735 // TaskInfo entry for what we have.
6736 if (next == null || next.task != curTask) {
6737 ActivityManager.RunningTaskInfo ci
6738 = new ActivityManager.RunningTaskInfo();
6739 ci.id = curTask.taskId;
6740 ci.baseActivity = r.intent.getComponent();
6741 ci.topActivity = top.intent.getComponent();
6742 ci.thumbnail = top.thumbnail;
6743 ci.description = topDescription;
6744 ci.numActivities = numActivities;
6745 ci.numRunning = numRunning;
6746 //System.out.println(
6747 // "#" + maxNum + ": " + " descr=" + ci.description);
6748 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006749 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006750 TAG, "State=" + top.state + "Idle=" + top.idle
6751 + " app=" + top.app
6752 + " thr=" + (top.app != null ? top.app.thread : null));
6753 if (top.state == ActivityState.RESUMED
6754 || top.state == ActivityState.PAUSING) {
6755 if (top.idle && top.app != null
6756 && top.app.thread != null) {
6757 topRecord = top;
6758 topThumbnail = top.app.thread;
6759 } else {
6760 top.thumbnailNeeded = true;
6761 }
6762 }
6763 if (pending == null) {
6764 pending = new PendingThumbnailsRecord(receiver);
6765 }
6766 pending.pendingRecords.add(top);
6767 }
6768 list.add(ci);
6769 maxNum--;
6770 top = null;
6771 }
6772 }
6773
6774 if (pending != null) {
6775 mPendingThumbnails.add(pending);
6776 }
6777 }
6778
Joe Onorato8a9b2202010-02-26 18:56:32 -08006779 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006780
6781 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006782 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006783 try {
6784 topThumbnail.requestThumbnail(topRecord);
6785 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006786 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006787 sendPendingThumbnail(null, topRecord, null, null, true);
6788 }
6789 }
6790
6791 if (pending == null && receiver != null) {
6792 // In this case all thumbnails were available and the client
6793 // is being asked to be told when the remaining ones come in...
6794 // which is unusually, since the top-most currently running
6795 // activity should never have a canned thumbnail! Oh well.
6796 try {
6797 receiver.finished();
6798 } catch (RemoteException ex) {
6799 }
6800 }
6801
6802 return list;
6803 }
6804
6805 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6806 int flags) {
6807 synchronized (this) {
6808 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6809 "getRecentTasks()");
6810
6811 final int N = mRecentTasks.size();
6812 ArrayList<ActivityManager.RecentTaskInfo> res
6813 = new ArrayList<ActivityManager.RecentTaskInfo>(
6814 maxNum < N ? maxNum : N);
6815 for (int i=0; i<N && maxNum > 0; i++) {
6816 TaskRecord tr = mRecentTasks.get(i);
6817 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6818 || (tr.intent == null)
6819 || ((tr.intent.getFlags()
6820 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6821 ActivityManager.RecentTaskInfo rti
6822 = new ActivityManager.RecentTaskInfo();
6823 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6824 rti.baseIntent = new Intent(
6825 tr.intent != null ? tr.intent : tr.affinityIntent);
6826 rti.origActivity = tr.origActivity;
6827 res.add(rti);
6828 maxNum--;
6829 }
6830 }
6831 return res;
6832 }
6833 }
6834
6835 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6836 int j;
6837 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6838 TaskRecord jt = startTask;
6839
6840 // First look backwards
6841 for (j=startIndex-1; j>=0; j--) {
6842 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6843 if (r.task != jt) {
6844 jt = r.task;
6845 if (affinity.equals(jt.affinity)) {
6846 return j;
6847 }
6848 }
6849 }
6850
6851 // Now look forwards
6852 final int N = mHistory.size();
6853 jt = startTask;
6854 for (j=startIndex+1; j<N; j++) {
6855 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6856 if (r.task != jt) {
6857 if (affinity.equals(jt.affinity)) {
6858 return j;
6859 }
6860 jt = r.task;
6861 }
6862 }
6863
6864 // Might it be at the top?
6865 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6866 return N-1;
6867 }
6868
6869 return -1;
6870 }
6871
6872 /**
6873 * Perform a reset of the given task, if needed as part of launching it.
6874 * Returns the new HistoryRecord at the top of the task.
6875 */
6876 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6877 HistoryRecord newActivity) {
6878 boolean forceReset = (newActivity.info.flags
6879 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6880 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6881 if ((newActivity.info.flags
6882 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6883 forceReset = true;
6884 }
6885 }
6886
6887 final TaskRecord task = taskTop.task;
6888
6889 // We are going to move through the history list so that we can look
6890 // at each activity 'target' with 'below' either the interesting
6891 // activity immediately below it in the stack or null.
6892 HistoryRecord target = null;
6893 int targetI = 0;
6894 int taskTopI = -1;
6895 int replyChainEnd = -1;
6896 int lastReparentPos = -1;
6897 for (int i=mHistory.size()-1; i>=-1; i--) {
6898 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6899
6900 if (below != null && below.finishing) {
6901 continue;
6902 }
6903 if (target == null) {
6904 target = below;
6905 targetI = i;
6906 // If we were in the middle of a reply chain before this
6907 // task, it doesn't appear like the root of the chain wants
6908 // anything interesting, so drop it.
6909 replyChainEnd = -1;
6910 continue;
6911 }
6912
6913 final int flags = target.info.flags;
6914
6915 final boolean finishOnTaskLaunch =
6916 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6917 final boolean allowTaskReparenting =
6918 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6919
6920 if (target.task == task) {
6921 // We are inside of the task being reset... we'll either
6922 // finish this activity, push it out for another task,
6923 // or leave it as-is. We only do this
6924 // for activities that are not the root of the task (since
6925 // if we finish the root, we may no longer have the task!).
6926 if (taskTopI < 0) {
6927 taskTopI = targetI;
6928 }
6929 if (below != null && below.task == task) {
6930 final boolean clearWhenTaskReset =
6931 (target.intent.getFlags()
6932 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006933 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006934 // If this activity is sending a reply to a previous
6935 // activity, we can't do anything with it now until
6936 // we reach the start of the reply chain.
6937 // XXX note that we are assuming the result is always
6938 // to the previous activity, which is almost always
6939 // the case but we really shouldn't count on.
6940 if (replyChainEnd < 0) {
6941 replyChainEnd = targetI;
6942 }
Ed Heyl73798232009-03-24 21:32:21 -07006943 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006944 && target.taskAffinity != null
6945 && !target.taskAffinity.equals(task.affinity)) {
6946 // If this activity has an affinity for another
6947 // task, then we need to move it out of here. We will
6948 // move it as far out of the way as possible, to the
6949 // bottom of the activity stack. This also keeps it
6950 // correctly ordered with any activities we previously
6951 // moved.
6952 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6953 if (target.taskAffinity != null
6954 && target.taskAffinity.equals(p.task.affinity)) {
6955 // If the activity currently at the bottom has the
6956 // same task affinity as the one we are moving,
6957 // then merge it into the same task.
6958 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006959 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006960 + " out to bottom task " + p.task);
6961 } else {
6962 mCurTask++;
6963 if (mCurTask <= 0) {
6964 mCurTask = 1;
6965 }
6966 target.task = new TaskRecord(mCurTask, target.info, null,
6967 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6968 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006969 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006970 + " out to new task " + target.task);
6971 }
6972 mWindowManager.setAppGroupId(target, task.taskId);
6973 if (replyChainEnd < 0) {
6974 replyChainEnd = targetI;
6975 }
6976 int dstPos = 0;
6977 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6978 p = (HistoryRecord)mHistory.get(srcPos);
6979 if (p.finishing) {
6980 continue;
6981 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006982 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006983 + " out to target's task " + target.task);
6984 task.numActivities--;
6985 p.task = target.task;
6986 target.task.numActivities++;
6987 mHistory.remove(srcPos);
6988 mHistory.add(dstPos, p);
6989 mWindowManager.moveAppToken(dstPos, p);
6990 mWindowManager.setAppGroupId(p, p.task.taskId);
6991 dstPos++;
6992 if (VALIDATE_TOKENS) {
6993 mWindowManager.validateAppTokens(mHistory);
6994 }
6995 i++;
6996 }
6997 if (taskTop == p) {
6998 taskTop = below;
6999 }
7000 if (taskTopI == replyChainEnd) {
7001 taskTopI = -1;
7002 }
7003 replyChainEnd = -1;
7004 addRecentTask(target.task);
7005 } else if (forceReset || finishOnTaskLaunch
7006 || clearWhenTaskReset) {
7007 // If the activity should just be removed -- either
7008 // because it asks for it, or the task should be
7009 // cleared -- then finish it and anything that is
7010 // part of its reply chain.
7011 if (clearWhenTaskReset) {
7012 // In this case, we want to finish this activity
7013 // and everything above it, so be sneaky and pretend
7014 // like these are all in the reply chain.
7015 replyChainEnd = targetI+1;
7016 while (replyChainEnd < mHistory.size() &&
7017 ((HistoryRecord)mHistory.get(
7018 replyChainEnd)).task == task) {
7019 replyChainEnd++;
7020 }
7021 replyChainEnd--;
7022 } else if (replyChainEnd < 0) {
7023 replyChainEnd = targetI;
7024 }
7025 HistoryRecord p = null;
7026 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7027 p = (HistoryRecord)mHistory.get(srcPos);
7028 if (p.finishing) {
7029 continue;
7030 }
7031 if (finishActivityLocked(p, srcPos,
7032 Activity.RESULT_CANCELED, null, "reset")) {
7033 replyChainEnd--;
7034 srcPos--;
7035 }
7036 }
7037 if (taskTop == p) {
7038 taskTop = below;
7039 }
7040 if (taskTopI == replyChainEnd) {
7041 taskTopI = -1;
7042 }
7043 replyChainEnd = -1;
7044 } else {
7045 // If we were in the middle of a chain, well the
7046 // activity that started it all doesn't want anything
7047 // special, so leave it all as-is.
7048 replyChainEnd = -1;
7049 }
7050 } else {
7051 // Reached the bottom of the task -- any reply chain
7052 // should be left as-is.
7053 replyChainEnd = -1;
7054 }
7055
7056 } else if (target.resultTo != null) {
7057 // If this activity is sending a reply to a previous
7058 // activity, we can't do anything with it now until
7059 // we reach the start of the reply chain.
7060 // XXX note that we are assuming the result is always
7061 // to the previous activity, which is almost always
7062 // the case but we really shouldn't count on.
7063 if (replyChainEnd < 0) {
7064 replyChainEnd = targetI;
7065 }
7066
7067 } else if (taskTopI >= 0 && allowTaskReparenting
7068 && task.affinity != null
7069 && task.affinity.equals(target.taskAffinity)) {
7070 // We are inside of another task... if this activity has
7071 // an affinity for our task, then either remove it if we are
7072 // clearing or move it over to our task. Note that
7073 // we currently punt on the case where we are resetting a
7074 // task that is not at the top but who has activities above
7075 // with an affinity to it... this is really not a normal
7076 // case, and we will need to later pull that task to the front
7077 // and usually at that point we will do the reset and pick
7078 // up those remaining activities. (This only happens if
7079 // someone starts an activity in a new task from an activity
7080 // in a task that is not currently on top.)
7081 if (forceReset || finishOnTaskLaunch) {
7082 if (replyChainEnd < 0) {
7083 replyChainEnd = targetI;
7084 }
7085 HistoryRecord p = null;
7086 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7087 p = (HistoryRecord)mHistory.get(srcPos);
7088 if (p.finishing) {
7089 continue;
7090 }
7091 if (finishActivityLocked(p, srcPos,
7092 Activity.RESULT_CANCELED, null, "reset")) {
7093 taskTopI--;
7094 lastReparentPos--;
7095 replyChainEnd--;
7096 srcPos--;
7097 }
7098 }
7099 replyChainEnd = -1;
7100 } else {
7101 if (replyChainEnd < 0) {
7102 replyChainEnd = targetI;
7103 }
7104 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7105 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7106 if (p.finishing) {
7107 continue;
7108 }
7109 if (lastReparentPos < 0) {
7110 lastReparentPos = taskTopI;
7111 taskTop = p;
7112 } else {
7113 lastReparentPos--;
7114 }
7115 mHistory.remove(srcPos);
7116 p.task.numActivities--;
7117 p.task = task;
7118 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007119 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007120 + " in to resetting task " + task);
7121 task.numActivities++;
7122 mWindowManager.moveAppToken(lastReparentPos, p);
7123 mWindowManager.setAppGroupId(p, p.task.taskId);
7124 if (VALIDATE_TOKENS) {
7125 mWindowManager.validateAppTokens(mHistory);
7126 }
7127 }
7128 replyChainEnd = -1;
7129
7130 // Now we've moved it in to place... but what if this is
7131 // a singleTop activity and we have put it on top of another
7132 // instance of the same activity? Then we drop the instance
7133 // below so it remains singleTop.
7134 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7135 for (int j=lastReparentPos-1; j>=0; j--) {
7136 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7137 if (p.finishing) {
7138 continue;
7139 }
7140 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7141 if (finishActivityLocked(p, j,
7142 Activity.RESULT_CANCELED, null, "replace")) {
7143 taskTopI--;
7144 lastReparentPos--;
7145 }
7146 }
7147 }
7148 }
7149 }
7150 }
7151
7152 target = below;
7153 targetI = i;
7154 }
7155
7156 return taskTop;
7157 }
7158
7159 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007160 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007161 */
7162 public void moveTaskToFront(int task) {
7163 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7164 "moveTaskToFront()");
7165
7166 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007167 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7168 Binder.getCallingUid(), "Task to front")) {
7169 return;
7170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007171 final long origId = Binder.clearCallingIdentity();
7172 try {
7173 int N = mRecentTasks.size();
7174 for (int i=0; i<N; i++) {
7175 TaskRecord tr = mRecentTasks.get(i);
7176 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007177 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007178 return;
7179 }
7180 }
7181 for (int i=mHistory.size()-1; i>=0; i--) {
7182 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7183 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007184 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007185 return;
7186 }
7187 }
7188 } finally {
7189 Binder.restoreCallingIdentity(origId);
7190 }
7191 }
7192 }
7193
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007194 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007195 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007196
7197 final int task = tr.taskId;
7198 int top = mHistory.size()-1;
7199
7200 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7201 // nothing to do!
7202 return;
7203 }
7204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007205 ArrayList moved = new ArrayList();
7206
7207 // Applying the affinities may have removed entries from the history,
7208 // so get the size again.
7209 top = mHistory.size()-1;
7210 int pos = top;
7211
7212 // Shift all activities with this task up to the top
7213 // of the stack, keeping them in the same internal order.
7214 while (pos >= 0) {
7215 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007216 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007217 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7218 boolean first = true;
7219 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007220 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007221 mHistory.remove(pos);
7222 mHistory.add(top, r);
7223 moved.add(0, r);
7224 top--;
7225 if (first) {
7226 addRecentTask(r.task);
7227 first = false;
7228 }
7229 }
7230 pos--;
7231 }
7232
Joe Onorato8a9b2202010-02-26 18:56:32 -08007233 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007234 "Prepare to front transition: task=" + tr);
7235 if (reason != null &&
7236 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7237 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7238 HistoryRecord r = topRunningActivityLocked(null);
7239 if (r != null) {
7240 mNoAnimActivities.add(r);
7241 }
7242 } else {
7243 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7244 }
7245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007246 mWindowManager.moveAppTokensToTop(moved);
7247 if (VALIDATE_TOKENS) {
7248 mWindowManager.validateAppTokens(mHistory);
7249 }
7250
7251 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007252 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007253 }
7254
7255 private final void finishTaskMove(int task) {
7256 resumeTopActivityLocked(null);
7257 }
7258
7259 public void moveTaskToBack(int task) {
7260 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7261 "moveTaskToBack()");
7262
7263 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007264 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7265 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7266 Binder.getCallingUid(), "Task to back")) {
7267 return;
7268 }
7269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007270 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007271 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 Binder.restoreCallingIdentity(origId);
7273 }
7274 }
7275
7276 /**
7277 * Moves an activity, and all of the other activities within the same task, to the bottom
7278 * of the history stack. The activity's order within the task is unchanged.
7279 *
7280 * @param token A reference to the activity we wish to move
7281 * @param nonRoot If false then this only works if the activity is the root
7282 * of a task; if true it will work for any activity in a task.
7283 * @return Returns true if the move completed, false if not.
7284 */
7285 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7286 synchronized(this) {
7287 final long origId = Binder.clearCallingIdentity();
7288 int taskId = getTaskForActivityLocked(token, !nonRoot);
7289 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007290 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007291 }
7292 Binder.restoreCallingIdentity(origId);
7293 }
7294 return false;
7295 }
7296
7297 /**
7298 * Worker method for rearranging history stack. Implements the function of moving all
7299 * activities for a specific task (gathering them if disjoint) into a single group at the
7300 * bottom of the stack.
7301 *
7302 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7303 * to premeptively cancel the move.
7304 *
7305 * @param task The taskId to collect and move to the bottom.
7306 * @return Returns true if the move completed, false if not.
7307 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007308 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007309 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007310
7311 // If we have a watcher, preflight the move before committing to it. First check
7312 // for *other* available tasks, but if none are available, then try again allowing the
7313 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007314 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007315 HistoryRecord next = topRunningActivityLocked(null, task);
7316 if (next == null) {
7317 next = topRunningActivityLocked(null, 0);
7318 }
7319 if (next != null) {
7320 // ask watcher if this is allowed
7321 boolean moveOK = true;
7322 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007323 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007325 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 }
7327 if (!moveOK) {
7328 return false;
7329 }
7330 }
7331 }
7332
7333 ArrayList moved = new ArrayList();
7334
Joe Onorato8a9b2202010-02-26 18:56:32 -08007335 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007336 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007337
7338 final int N = mHistory.size();
7339 int bottom = 0;
7340 int pos = 0;
7341
7342 // Shift all activities with this task down to the bottom
7343 // of the stack, keeping them in the same internal order.
7344 while (pos < N) {
7345 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007346 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007347 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7348 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007349 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 mHistory.remove(pos);
7351 mHistory.add(bottom, r);
7352 moved.add(r);
7353 bottom++;
7354 }
7355 pos++;
7356 }
7357
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007358 if (reason != null &&
7359 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7360 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7361 HistoryRecord r = topRunningActivityLocked(null);
7362 if (r != null) {
7363 mNoAnimActivities.add(r);
7364 }
7365 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007366 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 mWindowManager.moveAppTokensToBottom(moved);
7369 if (VALIDATE_TOKENS) {
7370 mWindowManager.validateAppTokens(mHistory);
7371 }
7372
7373 finishTaskMove(task);
7374 return true;
7375 }
7376
7377 public void moveTaskBackwards(int task) {
7378 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7379 "moveTaskBackwards()");
7380
7381 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007382 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7383 Binder.getCallingUid(), "Task backwards")) {
7384 return;
7385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386 final long origId = Binder.clearCallingIdentity();
7387 moveTaskBackwardsLocked(task);
7388 Binder.restoreCallingIdentity(origId);
7389 }
7390 }
7391
7392 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007393 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007394 }
7395
7396 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7397 synchronized(this) {
7398 return getTaskForActivityLocked(token, onlyRoot);
7399 }
7400 }
7401
7402 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7403 final int N = mHistory.size();
7404 TaskRecord lastTask = null;
7405 for (int i=0; i<N; i++) {
7406 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7407 if (r == token) {
7408 if (!onlyRoot || lastTask != r.task) {
7409 return r.task.taskId;
7410 }
7411 return -1;
7412 }
7413 lastTask = r.task;
7414 }
7415
7416 return -1;
7417 }
7418
7419 /**
7420 * Returns the top activity in any existing task matching the given
7421 * Intent. Returns null if no such task is found.
7422 */
7423 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7424 ComponentName cls = intent.getComponent();
7425 if (info.targetActivity != null) {
7426 cls = new ComponentName(info.packageName, info.targetActivity);
7427 }
7428
7429 TaskRecord cp = null;
7430
7431 final int N = mHistory.size();
7432 for (int i=(N-1); i>=0; i--) {
7433 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7434 if (!r.finishing && r.task != cp
7435 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7436 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007437 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 // + "/aff=" + r.task.affinity + " to new cls="
7439 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7440 if (r.task.affinity != null) {
7441 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007442 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007443 return r;
7444 }
7445 } else if (r.task.intent != null
7446 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007447 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007448 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007449 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007450 return r;
7451 } else if (r.task.affinityIntent != null
7452 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007453 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007454 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007455 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007456 return r;
7457 }
7458 }
7459 }
7460
7461 return null;
7462 }
7463
7464 /**
7465 * Returns the first activity (starting from the top of the stack) that
7466 * is the same as the given activity. Returns null if no such activity
7467 * is found.
7468 */
7469 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7470 ComponentName cls = intent.getComponent();
7471 if (info.targetActivity != null) {
7472 cls = new ComponentName(info.packageName, info.targetActivity);
7473 }
7474
7475 final int N = mHistory.size();
7476 for (int i=(N-1); i>=0; i--) {
7477 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7478 if (!r.finishing) {
7479 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007480 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007482 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007483 return r;
7484 }
7485 }
7486 }
7487
7488 return null;
7489 }
7490
7491 public void finishOtherInstances(IBinder token, ComponentName className) {
7492 synchronized(this) {
7493 final long origId = Binder.clearCallingIdentity();
7494
7495 int N = mHistory.size();
7496 TaskRecord lastTask = null;
7497 for (int i=0; i<N; i++) {
7498 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7499 if (r.realActivity.equals(className)
7500 && r != token && lastTask != r.task) {
7501 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7502 null, "others")) {
7503 i--;
7504 N--;
7505 }
7506 }
7507 lastTask = r.task;
7508 }
7509
7510 Binder.restoreCallingIdentity(origId);
7511 }
7512 }
7513
7514 // =========================================================
7515 // THUMBNAILS
7516 // =========================================================
7517
7518 public void reportThumbnail(IBinder token,
7519 Bitmap thumbnail, CharSequence description) {
7520 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7521 final long origId = Binder.clearCallingIdentity();
7522 sendPendingThumbnail(null, token, thumbnail, description, true);
7523 Binder.restoreCallingIdentity(origId);
7524 }
7525
7526 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7527 Bitmap thumbnail, CharSequence description, boolean always) {
7528 TaskRecord task = null;
7529 ArrayList receivers = null;
7530
7531 //System.out.println("Send pending thumbnail: " + r);
7532
7533 synchronized(this) {
7534 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007535 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007536 if (index < 0) {
7537 return;
7538 }
7539 r = (HistoryRecord)mHistory.get(index);
7540 }
7541 if (thumbnail == null) {
7542 thumbnail = r.thumbnail;
7543 description = r.description;
7544 }
7545 if (thumbnail == null && !always) {
7546 // If there is no thumbnail, and this entry is not actually
7547 // going away, then abort for now and pick up the next
7548 // thumbnail we get.
7549 return;
7550 }
7551 task = r.task;
7552
7553 int N = mPendingThumbnails.size();
7554 int i=0;
7555 while (i<N) {
7556 PendingThumbnailsRecord pr =
7557 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7558 //System.out.println("Looking in " + pr.pendingRecords);
7559 if (pr.pendingRecords.remove(r)) {
7560 if (receivers == null) {
7561 receivers = new ArrayList();
7562 }
7563 receivers.add(pr);
7564 if (pr.pendingRecords.size() == 0) {
7565 pr.finished = true;
7566 mPendingThumbnails.remove(i);
7567 N--;
7568 continue;
7569 }
7570 }
7571 i++;
7572 }
7573 }
7574
7575 if (receivers != null) {
7576 final int N = receivers.size();
7577 for (int i=0; i<N; i++) {
7578 try {
7579 PendingThumbnailsRecord pr =
7580 (PendingThumbnailsRecord)receivers.get(i);
7581 pr.receiver.newThumbnail(
7582 task != null ? task.taskId : -1, thumbnail, description);
7583 if (pr.finished) {
7584 pr.receiver.finished();
7585 }
7586 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007587 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007588 }
7589 }
7590 }
7591 }
7592
7593 // =========================================================
7594 // CONTENT PROVIDERS
7595 // =========================================================
7596
7597 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7598 List providers = null;
7599 try {
7600 providers = ActivityThread.getPackageManager().
7601 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007602 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 } catch (RemoteException ex) {
7604 }
7605 if (providers != null) {
7606 final int N = providers.size();
7607 for (int i=0; i<N; i++) {
7608 ProviderInfo cpi =
7609 (ProviderInfo)providers.get(i);
7610 ContentProviderRecord cpr =
7611 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7612 if (cpr == null) {
7613 cpr = new ContentProviderRecord(cpi, app.info);
7614 mProvidersByClass.put(cpi.name, cpr);
7615 }
7616 app.pubProviders.put(cpi.name, cpr);
7617 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007618 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007619 }
7620 }
7621 return providers;
7622 }
7623
7624 private final String checkContentProviderPermissionLocked(
7625 ProviderInfo cpi, ProcessRecord r, int mode) {
7626 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7627 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7628 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7629 cpi.exported ? -1 : cpi.applicationInfo.uid)
7630 == PackageManager.PERMISSION_GRANTED
7631 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7632 return null;
7633 }
7634 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7635 cpi.exported ? -1 : cpi.applicationInfo.uid)
7636 == PackageManager.PERMISSION_GRANTED) {
7637 return null;
7638 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007639
7640 PathPermission[] pps = cpi.pathPermissions;
7641 if (pps != null) {
7642 int i = pps.length;
7643 while (i > 0) {
7644 i--;
7645 PathPermission pp = pps[i];
7646 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7647 cpi.exported ? -1 : cpi.applicationInfo.uid)
7648 == PackageManager.PERMISSION_GRANTED
7649 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7650 return null;
7651 }
7652 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7653 cpi.exported ? -1 : cpi.applicationInfo.uid)
7654 == PackageManager.PERMISSION_GRANTED) {
7655 return null;
7656 }
7657 }
7658 }
7659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007660 String msg = "Permission Denial: opening provider " + cpi.name
7661 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7662 + ", uid=" + callingUid + ") requires "
7663 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007664 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 return msg;
7666 }
7667
7668 private final ContentProviderHolder getContentProviderImpl(
7669 IApplicationThread caller, String name) {
7670 ContentProviderRecord cpr;
7671 ProviderInfo cpi = null;
7672
7673 synchronized(this) {
7674 ProcessRecord r = null;
7675 if (caller != null) {
7676 r = getRecordForAppLocked(caller);
7677 if (r == null) {
7678 throw new SecurityException(
7679 "Unable to find app for caller " + caller
7680 + " (pid=" + Binder.getCallingPid()
7681 + ") when getting content provider " + name);
7682 }
7683 }
7684
7685 // First check if this content provider has been published...
7686 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7687 if (cpr != null) {
7688 cpi = cpr.info;
7689 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7690 return new ContentProviderHolder(cpi,
7691 cpi.readPermission != null
7692 ? cpi.readPermission : cpi.writePermission);
7693 }
7694
7695 if (r != null && cpr.canRunHere(r)) {
7696 // This provider has been published or is in the process
7697 // of being published... but it is also allowed to run
7698 // in the caller's process, so don't make a connection
7699 // and just let the caller instantiate its own instance.
7700 if (cpr.provider != null) {
7701 // don't give caller the provider object, it needs
7702 // to make its own.
7703 cpr = new ContentProviderRecord(cpr);
7704 }
7705 return cpr;
7706 }
7707
7708 final long origId = Binder.clearCallingIdentity();
7709
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007710 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711 // return it right away.
7712 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007713 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007714 "Adding provider requested by "
7715 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007716 + cpr.info.processName);
7717 Integer cnt = r.conProviders.get(cpr);
7718 if (cnt == null) {
7719 r.conProviders.put(cpr, new Integer(1));
7720 } else {
7721 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7722 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007723 cpr.clients.add(r);
7724 } else {
7725 cpr.externals++;
7726 }
7727
7728 if (cpr.app != null) {
7729 updateOomAdjLocked(cpr.app);
7730 }
7731
7732 Binder.restoreCallingIdentity(origId);
7733
7734 } else {
7735 try {
7736 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007737 resolveContentProvider(name,
7738 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007739 } catch (RemoteException ex) {
7740 }
7741 if (cpi == null) {
7742 return null;
7743 }
7744
7745 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7746 return new ContentProviderHolder(cpi,
7747 cpi.readPermission != null
7748 ? cpi.readPermission : cpi.writePermission);
7749 }
7750
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007751 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7752 && !cpi.processName.equals("system")) {
7753 // If this content provider does not run in the system
7754 // process, and the system is not yet ready to run other
7755 // processes, then fail fast instead of hanging.
7756 throw new IllegalArgumentException(
7757 "Attempt to launch content provider before system ready");
7758 }
7759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007760 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7761 final boolean firstClass = cpr == null;
7762 if (firstClass) {
7763 try {
7764 ApplicationInfo ai =
7765 ActivityThread.getPackageManager().
7766 getApplicationInfo(
7767 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007768 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007769 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007770 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 + cpi.name);
7772 return null;
7773 }
7774 cpr = new ContentProviderRecord(cpi, ai);
7775 } catch (RemoteException ex) {
7776 // pm is in same process, this will never happen.
7777 }
7778 }
7779
7780 if (r != null && cpr.canRunHere(r)) {
7781 // If this is a multiprocess provider, then just return its
7782 // info and allow the caller to instantiate it. Only do
7783 // this if the provider is the same user as the caller's
7784 // process, or can run as root (so can be in any process).
7785 return cpr;
7786 }
7787
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007788 if (DEBUG_PROVIDER) {
7789 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007790 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007791 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 }
7793
7794 // This is single process, and our app is now connecting to it.
7795 // See if we are already in the process of launching this
7796 // provider.
7797 final int N = mLaunchingProviders.size();
7798 int i;
7799 for (i=0; i<N; i++) {
7800 if (mLaunchingProviders.get(i) == cpr) {
7801 break;
7802 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007803 }
7804
7805 // If the provider is not already being launched, then get it
7806 // started.
7807 if (i >= N) {
7808 final long origId = Binder.clearCallingIdentity();
7809 ProcessRecord proc = startProcessLocked(cpi.processName,
7810 cpr.appInfo, false, 0, "content provider",
7811 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007812 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007813 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007814 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007815 + cpi.applicationInfo.packageName + "/"
7816 + cpi.applicationInfo.uid + " for provider "
7817 + name + ": process is bad");
7818 return null;
7819 }
7820 cpr.launchingApp = proc;
7821 mLaunchingProviders.add(cpr);
7822 Binder.restoreCallingIdentity(origId);
7823 }
7824
7825 // Make sure the provider is published (the same provider class
7826 // may be published under multiple names).
7827 if (firstClass) {
7828 mProvidersByClass.put(cpi.name, cpr);
7829 }
7830 mProvidersByName.put(name, cpr);
7831
7832 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007833 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007834 "Adding provider requested by "
7835 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007836 + cpr.info.processName);
7837 Integer cnt = r.conProviders.get(cpr);
7838 if (cnt == null) {
7839 r.conProviders.put(cpr, new Integer(1));
7840 } else {
7841 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7842 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007843 cpr.clients.add(r);
7844 } else {
7845 cpr.externals++;
7846 }
7847 }
7848 }
7849
7850 // Wait for the provider to be published...
7851 synchronized (cpr) {
7852 while (cpr.provider == null) {
7853 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007854 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007855 + cpi.applicationInfo.packageName + "/"
7856 + cpi.applicationInfo.uid + " for provider "
7857 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007858 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007859 cpi.applicationInfo.packageName,
7860 cpi.applicationInfo.uid, name);
7861 return null;
7862 }
7863 try {
7864 cpr.wait();
7865 } catch (InterruptedException ex) {
7866 }
7867 }
7868 }
7869 return cpr;
7870 }
7871
7872 public final ContentProviderHolder getContentProvider(
7873 IApplicationThread caller, String name) {
7874 if (caller == null) {
7875 String msg = "null IApplicationThread when getting content provider "
7876 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007877 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007878 throw new SecurityException(msg);
7879 }
7880
7881 return getContentProviderImpl(caller, name);
7882 }
7883
7884 private ContentProviderHolder getContentProviderExternal(String name) {
7885 return getContentProviderImpl(null, name);
7886 }
7887
7888 /**
7889 * Drop a content provider from a ProcessRecord's bookkeeping
7890 * @param cpr
7891 */
7892 public void removeContentProvider(IApplicationThread caller, String name) {
7893 synchronized (this) {
7894 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7895 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007896 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007897 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007898 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007899 return;
7900 }
7901 final ProcessRecord r = getRecordForAppLocked(caller);
7902 if (r == null) {
7903 throw new SecurityException(
7904 "Unable to find app for caller " + caller +
7905 " when removing content provider " + name);
7906 }
7907 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007908 ContentProviderRecord localCpr = (ContentProviderRecord)
7909 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007910 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007911 + r.info.processName + " from process "
7912 + localCpr.appInfo.processName);
7913 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007914 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007915 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007916 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007917 return;
7918 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007919 Integer cnt = r.conProviders.get(localCpr);
7920 if (cnt == null || cnt.intValue() <= 1) {
7921 localCpr.clients.remove(r);
7922 r.conProviders.remove(localCpr);
7923 } else {
7924 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7925 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007926 }
7927 updateOomAdjLocked();
7928 }
7929 }
7930
7931 private void removeContentProviderExternal(String name) {
7932 synchronized (this) {
7933 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7934 if(cpr == null) {
7935 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007936 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007937 return;
7938 }
7939
7940 //update content provider record entry info
7941 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7942 localCpr.externals--;
7943 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007944 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 }
7946 updateOomAdjLocked();
7947 }
7948 }
7949
7950 public final void publishContentProviders(IApplicationThread caller,
7951 List<ContentProviderHolder> providers) {
7952 if (providers == null) {
7953 return;
7954 }
7955
7956 synchronized(this) {
7957 final ProcessRecord r = getRecordForAppLocked(caller);
7958 if (r == null) {
7959 throw new SecurityException(
7960 "Unable to find app for caller " + caller
7961 + " (pid=" + Binder.getCallingPid()
7962 + ") when publishing content providers");
7963 }
7964
7965 final long origId = Binder.clearCallingIdentity();
7966
7967 final int N = providers.size();
7968 for (int i=0; i<N; i++) {
7969 ContentProviderHolder src = providers.get(i);
7970 if (src == null || src.info == null || src.provider == null) {
7971 continue;
7972 }
7973 ContentProviderRecord dst =
7974 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7975 if (dst != null) {
7976 mProvidersByClass.put(dst.info.name, dst);
7977 String names[] = dst.info.authority.split(";");
7978 for (int j = 0; j < names.length; j++) {
7979 mProvidersByName.put(names[j], dst);
7980 }
7981
7982 int NL = mLaunchingProviders.size();
7983 int j;
7984 for (j=0; j<NL; j++) {
7985 if (mLaunchingProviders.get(j) == dst) {
7986 mLaunchingProviders.remove(j);
7987 j--;
7988 NL--;
7989 }
7990 }
7991 synchronized (dst) {
7992 dst.provider = src.provider;
7993 dst.app = r;
7994 dst.notifyAll();
7995 }
7996 updateOomAdjLocked(r);
7997 }
7998 }
7999
8000 Binder.restoreCallingIdentity(origId);
8001 }
8002 }
8003
8004 public static final void installSystemProviders() {
8005 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8006 List providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008007 if (providers != null) {
8008 for (int i=providers.size()-1; i>=0; i--) {
8009 ProviderInfo pi = (ProviderInfo)providers.get(i);
8010 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008011 Slog.w(TAG, "Not installing system proc provider " + pi.name
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008012 + ": not system .apk");
8013 providers.remove(i);
8014 }
8015 }
8016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008017 mSystemThread.installSystemProviders(providers);
8018 }
8019
8020 // =========================================================
8021 // GLOBAL MANAGEMENT
8022 // =========================================================
8023
8024 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8025 ApplicationInfo info, String customProcess) {
8026 String proc = customProcess != null ? customProcess : info.processName;
8027 BatteryStatsImpl.Uid.Proc ps = null;
8028 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8029 synchronized (stats) {
8030 ps = stats.getProcessStatsLocked(info.uid, proc);
8031 }
8032 return new ProcessRecord(ps, thread, info, proc);
8033 }
8034
8035 final ProcessRecord addAppLocked(ApplicationInfo info) {
8036 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8037
8038 if (app == null) {
8039 app = newProcessRecordLocked(null, info, null);
8040 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008041 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008042 }
8043
8044 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8045 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8046 app.persistent = true;
8047 app.maxAdj = CORE_SERVER_ADJ;
8048 }
8049 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8050 mPersistentStartingProcesses.add(app);
8051 startProcessLocked(app, "added application", app.processName);
8052 }
8053
8054 return app;
8055 }
8056
8057 public void unhandledBack() {
8058 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8059 "unhandledBack()");
8060
8061 synchronized(this) {
8062 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008063 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008064 TAG, "Performing unhandledBack(): stack size = " + count);
8065 if (count > 1) {
8066 final long origId = Binder.clearCallingIdentity();
8067 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8068 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8069 Binder.restoreCallingIdentity(origId);
8070 }
8071 }
8072 }
8073
8074 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8075 String name = uri.getAuthority();
8076 ContentProviderHolder cph = getContentProviderExternal(name);
8077 ParcelFileDescriptor pfd = null;
8078 if (cph != null) {
8079 // We record the binder invoker's uid in thread-local storage before
8080 // going to the content provider to open the file. Later, in the code
8081 // that handles all permissions checks, we look for this uid and use
8082 // that rather than the Activity Manager's own uid. The effect is that
8083 // we do the check against the caller's permissions even though it looks
8084 // to the content provider like the Activity Manager itself is making
8085 // the request.
8086 sCallerIdentity.set(new Identity(
8087 Binder.getCallingPid(), Binder.getCallingUid()));
8088 try {
8089 pfd = cph.provider.openFile(uri, "r");
8090 } catch (FileNotFoundException e) {
8091 // do nothing; pfd will be returned null
8092 } finally {
8093 // Ensure that whatever happens, we clean up the identity state
8094 sCallerIdentity.remove();
8095 }
8096
8097 // We've got the fd now, so we're done with the provider.
8098 removeContentProviderExternal(name);
8099 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008100 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008101 }
8102 return pfd;
8103 }
8104
8105 public void goingToSleep() {
8106 synchronized(this) {
8107 mSleeping = true;
8108 mWindowManager.setEventDispatching(false);
8109
8110 if (mResumedActivity != null) {
8111 pauseIfSleepingLocked();
8112 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008113 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008114 }
8115 }
8116 }
8117
Dianne Hackborn55280a92009-05-07 15:53:46 -07008118 public boolean shutdown(int timeout) {
8119 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8120 != PackageManager.PERMISSION_GRANTED) {
8121 throw new SecurityException("Requires permission "
8122 + android.Manifest.permission.SHUTDOWN);
8123 }
8124
8125 boolean timedout = false;
8126
8127 synchronized(this) {
8128 mShuttingDown = true;
8129 mWindowManager.setEventDispatching(false);
8130
8131 if (mResumedActivity != null) {
8132 pauseIfSleepingLocked();
8133 final long endTime = System.currentTimeMillis() + timeout;
8134 while (mResumedActivity != null || mPausingActivity != null) {
8135 long delay = endTime - System.currentTimeMillis();
8136 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008137 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008138 timedout = true;
8139 break;
8140 }
8141 try {
8142 this.wait();
8143 } catch (InterruptedException e) {
8144 }
8145 }
8146 }
8147 }
8148
8149 mUsageStatsService.shutdown();
8150 mBatteryStatsService.shutdown();
8151
8152 return timedout;
8153 }
8154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008155 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008156 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008157 if (!mGoingToSleep.isHeld()) {
8158 mGoingToSleep.acquire();
8159 if (mLaunchingActivity.isHeld()) {
8160 mLaunchingActivity.release();
8161 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8162 }
8163 }
8164
8165 // If we are not currently pausing an activity, get the current
8166 // one to pause. If we are pausing one, we will just let that stuff
8167 // run and release the wake lock when all done.
8168 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008169 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8170 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008171 startPausingLocked(false, true);
8172 }
8173 }
8174 }
8175
8176 public void wakingUp() {
8177 synchronized(this) {
8178 if (mGoingToSleep.isHeld()) {
8179 mGoingToSleep.release();
8180 }
8181 mWindowManager.setEventDispatching(true);
8182 mSleeping = false;
8183 resumeTopActivityLocked(null);
8184 }
8185 }
8186
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008187 public void stopAppSwitches() {
8188 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8189 != PackageManager.PERMISSION_GRANTED) {
8190 throw new SecurityException("Requires permission "
8191 + android.Manifest.permission.STOP_APP_SWITCHES);
8192 }
8193
8194 synchronized(this) {
8195 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8196 + APP_SWITCH_DELAY_TIME;
8197 mDidAppSwitch = false;
8198 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8199 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8200 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8201 }
8202 }
8203
8204 public void resumeAppSwitches() {
8205 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8206 != PackageManager.PERMISSION_GRANTED) {
8207 throw new SecurityException("Requires permission "
8208 + android.Manifest.permission.STOP_APP_SWITCHES);
8209 }
8210
8211 synchronized(this) {
8212 // Note that we don't execute any pending app switches... we will
8213 // let those wait until either the timeout, or the next start
8214 // activity request.
8215 mAppSwitchesAllowedTime = 0;
8216 }
8217 }
8218
8219 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8220 String name) {
8221 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8222 return true;
8223 }
8224
8225 final int perm = checkComponentPermission(
8226 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8227 callingUid, -1);
8228 if (perm == PackageManager.PERMISSION_GRANTED) {
8229 return true;
8230 }
8231
Joe Onorato8a9b2202010-02-26 18:56:32 -08008232 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008233 return false;
8234 }
8235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008236 public void setDebugApp(String packageName, boolean waitForDebugger,
8237 boolean persistent) {
8238 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8239 "setDebugApp()");
8240
8241 // Note that this is not really thread safe if there are multiple
8242 // callers into it at the same time, but that's not a situation we
8243 // care about.
8244 if (persistent) {
8245 final ContentResolver resolver = mContext.getContentResolver();
8246 Settings.System.putString(
8247 resolver, Settings.System.DEBUG_APP,
8248 packageName);
8249 Settings.System.putInt(
8250 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8251 waitForDebugger ? 1 : 0);
8252 }
8253
8254 synchronized (this) {
8255 if (!persistent) {
8256 mOrigDebugApp = mDebugApp;
8257 mOrigWaitForDebugger = mWaitForDebugger;
8258 }
8259 mDebugApp = packageName;
8260 mWaitForDebugger = waitForDebugger;
8261 mDebugTransient = !persistent;
8262 if (packageName != null) {
8263 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008264 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008265 Binder.restoreCallingIdentity(origId);
8266 }
8267 }
8268 }
8269
8270 public void setAlwaysFinish(boolean enabled) {
8271 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8272 "setAlwaysFinish()");
8273
8274 Settings.System.putInt(
8275 mContext.getContentResolver(),
8276 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8277
8278 synchronized (this) {
8279 mAlwaysFinishActivities = enabled;
8280 }
8281 }
8282
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008283 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008285 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008286 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008287 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008288 }
8289 }
8290
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008291 public boolean isUserAMonkey() {
8292 // For now the fact that there is a controller implies
8293 // we have a monkey.
8294 synchronized (this) {
8295 return mController != null;
8296 }
8297 }
8298
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008299 public void registerActivityWatcher(IActivityWatcher watcher) {
8300 mWatchers.register(watcher);
8301 }
8302
8303 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8304 mWatchers.unregister(watcher);
8305 }
8306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008307 public final void enterSafeMode() {
8308 synchronized(this) {
8309 // It only makes sense to do this before the system is ready
8310 // and started launching other packages.
8311 if (!mSystemReady) {
8312 try {
8313 ActivityThread.getPackageManager().enterSafeMode();
8314 } catch (RemoteException e) {
8315 }
8316
8317 View v = LayoutInflater.from(mContext).inflate(
8318 com.android.internal.R.layout.safe_mode, null);
8319 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8320 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8321 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8322 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8323 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8324 lp.format = v.getBackground().getOpacity();
8325 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8326 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8327 ((WindowManager)mContext.getSystemService(
8328 Context.WINDOW_SERVICE)).addView(v, lp);
8329 }
8330 }
8331 }
8332
8333 public void noteWakeupAlarm(IIntentSender sender) {
8334 if (!(sender instanceof PendingIntentRecord)) {
8335 return;
8336 }
8337 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8338 synchronized (stats) {
8339 if (mBatteryStatsService.isOnBattery()) {
8340 mBatteryStatsService.enforceCallingPermission();
8341 PendingIntentRecord rec = (PendingIntentRecord)sender;
8342 int MY_UID = Binder.getCallingUid();
8343 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8344 BatteryStatsImpl.Uid.Pkg pkg =
8345 stats.getPackageStatsLocked(uid, rec.key.packageName);
8346 pkg.incWakeupsLocked();
8347 }
8348 }
8349 }
8350
8351 public boolean killPidsForMemory(int[] pids) {
8352 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8353 throw new SecurityException("killPidsForMemory only available to the system");
8354 }
8355
8356 // XXX Note: don't acquire main activity lock here, because the window
8357 // manager calls in with its locks held.
8358
8359 boolean killed = false;
8360 synchronized (mPidsSelfLocked) {
8361 int[] types = new int[pids.length];
8362 int worstType = 0;
8363 for (int i=0; i<pids.length; i++) {
8364 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8365 if (proc != null) {
8366 int type = proc.setAdj;
8367 types[i] = type;
8368 if (type > worstType) {
8369 worstType = type;
8370 }
8371 }
8372 }
8373
8374 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8375 // then constrain it so we will kill all hidden procs.
8376 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8377 worstType = HIDDEN_APP_MIN_ADJ;
8378 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008379 Slog.w(TAG, "Killing processes for memory at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008380 for (int i=0; i<pids.length; i++) {
8381 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8382 if (proc == null) {
8383 continue;
8384 }
8385 int adj = proc.setAdj;
8386 if (adj >= worstType) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008387 Slog.w(TAG, "Killing for memory: " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008388 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008389 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008390 proc.processName, adj);
8391 killed = true;
8392 Process.killProcess(pids[i]);
8393 }
8394 }
8395 }
8396 return killed;
8397 }
8398
8399 public void reportPss(IApplicationThread caller, int pss) {
8400 Watchdog.PssRequestor req;
8401 String name;
8402 ProcessRecord callerApp;
8403 synchronized (this) {
8404 if (caller == null) {
8405 return;
8406 }
8407 callerApp = getRecordForAppLocked(caller);
8408 if (callerApp == null) {
8409 return;
8410 }
8411 callerApp.lastPss = pss;
8412 req = callerApp;
8413 name = callerApp.processName;
8414 }
8415 Watchdog.getInstance().reportPss(req, name, pss);
8416 if (!callerApp.persistent) {
8417 removeRequestedPss(callerApp);
8418 }
8419 }
8420
8421 public void requestPss(Runnable completeCallback) {
8422 ArrayList<ProcessRecord> procs;
8423 synchronized (this) {
8424 mRequestPssCallback = completeCallback;
8425 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008426 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8427 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008428 if (!proc.persistent) {
8429 mRequestPssList.add(proc);
8430 }
8431 }
8432 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8433 }
8434
8435 int oldPri = Process.getThreadPriority(Process.myTid());
8436 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8437 for (int i=procs.size()-1; i>=0; i--) {
8438 ProcessRecord proc = procs.get(i);
8439 proc.lastPss = 0;
8440 proc.requestPss();
8441 }
8442 Process.setThreadPriority(oldPri);
8443 }
8444
8445 void removeRequestedPss(ProcessRecord proc) {
8446 Runnable callback = null;
8447 synchronized (this) {
8448 if (mRequestPssList.remove(proc)) {
8449 if (mRequestPssList.size() == 0) {
8450 callback = mRequestPssCallback;
8451 mRequestPssCallback = null;
8452 }
8453 }
8454 }
8455
8456 if (callback != null) {
8457 callback.run();
8458 }
8459 }
8460
8461 public void collectPss(Watchdog.PssStats stats) {
8462 stats.mEmptyPss = 0;
8463 stats.mEmptyCount = 0;
8464 stats.mBackgroundPss = 0;
8465 stats.mBackgroundCount = 0;
8466 stats.mServicePss = 0;
8467 stats.mServiceCount = 0;
8468 stats.mVisiblePss = 0;
8469 stats.mVisibleCount = 0;
8470 stats.mForegroundPss = 0;
8471 stats.mForegroundCount = 0;
8472 stats.mNoPssCount = 0;
8473 synchronized (this) {
8474 int i;
8475 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8476 ? mProcDeaths.length : stats.mProcDeaths.length;
8477 int aggr = 0;
8478 for (i=0; i<NPD; i++) {
8479 aggr += mProcDeaths[i];
8480 stats.mProcDeaths[i] = aggr;
8481 }
8482 while (i<stats.mProcDeaths.length) {
8483 stats.mProcDeaths[i] = 0;
8484 i++;
8485 }
8486
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008487 for (i=mLruProcesses.size()-1; i>=0; i--) {
8488 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008489 if (proc.persistent) {
8490 continue;
8491 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008492 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 if (proc.lastPss == 0) {
8494 stats.mNoPssCount++;
8495 continue;
8496 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008497 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8498 if (proc.empty) {
8499 stats.mEmptyPss += proc.lastPss;
8500 stats.mEmptyCount++;
8501 } else {
8502 stats.mBackgroundPss += proc.lastPss;
8503 stats.mBackgroundCount++;
8504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008505 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8506 stats.mVisiblePss += proc.lastPss;
8507 stats.mVisibleCount++;
8508 } else {
8509 stats.mForegroundPss += proc.lastPss;
8510 stats.mForegroundCount++;
8511 }
8512 }
8513 }
8514 }
8515
8516 public final void startRunning(String pkg, String cls, String action,
8517 String data) {
8518 synchronized(this) {
8519 if (mStartRunning) {
8520 return;
8521 }
8522 mStartRunning = true;
8523 mTopComponent = pkg != null && cls != null
8524 ? new ComponentName(pkg, cls) : null;
8525 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8526 mTopData = data;
8527 if (!mSystemReady) {
8528 return;
8529 }
8530 }
8531
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008532 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008533 }
8534
8535 private void retrieveSettings() {
8536 final ContentResolver resolver = mContext.getContentResolver();
8537 String debugApp = Settings.System.getString(
8538 resolver, Settings.System.DEBUG_APP);
8539 boolean waitForDebugger = Settings.System.getInt(
8540 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8541 boolean alwaysFinishActivities = Settings.System.getInt(
8542 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8543
8544 Configuration configuration = new Configuration();
8545 Settings.System.getConfiguration(resolver, configuration);
8546
8547 synchronized (this) {
8548 mDebugApp = mOrigDebugApp = debugApp;
8549 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8550 mAlwaysFinishActivities = alwaysFinishActivities;
8551 // This happens before any activities are started, so we can
8552 // change mConfiguration in-place.
8553 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008554 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008555 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008556 }
8557 }
8558
8559 public boolean testIsSystemReady() {
8560 // no need to synchronize(this) just to read & return the value
8561 return mSystemReady;
8562 }
8563
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008564 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008565 // In the simulator, startRunning will never have been called, which
8566 // normally sets a few crucial variables. Do it here instead.
8567 if (!Process.supportsProcesses()) {
8568 mStartRunning = true;
8569 mTopAction = Intent.ACTION_MAIN;
8570 }
8571
8572 synchronized(this) {
8573 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008574 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 return;
8576 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008577
8578 // Check to see if there are any update receivers to run.
8579 if (!mDidUpdate) {
8580 if (mWaitingUpdate) {
8581 return;
8582 }
8583 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8584 List<ResolveInfo> ris = null;
8585 try {
8586 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8587 intent, null, 0);
8588 } catch (RemoteException e) {
8589 }
8590 if (ris != null) {
8591 for (int i=ris.size()-1; i>=0; i--) {
8592 if ((ris.get(i).activityInfo.applicationInfo.flags
8593 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8594 ris.remove(i);
8595 }
8596 }
8597 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8598 for (int i=0; i<ris.size(); i++) {
8599 ActivityInfo ai = ris.get(i).activityInfo;
8600 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8601 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008602 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008603 finisher = new IIntentReceiver.Stub() {
8604 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008605 String data, Bundle extras, boolean ordered,
8606 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008607 throws RemoteException {
8608 synchronized (ActivityManagerService.this) {
8609 mDidUpdate = true;
8610 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008611 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008612 }
8613 };
8614 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008615 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008616 broadcastIntentLocked(null, null, intent, null, finisher,
8617 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008618 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008619 mWaitingUpdate = true;
8620 }
8621 }
8622 }
8623 if (mWaitingUpdate) {
8624 return;
8625 }
8626 mDidUpdate = true;
8627 }
8628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008629 mSystemReady = true;
8630 if (!mStartRunning) {
8631 return;
8632 }
8633 }
8634
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008635 ArrayList<ProcessRecord> procsToKill = null;
8636 synchronized(mPidsSelfLocked) {
8637 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8638 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8639 if (!isAllowedWhileBooting(proc.info)){
8640 if (procsToKill == null) {
8641 procsToKill = new ArrayList<ProcessRecord>();
8642 }
8643 procsToKill.add(proc);
8644 }
8645 }
8646 }
8647
8648 if (procsToKill != null) {
8649 synchronized(this) {
8650 for (int i=procsToKill.size()-1; i>=0; i--) {
8651 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008652 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008653 removeProcessLocked(proc, true);
8654 }
8655 }
8656 }
8657
Joe Onorato8a9b2202010-02-26 18:56:32 -08008658 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008659 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660 SystemClock.uptimeMillis());
8661
8662 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008663 // Make sure we have no pre-ready processes sitting around.
8664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008665 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8666 ResolveInfo ri = mContext.getPackageManager()
8667 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008668 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 CharSequence errorMsg = null;
8670 if (ri != null) {
8671 ActivityInfo ai = ri.activityInfo;
8672 ApplicationInfo app = ai.applicationInfo;
8673 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8674 mTopAction = Intent.ACTION_FACTORY_TEST;
8675 mTopData = null;
8676 mTopComponent = new ComponentName(app.packageName,
8677 ai.name);
8678 } else {
8679 errorMsg = mContext.getResources().getText(
8680 com.android.internal.R.string.factorytest_not_system);
8681 }
8682 } else {
8683 errorMsg = mContext.getResources().getText(
8684 com.android.internal.R.string.factorytest_no_action);
8685 }
8686 if (errorMsg != null) {
8687 mTopAction = null;
8688 mTopData = null;
8689 mTopComponent = null;
8690 Message msg = Message.obtain();
8691 msg.what = SHOW_FACTORY_ERROR_MSG;
8692 msg.getData().putCharSequence("msg", errorMsg);
8693 mHandler.sendMessage(msg);
8694 }
8695 }
8696 }
8697
8698 retrieveSettings();
8699
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008700 if (goingCallback != null) goingCallback.run();
8701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008702 synchronized (this) {
8703 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8704 try {
8705 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008706 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008707 if (apps != null) {
8708 int N = apps.size();
8709 int i;
8710 for (i=0; i<N; i++) {
8711 ApplicationInfo info
8712 = (ApplicationInfo)apps.get(i);
8713 if (info != null &&
8714 !info.packageName.equals("android")) {
8715 addAppLocked(info);
8716 }
8717 }
8718 }
8719 } catch (RemoteException ex) {
8720 // pm is in same process, this will never happen.
8721 }
8722 }
8723
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008724 // Start up initial activity.
8725 mBooting = true;
8726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008727 try {
8728 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8729 Message msg = Message.obtain();
8730 msg.what = SHOW_UID_ERROR_MSG;
8731 mHandler.sendMessage(msg);
8732 }
8733 } catch (RemoteException e) {
8734 }
8735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008736 resumeTopActivityLocked(null);
8737 }
8738 }
8739
Dan Egnorb7f03672009-12-09 16:22:32 -08008740 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008741 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008742 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008743 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008744 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 startAppProblemLocked(app);
8746 app.stopFreezingAllLocked();
8747 return handleAppCrashLocked(app);
8748 }
8749
Dan Egnorb7f03672009-12-09 16:22:32 -08008750 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008751 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008752 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008753 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008754 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8755 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008756 startAppProblemLocked(app);
8757 app.stopFreezingAllLocked();
8758 }
8759
8760 /**
8761 * Generate a process error record, suitable for attachment to a ProcessRecord.
8762 *
8763 * @param app The ProcessRecord in which the error occurred.
8764 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8765 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008766 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008767 * @param shortMsg Short message describing the crash.
8768 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008769 * @param stackTrace Full crash stack trace, may be null.
8770 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008771 * @return Returns a fully-formed AppErrorStateInfo record.
8772 */
8773 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008774 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008775 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008777 report.condition = condition;
8778 report.processName = app.processName;
8779 report.pid = app.pid;
8780 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008781 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 report.shortMsg = shortMsg;
8783 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008784 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008785
8786 return report;
8787 }
8788
Dan Egnor42471dd2010-01-07 17:25:22 -08008789 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008790 synchronized (this) {
8791 app.crashing = false;
8792 app.crashingReport = null;
8793 app.notResponding = false;
8794 app.notRespondingReport = null;
8795 if (app.anrDialog == fromDialog) {
8796 app.anrDialog = null;
8797 }
8798 if (app.waitDialog == fromDialog) {
8799 app.waitDialog = null;
8800 }
8801 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008802 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008803 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008804 + app.processName
8805 + " (pid=" + app.pid + ") at user's request");
8806 Process.killProcess(app.pid);
8807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008808 }
8809 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008810
Dan Egnorb7f03672009-12-09 16:22:32 -08008811 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 long now = SystemClock.uptimeMillis();
8813
8814 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8815 app.info.uid);
8816 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8817 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008818 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008820 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008821 app.info.processName, app.info.uid);
8822 killServicesLocked(app, false);
8823 for (int i=mHistory.size()-1; i>=0; i--) {
8824 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8825 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008826 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008827 + r.intent.getComponent().flattenToShortString());
8828 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8829 }
8830 }
8831 if (!app.persistent) {
8832 // We don't want to start this process again until the user
8833 // explicitly does so... but for persistent process, we really
8834 // need to keep it running. If a persistent process is actually
8835 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008836 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008837 app.info.processName);
8838 mBadProcesses.put(app.info.processName, app.info.uid, now);
8839 app.bad = true;
8840 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8841 app.removed = true;
8842 removeProcessLocked(app, false);
8843 return false;
8844 }
8845 }
8846
8847 // Bump up the crash count of any services currently running in the proc.
8848 if (app.services.size() != 0) {
8849 // Any services running in the application need to be placed
8850 // back in the pending list.
8851 Iterator it = app.services.iterator();
8852 while (it.hasNext()) {
8853 ServiceRecord sr = (ServiceRecord)it.next();
8854 sr.crashCount++;
8855 }
8856 }
8857
8858 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8859 return true;
8860 }
8861
8862 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008863 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8864 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008865 skipCurrentReceiverLocked(app);
8866 }
8867
8868 void skipCurrentReceiverLocked(ProcessRecord app) {
8869 boolean reschedule = false;
8870 BroadcastRecord r = app.curReceiver;
8871 if (r != null) {
8872 // The current broadcast is waiting for this app's receiver
8873 // to be finished. Looks like that's not going to happen, so
8874 // let the broadcast continue.
8875 logBroadcastReceiverDiscard(r);
8876 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8877 r.resultExtras, r.resultAbort, true);
8878 reschedule = true;
8879 }
8880 r = mPendingBroadcast;
8881 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008882 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008883 "skip & discard pending app " + r);
8884 logBroadcastReceiverDiscard(r);
8885 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8886 r.resultExtras, r.resultAbort, true);
8887 reschedule = true;
8888 }
8889 if (reschedule) {
8890 scheduleBroadcastsLocked();
8891 }
8892 }
8893
Dan Egnor60d87622009-12-16 16:32:58 -08008894 /**
8895 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8896 * The application process will exit immediately after this call returns.
8897 * @param app object of the crashing app, null for the system server
8898 * @param crashInfo describing the exception
8899 */
8900 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8901 ProcessRecord r = findAppProcess(app);
8902
8903 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8904 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008905 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008906 crashInfo.exceptionClassName,
8907 crashInfo.exceptionMessage,
8908 crashInfo.throwFileName,
8909 crashInfo.throwLineNumber);
8910
Dan Egnor42471dd2010-01-07 17:25:22 -08008911 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008912
8913 crashApplication(r, crashInfo);
8914 }
8915
8916 /**
8917 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8918 * @param app object of the crashing app, null for the system server
8919 * @param tag reported by the caller
8920 * @param crashInfo describing the context of the error
8921 * @return true if the process should exit immediately (WTF is fatal)
8922 */
8923 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008924 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008925 ProcessRecord r = findAppProcess(app);
8926
8927 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8928 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008929 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008930 tag, crashInfo.exceptionMessage);
8931
Dan Egnor42471dd2010-01-07 17:25:22 -08008932 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008933
Doug Zongker43866e02010-01-07 12:09:54 -08008934 if (Settings.Secure.getInt(mContext.getContentResolver(),
8935 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008936 crashApplication(r, crashInfo);
8937 return true;
8938 } else {
8939 return false;
8940 }
8941 }
8942
8943 /**
8944 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8945 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8946 */
8947 private ProcessRecord findAppProcess(IBinder app) {
8948 if (app == null) {
8949 return null;
8950 }
8951
8952 synchronized (this) {
8953 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8954 final int NA = apps.size();
8955 for (int ia=0; ia<NA; ia++) {
8956 ProcessRecord p = apps.valueAt(ia);
8957 if (p.thread != null && p.thread.asBinder() == app) {
8958 return p;
8959 }
8960 }
8961 }
8962
Joe Onorato8a9b2202010-02-26 18:56:32 -08008963 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008964 return null;
8965 }
8966 }
8967
8968 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008969 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008970 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008971 * @param process which caused the error, null means the system server
8972 * @param activity which triggered the error, null if unknown
8973 * @param parent activity related to the error, null if unknown
8974 * @param subject line related to the error, null if absent
8975 * @param report in long form describing the error, null if absent
8976 * @param logFile to include in the report, null if none
8977 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008978 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08008979 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08008980 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
8981 final String report, final File logFile,
8982 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08008983 // NOTE -- this must never acquire the ActivityManagerService lock,
8984 // otherwise the watchdog may be prevented from resetting the system.
8985
Dan Egnora455d192010-03-12 08:52:28 -08008986 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08008987 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08008988 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08008989 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08008990 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08008991 } else {
Dan Egnora455d192010-03-12 08:52:28 -08008992 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08008993 }
8994
Dan Egnora455d192010-03-12 08:52:28 -08008995 final String dropboxTag = prefix + eventType;
8996 final DropBoxManager dbox = (DropBoxManager)
8997 mContext.getSystemService(Context.DROPBOX_SERVICE);
8998
8999 // Exit early if the dropbox isn't configured to accept this report type.
9000 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9001
9002 final StringBuilder sb = new StringBuilder(1024);
9003 if (process == null || process.pid == MY_PID) {
9004 sb.append("Process: system_server\n");
9005 } else {
9006 sb.append("Process: ").append(process.processName).append("\n");
9007 }
9008 if (process != null) {
9009 int flags = process.info.flags;
9010 IPackageManager pm = ActivityThread.getPackageManager();
9011 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9012 for (String pkg : process.pkgList) {
9013 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009014 try {
Dan Egnora455d192010-03-12 08:52:28 -08009015 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9016 if (pi != null) {
9017 sb.append(" v").append(pi.versionCode);
9018 if (pi.versionName != null) {
9019 sb.append(" (").append(pi.versionName).append(")");
9020 }
9021 }
9022 } catch (RemoteException e) {
9023 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009024 }
Dan Egnora455d192010-03-12 08:52:28 -08009025 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009026 }
Dan Egnora455d192010-03-12 08:52:28 -08009027 }
9028 if (activity != null) {
9029 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9030 }
9031 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9032 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9033 }
9034 if (parent != null && parent != activity) {
9035 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9036 }
9037 if (subject != null) {
9038 sb.append("Subject: ").append(subject).append("\n");
9039 }
9040 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9041 sb.append("\n");
9042
9043 // Do the rest in a worker thread to avoid blocking the caller on I/O
9044 // (After this point, we shouldn't access AMS internal data structures.)
9045 Thread worker = new Thread("Error dump: " + dropboxTag) {
9046 @Override
9047 public void run() {
9048 if (report != null) {
9049 sb.append(report);
9050 }
9051 if (logFile != null) {
9052 try {
9053 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9054 } catch (IOException e) {
9055 Slog.e(TAG, "Error reading " + logFile, e);
9056 }
9057 }
9058 if (crashInfo != null && crashInfo.stackTrace != null) {
9059 sb.append(crashInfo.stackTrace);
9060 }
9061
9062 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9063 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9064 if (lines > 0) {
9065 sb.append("\n");
9066
9067 // Merge several logcat streams, and take the last N lines
9068 InputStreamReader input = null;
9069 try {
9070 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9071 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9072 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9073
9074 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9075 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9076 input = new InputStreamReader(logcat.getInputStream());
9077
9078 int num;
9079 char[] buf = new char[8192];
9080 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9081 } catch (IOException e) {
9082 Slog.e(TAG, "Error running logcat", e);
9083 } finally {
9084 if (input != null) try { input.close(); } catch (IOException e) {}
9085 }
9086 }
9087
9088 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009089 }
Dan Egnora455d192010-03-12 08:52:28 -08009090 };
9091
9092 if (process == null || process.pid == MY_PID) {
9093 worker.run(); // We may be about to die -- need to run this synchronously
9094 } else {
9095 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009096 }
9097 }
9098
9099 /**
9100 * Bring up the "unexpected error" dialog box for a crashing app.
9101 * Deal with edge cases (intercepts from instrumented applications,
9102 * ActivityController, error intent receivers, that sort of thing).
9103 * @param r the application crashing
9104 * @param crashInfo describing the failure
9105 */
9106 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009107 long timeMillis = System.currentTimeMillis();
9108 String shortMsg = crashInfo.exceptionClassName;
9109 String longMsg = crashInfo.exceptionMessage;
9110 String stackTrace = crashInfo.stackTrace;
9111 if (shortMsg != null && longMsg != null) {
9112 longMsg = shortMsg + ": " + longMsg;
9113 } else if (shortMsg != null) {
9114 longMsg = shortMsg;
9115 }
9116
Dan Egnor60d87622009-12-16 16:32:58 -08009117 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009118 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009119 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 try {
9121 String name = r != null ? r.processName : null;
9122 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009123 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009124 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009125 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009126 + " at watcher's request");
9127 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009128 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009129 }
9130 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009131 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009132 }
9133 }
9134
9135 final long origId = Binder.clearCallingIdentity();
9136
9137 // If this process is running instrumentation, finish it.
9138 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009139 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009140 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009141 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9142 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009143 Bundle info = new Bundle();
9144 info.putString("shortMsg", shortMsg);
9145 info.putString("longMsg", longMsg);
9146 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9147 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009148 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009149 }
9150
Dan Egnor60d87622009-12-16 16:32:58 -08009151 // If we can't identify the process or it's already exceeded its crash quota,
9152 // quit right away without showing a crash dialog.
9153 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009154 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009155 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009156 }
9157
9158 Message msg = Message.obtain();
9159 msg.what = SHOW_ERROR_MSG;
9160 HashMap data = new HashMap();
9161 data.put("result", result);
9162 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009163 msg.obj = data;
9164 mHandler.sendMessage(msg);
9165
9166 Binder.restoreCallingIdentity(origId);
9167 }
9168
9169 int res = result.get();
9170
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009171 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009172 synchronized (this) {
9173 if (r != null) {
9174 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9175 SystemClock.uptimeMillis());
9176 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009177 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009178 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009179 }
9180 }
9181
9182 if (appErrorIntent != null) {
9183 try {
9184 mContext.startActivity(appErrorIntent);
9185 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009186 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009190
9191 Intent createAppErrorIntentLocked(ProcessRecord r,
9192 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9193 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009194 if (report == null) {
9195 return null;
9196 }
9197 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9198 result.setComponent(r.errorReportReceiver);
9199 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9200 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9201 return result;
9202 }
9203
Dan Egnorb7f03672009-12-09 16:22:32 -08009204 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9205 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009206 if (r.errorReportReceiver == null) {
9207 return null;
9208 }
9209
9210 if (!r.crashing && !r.notResponding) {
9211 return null;
9212 }
9213
Dan Egnorb7f03672009-12-09 16:22:32 -08009214 ApplicationErrorReport report = new ApplicationErrorReport();
9215 report.packageName = r.info.packageName;
9216 report.installerPackageName = r.errorReportReceiver.getPackageName();
9217 report.processName = r.processName;
9218 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009219 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009220
Dan Egnorb7f03672009-12-09 16:22:32 -08009221 if (r.crashing) {
9222 report.type = ApplicationErrorReport.TYPE_CRASH;
9223 report.crashInfo = crashInfo;
9224 } else if (r.notResponding) {
9225 report.type = ApplicationErrorReport.TYPE_ANR;
9226 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009227
Dan Egnorb7f03672009-12-09 16:22:32 -08009228 report.anrInfo.activity = r.notRespondingReport.tag;
9229 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9230 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009231 }
9232
Dan Egnorb7f03672009-12-09 16:22:32 -08009233 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009234 }
9235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009236 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9237 // assume our apps are happy - lazy create the list
9238 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9239
9240 synchronized (this) {
9241
9242 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009243 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9244 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009245 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9246 // This one's in trouble, so we'll generate a report for it
9247 // crashes are higher priority (in case there's a crash *and* an anr)
9248 ActivityManager.ProcessErrorStateInfo report = null;
9249 if (app.crashing) {
9250 report = app.crashingReport;
9251 } else if (app.notResponding) {
9252 report = app.notRespondingReport;
9253 }
9254
9255 if (report != null) {
9256 if (errList == null) {
9257 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9258 }
9259 errList.add(report);
9260 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009261 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009262 " crashing = " + app.crashing +
9263 " notResponding = " + app.notResponding);
9264 }
9265 }
9266 }
9267 }
9268
9269 return errList;
9270 }
9271
9272 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9273 // Lazy instantiation of list
9274 List<ActivityManager.RunningAppProcessInfo> runList = null;
9275 synchronized (this) {
9276 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009277 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9278 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9280 // Generate process state info for running application
9281 ActivityManager.RunningAppProcessInfo currApp =
9282 new ActivityManager.RunningAppProcessInfo(app.processName,
9283 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009284 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009286 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9288 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9289 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009290 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9291 } else if (adj >= HOME_APP_ADJ) {
9292 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9293 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009294 } else if (adj >= SECONDARY_SERVER_ADJ) {
9295 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9296 } else if (adj >= VISIBLE_APP_ADJ) {
9297 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9298 } else {
9299 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9300 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009301 currApp.importanceReasonCode = app.adjTypeCode;
9302 if (app.adjSource instanceof ProcessRecord) {
9303 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9304 } else if (app.adjSource instanceof HistoryRecord) {
9305 HistoryRecord r = (HistoryRecord)app.adjSource;
9306 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9307 }
9308 if (app.adjTarget instanceof ComponentName) {
9309 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9310 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009311 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 // + " lru=" + currApp.lru);
9313 if (runList == null) {
9314 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9315 }
9316 runList.add(currApp);
9317 }
9318 }
9319 }
9320 return runList;
9321 }
9322
9323 @Override
9324 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009325 if (checkCallingPermission(android.Manifest.permission.DUMP)
9326 != PackageManager.PERMISSION_GRANTED) {
9327 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9328 + Binder.getCallingPid()
9329 + ", uid=" + Binder.getCallingUid()
9330 + " without permission "
9331 + android.Manifest.permission.DUMP);
9332 return;
9333 }
9334
9335 boolean dumpAll = false;
9336
9337 int opti = 0;
9338 while (opti < args.length) {
9339 String opt = args[opti];
9340 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9341 break;
9342 }
9343 opti++;
9344 if ("-a".equals(opt)) {
9345 dumpAll = true;
9346 } else if ("-h".equals(opt)) {
9347 pw.println("Activity manager dump options:");
9348 pw.println(" [-a] [h- [cmd] ...");
9349 pw.println(" cmd may be one of:");
9350 pw.println(" activities: activity stack state");
9351 pw.println(" broadcasts: broadcast state");
9352 pw.println(" intents: pending intent state");
9353 pw.println(" processes: process state");
9354 pw.println(" providers: content provider state");
9355 pw.println(" services: service state");
9356 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009357 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009358 } else {
9359 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009360 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009361 }
9362
9363 // Is the caller requesting to dump a particular piece of data?
9364 if (opti < args.length) {
9365 String cmd = args[opti];
9366 opti++;
9367 if ("activities".equals(cmd) || "a".equals(cmd)) {
9368 synchronized (this) {
9369 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009370 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009371 return;
9372 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9373 synchronized (this) {
9374 dumpBroadcastsLocked(fd, pw, args, opti, true);
9375 }
9376 return;
9377 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9378 synchronized (this) {
9379 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9380 }
9381 return;
9382 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9383 synchronized (this) {
9384 dumpProcessesLocked(fd, pw, args, opti, true);
9385 }
9386 return;
9387 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9388 synchronized (this) {
9389 dumpProvidersLocked(fd, pw, args, opti, true);
9390 }
9391 return;
9392 } else if ("service".equals(cmd)) {
9393 dumpService(fd, pw, args, opti, true);
9394 return;
9395 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9396 synchronized (this) {
9397 dumpServicesLocked(fd, pw, args, opti, true);
9398 }
9399 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009400 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009401 }
9402
9403 // No piece of data specified, dump everything.
9404 synchronized (this) {
9405 boolean needSep;
9406 if (dumpAll) {
9407 pw.println("Providers in Current Activity Manager State:");
9408 }
9409 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9410 if (needSep) {
9411 pw.println(" ");
9412 }
9413 if (dumpAll) {
9414 pw.println("-------------------------------------------------------------------------------");
9415 pw.println("Broadcasts in Current Activity Manager State:");
9416 }
9417 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9418 if (needSep) {
9419 pw.println(" ");
9420 }
9421 if (dumpAll) {
9422 pw.println("-------------------------------------------------------------------------------");
9423 pw.println("Services in Current Activity Manager State:");
9424 }
9425 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9426 if (needSep) {
9427 pw.println(" ");
9428 }
9429 if (dumpAll) {
9430 pw.println("-------------------------------------------------------------------------------");
9431 pw.println("PendingIntents in Current Activity Manager State:");
9432 }
9433 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9434 if (needSep) {
9435 pw.println(" ");
9436 }
9437 if (dumpAll) {
9438 pw.println("-------------------------------------------------------------------------------");
9439 pw.println("Activities in Current Activity Manager State:");
9440 }
9441 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9442 if (needSep) {
9443 pw.println(" ");
9444 }
9445 if (dumpAll) {
9446 pw.println("-------------------------------------------------------------------------------");
9447 pw.println("Processes in Current Activity Manager State:");
9448 }
9449 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9450 }
9451 }
9452
9453 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9454 int opti, boolean dumpAll, boolean needHeader) {
9455 if (needHeader) {
9456 pw.println(" Activity stack:");
9457 }
9458 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9459 pw.println(" ");
9460 pw.println(" Running activities (most recent first):");
9461 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9462 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009463 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009464 pw.println(" Activities waiting for another to become visible:");
9465 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9466 }
9467 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009468 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009469 pw.println(" Activities waiting to stop:");
9470 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9471 }
9472 if (mFinishingActivities.size() > 0) {
9473 pw.println(" ");
9474 pw.println(" Activities waiting to finish:");
9475 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009477
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009478 pw.println(" ");
9479 pw.println(" mPausingActivity: " + mPausingActivity);
9480 pw.println(" mResumedActivity: " + mResumedActivity);
9481 pw.println(" mFocusedActivity: " + mFocusedActivity);
9482 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009483
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009484 if (dumpAll && mRecentTasks.size() > 0) {
9485 pw.println(" ");
9486 pw.println("Recent tasks in Current Activity Manager State:");
9487
9488 final int N = mRecentTasks.size();
9489 for (int i=0; i<N; i++) {
9490 TaskRecord tr = mRecentTasks.get(i);
9491 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9492 pw.println(tr);
9493 mRecentTasks.get(i).dump(pw, " ");
9494 }
9495 }
9496
9497 pw.println(" ");
9498 pw.println(" mCurTask: " + mCurTask);
9499
9500 return true;
9501 }
9502
9503 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9504 int opti, boolean dumpAll) {
9505 boolean needSep = false;
9506 int numPers = 0;
9507
9508 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009509 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9510 final int NA = procs.size();
9511 for (int ia=0; ia<NA; ia++) {
9512 if (!needSep) {
9513 pw.println(" All known processes:");
9514 needSep = true;
9515 }
9516 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009517 pw.print(r.persistent ? " *PERS*" : " *APP*");
9518 pw.print(" UID "); pw.print(procs.keyAt(ia));
9519 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009520 r.dump(pw, " ");
9521 if (r.persistent) {
9522 numPers++;
9523 }
9524 }
9525 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009526 }
9527
9528 if (mLruProcesses.size() > 0) {
9529 if (needSep) pw.println(" ");
9530 needSep = true;
9531 pw.println(" Running processes (most recent first):");
9532 dumpProcessList(pw, this, mLruProcesses, " ",
9533 "App ", "PERS", true);
9534 needSep = true;
9535 }
9536
9537 synchronized (mPidsSelfLocked) {
9538 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009539 if (needSep) pw.println(" ");
9540 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009541 pw.println(" PID mappings:");
9542 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9543 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9544 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 }
9546 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009547 }
9548
9549 if (mForegroundProcesses.size() > 0) {
9550 if (needSep) pw.println(" ");
9551 needSep = true;
9552 pw.println(" Foreground Processes:");
9553 for (int i=0; i<mForegroundProcesses.size(); i++) {
9554 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9555 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009556 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009557 }
9558
9559 if (mPersistentStartingProcesses.size() > 0) {
9560 if (needSep) pw.println(" ");
9561 needSep = true;
9562 pw.println(" Persisent processes that are starting:");
9563 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9564 "Starting Norm", "Restarting PERS", false);
9565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009566
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009567 if (mStartingProcesses.size() > 0) {
9568 if (needSep) pw.println(" ");
9569 needSep = true;
9570 pw.println(" Processes that are starting:");
9571 dumpProcessList(pw, this, mStartingProcesses, " ",
9572 "Starting Norm", "Starting PERS", false);
9573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009574
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009575 if (mRemovedProcesses.size() > 0) {
9576 if (needSep) pw.println(" ");
9577 needSep = true;
9578 pw.println(" Processes that are being removed:");
9579 dumpProcessList(pw, this, mRemovedProcesses, " ",
9580 "Removed Norm", "Removed PERS", false);
9581 }
9582
9583 if (mProcessesOnHold.size() > 0) {
9584 if (needSep) pw.println(" ");
9585 needSep = true;
9586 pw.println(" Processes that are on old until the system is ready:");
9587 dumpProcessList(pw, this, mProcessesOnHold, " ",
9588 "OnHold Norm", "OnHold PERS", false);
9589 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009591 if (mProcessesToGc.size() > 0) {
9592 if (needSep) pw.println(" ");
9593 needSep = true;
9594 pw.println(" Processes that are waiting to GC:");
9595 long now = SystemClock.uptimeMillis();
9596 for (int i=0; i<mProcessesToGc.size(); i++) {
9597 ProcessRecord proc = mProcessesToGc.get(i);
9598 pw.print(" Process "); pw.println(proc);
9599 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9600 pw.print(", last gced=");
9601 pw.print(now-proc.lastRequestedGc);
9602 pw.print(" ms ago, last lowMem=");
9603 pw.print(now-proc.lastLowMemory);
9604 pw.println(" ms ago");
9605
9606 }
9607 }
9608
9609 if (mProcessCrashTimes.getMap().size() > 0) {
9610 if (needSep) pw.println(" ");
9611 needSep = true;
9612 pw.println(" Time since processes crashed:");
9613 long now = SystemClock.uptimeMillis();
9614 for (Map.Entry<String, SparseArray<Long>> procs
9615 : mProcessCrashTimes.getMap().entrySet()) {
9616 SparseArray<Long> uids = procs.getValue();
9617 final int N = uids.size();
9618 for (int i=0; i<N; i++) {
9619 pw.print(" Process "); pw.print(procs.getKey());
9620 pw.print(" uid "); pw.print(uids.keyAt(i));
9621 pw.print(": last crashed ");
9622 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009623 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009624 }
9625 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009627
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009628 if (mBadProcesses.getMap().size() > 0) {
9629 if (needSep) pw.println(" ");
9630 needSep = true;
9631 pw.println(" Bad processes:");
9632 for (Map.Entry<String, SparseArray<Long>> procs
9633 : mBadProcesses.getMap().entrySet()) {
9634 SparseArray<Long> uids = procs.getValue();
9635 final int N = uids.size();
9636 for (int i=0; i<N; i++) {
9637 pw.print(" Bad process "); pw.print(procs.getKey());
9638 pw.print(" uid "); pw.print(uids.keyAt(i));
9639 pw.print(": crashed at time ");
9640 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009641 }
9642 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009643 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009644
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009645 pw.println(" ");
9646 pw.println(" mHomeProcess: " + mHomeProcess);
9647 pw.println(" mConfiguration: " + mConfiguration);
9648 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9649 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9650 || mOrigWaitForDebugger) {
9651 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9652 + " mDebugTransient=" + mDebugTransient
9653 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9654 }
9655 if (mAlwaysFinishActivities || mController != null) {
9656 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9657 + " mController=" + mController);
9658 }
9659 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009660 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009661 pw.println(" mStartRunning=" + mStartRunning
9662 + " mSystemReady=" + mSystemReady
9663 + " mBooting=" + mBooting
9664 + " mBooted=" + mBooted
9665 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009666 pw.println(" mGoingToSleep=" + mGoingToSleep);
9667 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009668 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009669
9670 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009671 }
9672
9673 /**
9674 * There are three ways to call this:
9675 * - no service specified: dump all the services
9676 * - a flattened component name that matched an existing service was specified as the
9677 * first arg: dump that one service
9678 * - the first arg isn't the flattened component name of an existing service:
9679 * dump all services whose component contains the first arg as a substring
9680 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009681 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9682 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 String[] newArgs;
9684 String componentNameString;
9685 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009686 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009687 componentNameString = null;
9688 newArgs = EMPTY_STRING_ARRAY;
9689 r = null;
9690 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009691 componentNameString = args[opti];
9692 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009693 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9694 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009695 newArgs = new String[args.length - opti];
9696 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009697 }
9698
9699 if (r != null) {
9700 dumpService(fd, pw, r, newArgs);
9701 } else {
9702 for (ServiceRecord r1 : mServices.values()) {
9703 if (componentNameString == null
9704 || r1.name.flattenToString().contains(componentNameString)) {
9705 dumpService(fd, pw, r1, newArgs);
9706 }
9707 }
9708 }
9709 }
9710
9711 /**
9712 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9713 * there is a thread associated with the service.
9714 */
9715 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9716 pw.println(" Service " + r.name.flattenToString());
9717 if (r.app != null && r.app.thread != null) {
9718 try {
9719 // flush anything that is already in the PrintWriter since the thread is going
9720 // to write to the file descriptor directly
9721 pw.flush();
9722 r.app.thread.dumpService(fd, r, args);
9723 pw.print("\n");
9724 } catch (RemoteException e) {
9725 pw.println("got a RemoteException while dumping the service");
9726 }
9727 }
9728 }
9729
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009730 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9731 int opti, boolean dumpAll) {
9732 boolean needSep = false;
9733
9734 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009735 if (mRegisteredReceivers.size() > 0) {
9736 pw.println(" ");
9737 pw.println(" Registered Receivers:");
9738 Iterator it = mRegisteredReceivers.values().iterator();
9739 while (it.hasNext()) {
9740 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009741 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009742 r.dump(pw, " ");
9743 }
9744 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009746 pw.println(" ");
9747 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009748 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009749 needSep = true;
9750 }
9751
9752 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9753 || mPendingBroadcast != null) {
9754 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009755 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009756 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009758 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9759 pw.println(" Broadcast #" + i + ":");
9760 mParallelBroadcasts.get(i).dump(pw, " ");
9761 }
9762 if (mOrderedBroadcasts.size() > 0) {
9763 pw.println(" ");
9764 pw.println(" Active serialized broadcasts:");
9765 }
9766 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9767 pw.println(" Serialized Broadcast #" + i + ":");
9768 mOrderedBroadcasts.get(i).dump(pw, " ");
9769 }
9770 pw.println(" ");
9771 pw.println(" Pending broadcast:");
9772 if (mPendingBroadcast != null) {
9773 mPendingBroadcast.dump(pw, " ");
9774 } else {
9775 pw.println(" (null)");
9776 }
9777 needSep = true;
9778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009779
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009780 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009781 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009782 pw.println(" Historical broadcasts:");
9783 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9784 BroadcastRecord r = mBroadcastHistory[i];
9785 if (r == null) {
9786 break;
9787 }
9788 pw.println(" Historical Broadcast #" + i + ":");
9789 r.dump(pw, " ");
9790 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009791 needSep = true;
9792 }
9793
9794 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009795 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009796 pw.println(" Sticky broadcasts:");
9797 StringBuilder sb = new StringBuilder(128);
9798 for (Map.Entry<String, ArrayList<Intent>> ent
9799 : mStickyBroadcasts.entrySet()) {
9800 pw.print(" * Sticky action "); pw.print(ent.getKey());
9801 pw.println(":");
9802 ArrayList<Intent> intents = ent.getValue();
9803 final int N = intents.size();
9804 for (int i=0; i<N; i++) {
9805 sb.setLength(0);
9806 sb.append(" Intent: ");
9807 intents.get(i).toShortString(sb, true, false);
9808 pw.println(sb.toString());
9809 Bundle bundle = intents.get(i).getExtras();
9810 if (bundle != null) {
9811 pw.print(" ");
9812 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 }
9814 }
9815 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009816 needSep = true;
9817 }
9818
9819 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009820 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009821 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009822 pw.println(" mHandler:");
9823 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009824 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009826
9827 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009828 }
9829
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009830 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9831 int opti, boolean dumpAll) {
9832 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009834 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835 if (mServices.size() > 0) {
9836 pw.println(" Active services:");
9837 Iterator<ServiceRecord> it = mServices.values().iterator();
9838 while (it.hasNext()) {
9839 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009840 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009841 r.dump(pw, " ");
9842 }
9843 needSep = true;
9844 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009846
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009847 if (mPendingServices.size() > 0) {
9848 if (needSep) pw.println(" ");
9849 pw.println(" Pending services:");
9850 for (int i=0; i<mPendingServices.size(); i++) {
9851 ServiceRecord r = mPendingServices.get(i);
9852 pw.print(" * Pending "); pw.println(r);
9853 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009854 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009855 needSep = true;
9856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009857
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009858 if (mRestartingServices.size() > 0) {
9859 if (needSep) pw.println(" ");
9860 pw.println(" Restarting services:");
9861 for (int i=0; i<mRestartingServices.size(); i++) {
9862 ServiceRecord r = mRestartingServices.get(i);
9863 pw.print(" * Restarting "); pw.println(r);
9864 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009866 needSep = true;
9867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009869 if (mStoppingServices.size() > 0) {
9870 if (needSep) pw.println(" ");
9871 pw.println(" Stopping services:");
9872 for (int i=0; i<mStoppingServices.size(); i++) {
9873 ServiceRecord r = mStoppingServices.get(i);
9874 pw.print(" * Stopping "); pw.println(r);
9875 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009876 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009877 needSep = true;
9878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009879
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009880 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009881 if (mServiceConnections.size() > 0) {
9882 if (needSep) pw.println(" ");
9883 pw.println(" Connection bindings to services:");
9884 Iterator<ConnectionRecord> it
9885 = mServiceConnections.values().iterator();
9886 while (it.hasNext()) {
9887 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009888 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009889 r.dump(pw, " ");
9890 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009891 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 }
9893 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009894
9895 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009896 }
9897
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009898 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9899 int opti, boolean dumpAll) {
9900 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009902 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903 if (mProvidersByClass.size() > 0) {
9904 if (needSep) pw.println(" ");
9905 pw.println(" Published content providers (by class):");
9906 Iterator it = mProvidersByClass.entrySet().iterator();
9907 while (it.hasNext()) {
9908 Map.Entry e = (Map.Entry)it.next();
9909 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009910 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009911 r.dump(pw, " ");
9912 }
9913 needSep = true;
9914 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009915
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009916 if (mProvidersByName.size() > 0) {
9917 pw.println(" ");
9918 pw.println(" Authority to provider mappings:");
9919 Iterator it = mProvidersByName.entrySet().iterator();
9920 while (it.hasNext()) {
9921 Map.Entry e = (Map.Entry)it.next();
9922 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9923 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9924 pw.println(r);
9925 }
9926 needSep = true;
9927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009928 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009929
9930 if (mLaunchingProviders.size() > 0) {
9931 if (needSep) pw.println(" ");
9932 pw.println(" Launching content providers:");
9933 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9934 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9935 pw.println(mLaunchingProviders.get(i));
9936 }
9937 needSep = true;
9938 }
9939
9940 if (mGrantedUriPermissions.size() > 0) {
9941 pw.println();
9942 pw.println("Granted Uri Permissions:");
9943 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9944 int uid = mGrantedUriPermissions.keyAt(i);
9945 HashMap<Uri, UriPermission> perms
9946 = mGrantedUriPermissions.valueAt(i);
9947 pw.print(" * UID "); pw.print(uid);
9948 pw.println(" holds:");
9949 for (UriPermission perm : perms.values()) {
9950 pw.print(" "); pw.println(perm);
9951 perm.dump(pw, " ");
9952 }
9953 }
9954 needSep = true;
9955 }
9956
9957 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009958 }
9959
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009960 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9961 int opti, boolean dumpAll) {
9962 boolean needSep = false;
9963
9964 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965 if (this.mIntentSenderRecords.size() > 0) {
9966 Iterator<WeakReference<PendingIntentRecord>> it
9967 = mIntentSenderRecords.values().iterator();
9968 while (it.hasNext()) {
9969 WeakReference<PendingIntentRecord> ref = it.next();
9970 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009971 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009972 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009973 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009974 rec.dump(pw, " ");
9975 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009976 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009977 }
9978 }
9979 }
9980 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009981
9982 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009983 }
9984
9985 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009986 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009987 TaskRecord lastTask = null;
9988 for (int i=list.size()-1; i>=0; i--) {
9989 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009990 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009991 if (lastTask != r.task) {
9992 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009993 pw.print(prefix);
9994 pw.print(full ? "* " : " ");
9995 pw.println(lastTask);
9996 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009997 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009999 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010000 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10001 pw.print(" #"); pw.print(i); pw.print(": ");
10002 pw.println(r);
10003 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010004 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 }
10007 }
10008
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010009 private static String buildOomTag(String prefix, String space, int val, int base) {
10010 if (val == base) {
10011 if (space == null) return prefix;
10012 return prefix + " ";
10013 }
10014 return prefix + "+" + Integer.toString(val-base);
10015 }
10016
10017 private static final int dumpProcessList(PrintWriter pw,
10018 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010019 String prefix, String normalLabel, String persistentLabel,
10020 boolean inclOomAdj) {
10021 int numPers = 0;
10022 for (int i=list.size()-1; i>=0; i--) {
10023 ProcessRecord r = (ProcessRecord)list.get(i);
10024 if (false) {
10025 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10026 + " #" + i + ":");
10027 r.dump(pw, prefix + " ");
10028 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010029 String oomAdj;
10030 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010031 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010032 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010033 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10034 } else if (r.setAdj >= HOME_APP_ADJ) {
10035 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10036 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10037 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10038 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10039 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10040 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10041 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10042 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10043 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010044 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010045 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010046 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010047 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010048 } else {
10049 oomAdj = Integer.toString(r.setAdj);
10050 }
10051 String schedGroup;
10052 switch (r.setSchedGroup) {
10053 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10054 schedGroup = "B";
10055 break;
10056 case Process.THREAD_GROUP_DEFAULT:
10057 schedGroup = "F";
10058 break;
10059 default:
10060 schedGroup = Integer.toString(r.setSchedGroup);
10061 break;
10062 }
10063 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010065 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010066 if (r.adjSource != null || r.adjTarget != null) {
10067 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010068 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010070 } else {
10071 pw.println(String.format("%s%s #%2d: %s",
10072 prefix, (r.persistent ? persistentLabel : normalLabel),
10073 i, r.toString()));
10074 }
10075 if (r.persistent) {
10076 numPers++;
10077 }
10078 }
10079 return numPers;
10080 }
10081
10082 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
10083 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010084 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010085 long uptime = SystemClock.uptimeMillis();
10086 long realtime = SystemClock.elapsedRealtime();
10087
10088 if (isCheckinRequest) {
10089 // short checkin version
10090 pw.println(uptime + "," + realtime);
10091 pw.flush();
10092 } else {
10093 pw.println("Applications Memory Usage (kB):");
10094 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10095 }
10096 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10097 ProcessRecord r = (ProcessRecord)list.get(i);
10098 if (r.thread != null) {
10099 if (!isCheckinRequest) {
10100 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10101 pw.flush();
10102 }
10103 try {
10104 r.thread.asBinder().dump(fd, args);
10105 } catch (RemoteException e) {
10106 if (!isCheckinRequest) {
10107 pw.println("Got RemoteException!");
10108 pw.flush();
10109 }
10110 }
10111 }
10112 }
10113 }
10114
10115 /**
10116 * Searches array of arguments for the specified string
10117 * @param args array of argument strings
10118 * @param value value to search for
10119 * @return true if the value is contained in the array
10120 */
10121 private static boolean scanArgs(String[] args, String value) {
10122 if (args != null) {
10123 for (String arg : args) {
10124 if (value.equals(arg)) {
10125 return true;
10126 }
10127 }
10128 }
10129 return false;
10130 }
10131
Dianne Hackborn75b03852009-06-12 15:43:26 -070010132 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010133 int count = mHistory.size();
10134
10135 // convert the token to an entry in the history.
10136 HistoryRecord r = null;
10137 int index = -1;
10138 for (int i=count-1; i>=0; i--) {
10139 Object o = mHistory.get(i);
10140 if (o == token) {
10141 r = (HistoryRecord)o;
10142 index = i;
10143 break;
10144 }
10145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010146
10147 return index;
10148 }
10149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010150 private final void killServicesLocked(ProcessRecord app,
10151 boolean allowRestart) {
10152 // Report disconnected services.
10153 if (false) {
10154 // XXX we are letting the client link to the service for
10155 // death notifications.
10156 if (app.services.size() > 0) {
10157 Iterator it = app.services.iterator();
10158 while (it.hasNext()) {
10159 ServiceRecord r = (ServiceRecord)it.next();
10160 if (r.connections.size() > 0) {
10161 Iterator<ConnectionRecord> jt
10162 = r.connections.values().iterator();
10163 while (jt.hasNext()) {
10164 ConnectionRecord c = jt.next();
10165 if (c.binding.client != app) {
10166 try {
10167 //c.conn.connected(r.className, null);
10168 } catch (Exception e) {
10169 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010170 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010171 + r.shortName
10172 + " from app " + app.processName, e);
10173 }
10174 }
10175 }
10176 }
10177 }
10178 }
10179 }
10180
10181 // Clean up any connections this application has to other services.
10182 if (app.connections.size() > 0) {
10183 Iterator<ConnectionRecord> it = app.connections.iterator();
10184 while (it.hasNext()) {
10185 ConnectionRecord r = it.next();
10186 removeConnectionLocked(r, app, null);
10187 }
10188 }
10189 app.connections.clear();
10190
10191 if (app.services.size() != 0) {
10192 // Any services running in the application need to be placed
10193 // back in the pending list.
10194 Iterator it = app.services.iterator();
10195 while (it.hasNext()) {
10196 ServiceRecord sr = (ServiceRecord)it.next();
10197 synchronized (sr.stats.getBatteryStats()) {
10198 sr.stats.stopLaunchedLocked();
10199 }
10200 sr.app = null;
10201 sr.executeNesting = 0;
10202 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010203
10204 boolean hasClients = sr.bindings.size() > 0;
10205 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206 Iterator<IntentBindRecord> bindings
10207 = sr.bindings.values().iterator();
10208 while (bindings.hasNext()) {
10209 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010210 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010211 + ": shouldUnbind=" + b.hasBound);
10212 b.binder = null;
10213 b.requested = b.received = b.hasBound = false;
10214 }
10215 }
10216
10217 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010218 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010219 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010220 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010221 sr.crashCount, sr.shortName, app.pid);
10222 bringDownServiceLocked(sr, true);
10223 } else if (!allowRestart) {
10224 bringDownServiceLocked(sr, true);
10225 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010226 boolean canceled = scheduleServiceRestartLocked(sr, true);
10227
10228 // Should the service remain running? Note that in the
10229 // extreme case of so many attempts to deliver a command
10230 // that it failed, that we also will stop it here.
10231 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10232 if (sr.pendingStarts.size() == 0) {
10233 sr.startRequested = false;
10234 if (!hasClients) {
10235 // Whoops, no reason to restart!
10236 bringDownServiceLocked(sr, true);
10237 }
10238 }
10239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010240 }
10241 }
10242
10243 if (!allowRestart) {
10244 app.services.clear();
10245 }
10246 }
10247
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010248 // Make sure we have no more records on the stopping list.
10249 int i = mStoppingServices.size();
10250 while (i > 0) {
10251 i--;
10252 ServiceRecord sr = mStoppingServices.get(i);
10253 if (sr.app == app) {
10254 mStoppingServices.remove(i);
10255 }
10256 }
10257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010258 app.executingServices.clear();
10259 }
10260
10261 private final void removeDyingProviderLocked(ProcessRecord proc,
10262 ContentProviderRecord cpr) {
10263 synchronized (cpr) {
10264 cpr.launchingApp = null;
10265 cpr.notifyAll();
10266 }
10267
10268 mProvidersByClass.remove(cpr.info.name);
10269 String names[] = cpr.info.authority.split(";");
10270 for (int j = 0; j < names.length; j++) {
10271 mProvidersByName.remove(names[j]);
10272 }
10273
10274 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10275 while (cit.hasNext()) {
10276 ProcessRecord capp = cit.next();
10277 if (!capp.persistent && capp.thread != null
10278 && capp.pid != 0
10279 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010280 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010281 + " (pid " + capp.pid
10282 + ") because provider " + cpr.info.name
10283 + " is in dying process " + proc.processName);
10284 Process.killProcess(capp.pid);
10285 }
10286 }
10287
10288 mLaunchingProviders.remove(cpr);
10289 }
10290
10291 /**
10292 * Main code for cleaning up a process when it has gone away. This is
10293 * called both as a result of the process dying, or directly when stopping
10294 * a process when running in single process mode.
10295 */
10296 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10297 boolean restarting, int index) {
10298 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010299 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010300 }
10301
Dianne Hackborn36124872009-10-08 16:22:03 -070010302 mProcessesToGc.remove(app);
10303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010304 // Dismiss any open dialogs.
10305 if (app.crashDialog != null) {
10306 app.crashDialog.dismiss();
10307 app.crashDialog = null;
10308 }
10309 if (app.anrDialog != null) {
10310 app.anrDialog.dismiss();
10311 app.anrDialog = null;
10312 }
10313 if (app.waitDialog != null) {
10314 app.waitDialog.dismiss();
10315 app.waitDialog = null;
10316 }
10317
10318 app.crashing = false;
10319 app.notResponding = false;
10320
10321 app.resetPackageList();
10322 app.thread = null;
10323 app.forcingToForeground = null;
10324 app.foregroundServices = false;
10325
10326 killServicesLocked(app, true);
10327
10328 boolean restart = false;
10329
10330 int NL = mLaunchingProviders.size();
10331
10332 // Remove published content providers.
10333 if (!app.pubProviders.isEmpty()) {
10334 Iterator it = app.pubProviders.values().iterator();
10335 while (it.hasNext()) {
10336 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10337 cpr.provider = null;
10338 cpr.app = null;
10339
10340 // See if someone is waiting for this provider... in which
10341 // case we don't remove it, but just let it restart.
10342 int i = 0;
10343 if (!app.bad) {
10344 for (; i<NL; i++) {
10345 if (mLaunchingProviders.get(i) == cpr) {
10346 restart = true;
10347 break;
10348 }
10349 }
10350 } else {
10351 i = NL;
10352 }
10353
10354 if (i >= NL) {
10355 removeDyingProviderLocked(app, cpr);
10356 NL = mLaunchingProviders.size();
10357 }
10358 }
10359 app.pubProviders.clear();
10360 }
10361
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010362 // Take care of any launching providers waiting for this process.
10363 if (checkAppInLaunchingProvidersLocked(app, false)) {
10364 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010365 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 // Unregister from connected content providers.
10368 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010369 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370 while (it.hasNext()) {
10371 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10372 cpr.clients.remove(app);
10373 }
10374 app.conProviders.clear();
10375 }
10376
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010377 // At this point there may be remaining entries in mLaunchingProviders
10378 // where we were the only one waiting, so they are no longer of use.
10379 // Look for these and clean up if found.
10380 // XXX Commented out for now. Trying to figure out a way to reproduce
10381 // the actual situation to identify what is actually going on.
10382 if (false) {
10383 for (int i=0; i<NL; i++) {
10384 ContentProviderRecord cpr = (ContentProviderRecord)
10385 mLaunchingProviders.get(i);
10386 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10387 synchronized (cpr) {
10388 cpr.launchingApp = null;
10389 cpr.notifyAll();
10390 }
10391 }
10392 }
10393 }
10394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010395 skipCurrentReceiverLocked(app);
10396
10397 // Unregister any receivers.
10398 if (app.receivers.size() > 0) {
10399 Iterator<ReceiverList> it = app.receivers.iterator();
10400 while (it.hasNext()) {
10401 removeReceiverLocked(it.next());
10402 }
10403 app.receivers.clear();
10404 }
10405
Christopher Tate181fafa2009-05-14 11:12:14 -070010406 // If the app is undergoing backup, tell the backup manager about it
10407 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010408 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010409 try {
10410 IBackupManager bm = IBackupManager.Stub.asInterface(
10411 ServiceManager.getService(Context.BACKUP_SERVICE));
10412 bm.agentDisconnected(app.info.packageName);
10413 } catch (RemoteException e) {
10414 // can't happen; backup manager is local
10415 }
10416 }
10417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010418 // If the caller is restarting this app, then leave it in its
10419 // current lists and let the caller take care of it.
10420 if (restarting) {
10421 return;
10422 }
10423
10424 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010425 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010426 "Removing non-persistent process during cleanup: " + app);
10427 mProcessNames.remove(app.processName, app.info.uid);
10428 } else if (!app.removed) {
10429 // This app is persistent, so we need to keep its record around.
10430 // If it is not already on the pending app list, add it there
10431 // and start a new process for it.
10432 app.thread = null;
10433 app.forcingToForeground = null;
10434 app.foregroundServices = false;
10435 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10436 mPersistentStartingProcesses.add(app);
10437 restart = true;
10438 }
10439 }
10440 mProcessesOnHold.remove(app);
10441
The Android Open Source Project4df24232009-03-05 14:34:35 -080010442 if (app == mHomeProcess) {
10443 mHomeProcess = null;
10444 }
10445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 if (restart) {
10447 // We have components that still need to be running in the
10448 // process, so re-launch it.
10449 mProcessNames.put(app.processName, app.info.uid, app);
10450 startProcessLocked(app, "restart", app.processName);
10451 } else if (app.pid > 0 && app.pid != MY_PID) {
10452 // Goodbye!
10453 synchronized (mPidsSelfLocked) {
10454 mPidsSelfLocked.remove(app.pid);
10455 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10456 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010457 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010458 }
10459 }
10460
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010461 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10462 // Look through the content providers we are waiting to have launched,
10463 // and if any run in this process then either schedule a restart of
10464 // the process or kill the client waiting for it if this process has
10465 // gone bad.
10466 int NL = mLaunchingProviders.size();
10467 boolean restart = false;
10468 for (int i=0; i<NL; i++) {
10469 ContentProviderRecord cpr = (ContentProviderRecord)
10470 mLaunchingProviders.get(i);
10471 if (cpr.launchingApp == app) {
10472 if (!alwaysBad && !app.bad) {
10473 restart = true;
10474 } else {
10475 removeDyingProviderLocked(app, cpr);
10476 NL = mLaunchingProviders.size();
10477 }
10478 }
10479 }
10480 return restart;
10481 }
10482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010483 // =========================================================
10484 // SERVICES
10485 // =========================================================
10486
10487 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10488 ActivityManager.RunningServiceInfo info =
10489 new ActivityManager.RunningServiceInfo();
10490 info.service = r.name;
10491 if (r.app != null) {
10492 info.pid = r.app.pid;
10493 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010494 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010495 info.process = r.processName;
10496 info.foreground = r.isForeground;
10497 info.activeSince = r.createTime;
10498 info.started = r.startRequested;
10499 info.clientCount = r.connections.size();
10500 info.crashCount = r.crashCount;
10501 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010502 if (r.isForeground) {
10503 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10504 }
10505 if (r.startRequested) {
10506 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10507 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010508 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010509 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10510 }
10511 if (r.app != null && r.app.persistent) {
10512 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10513 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010514 for (ConnectionRecord conn : r.connections.values()) {
10515 if (conn.clientLabel != 0) {
10516 info.clientPackage = conn.binding.client.info.packageName;
10517 info.clientLabel = conn.clientLabel;
10518 break;
10519 }
10520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010521 return info;
10522 }
10523
10524 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10525 int flags) {
10526 synchronized (this) {
10527 ArrayList<ActivityManager.RunningServiceInfo> res
10528 = new ArrayList<ActivityManager.RunningServiceInfo>();
10529
10530 if (mServices.size() > 0) {
10531 Iterator<ServiceRecord> it = mServices.values().iterator();
10532 while (it.hasNext() && res.size() < maxNum) {
10533 res.add(makeRunningServiceInfoLocked(it.next()));
10534 }
10535 }
10536
10537 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10538 ServiceRecord r = mRestartingServices.get(i);
10539 ActivityManager.RunningServiceInfo info =
10540 makeRunningServiceInfoLocked(r);
10541 info.restarting = r.nextRestartTime;
10542 res.add(info);
10543 }
10544
10545 return res;
10546 }
10547 }
10548
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010549 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10550 synchronized (this) {
10551 ServiceRecord r = mServices.get(name);
10552 if (r != null) {
10553 for (ConnectionRecord conn : r.connections.values()) {
10554 if (conn.clientIntent != null) {
10555 return conn.clientIntent;
10556 }
10557 }
10558 }
10559 }
10560 return null;
10561 }
10562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010563 private final ServiceRecord findServiceLocked(ComponentName name,
10564 IBinder token) {
10565 ServiceRecord r = mServices.get(name);
10566 return r == token ? r : null;
10567 }
10568
10569 private final class ServiceLookupResult {
10570 final ServiceRecord record;
10571 final String permission;
10572
10573 ServiceLookupResult(ServiceRecord _record, String _permission) {
10574 record = _record;
10575 permission = _permission;
10576 }
10577 };
10578
10579 private ServiceLookupResult findServiceLocked(Intent service,
10580 String resolvedType) {
10581 ServiceRecord r = null;
10582 if (service.getComponent() != null) {
10583 r = mServices.get(service.getComponent());
10584 }
10585 if (r == null) {
10586 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10587 r = mServicesByIntent.get(filter);
10588 }
10589
10590 if (r == null) {
10591 try {
10592 ResolveInfo rInfo =
10593 ActivityThread.getPackageManager().resolveService(
10594 service, resolvedType, 0);
10595 ServiceInfo sInfo =
10596 rInfo != null ? rInfo.serviceInfo : null;
10597 if (sInfo == null) {
10598 return null;
10599 }
10600
10601 ComponentName name = new ComponentName(
10602 sInfo.applicationInfo.packageName, sInfo.name);
10603 r = mServices.get(name);
10604 } catch (RemoteException ex) {
10605 // pm is in same process, this will never happen.
10606 }
10607 }
10608 if (r != null) {
10609 int callingPid = Binder.getCallingPid();
10610 int callingUid = Binder.getCallingUid();
10611 if (checkComponentPermission(r.permission,
10612 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10613 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010614 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 + " from pid=" + callingPid
10616 + ", uid=" + callingUid
10617 + " requires " + r.permission);
10618 return new ServiceLookupResult(null, r.permission);
10619 }
10620 return new ServiceLookupResult(r, null);
10621 }
10622 return null;
10623 }
10624
10625 private class ServiceRestarter implements Runnable {
10626 private ServiceRecord mService;
10627
10628 void setService(ServiceRecord service) {
10629 mService = service;
10630 }
10631
10632 public void run() {
10633 synchronized(ActivityManagerService.this) {
10634 performServiceRestartLocked(mService);
10635 }
10636 }
10637 }
10638
10639 private ServiceLookupResult retrieveServiceLocked(Intent service,
10640 String resolvedType, int callingPid, int callingUid) {
10641 ServiceRecord r = null;
10642 if (service.getComponent() != null) {
10643 r = mServices.get(service.getComponent());
10644 }
10645 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10646 r = mServicesByIntent.get(filter);
10647 if (r == null) {
10648 try {
10649 ResolveInfo rInfo =
10650 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010651 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 ServiceInfo sInfo =
10653 rInfo != null ? rInfo.serviceInfo : null;
10654 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010655 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010656 ": not found");
10657 return null;
10658 }
10659
10660 ComponentName name = new ComponentName(
10661 sInfo.applicationInfo.packageName, sInfo.name);
10662 r = mServices.get(name);
10663 if (r == null) {
10664 filter = new Intent.FilterComparison(service.cloneFilter());
10665 ServiceRestarter res = new ServiceRestarter();
10666 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10667 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10668 synchronized (stats) {
10669 ss = stats.getServiceStatsLocked(
10670 sInfo.applicationInfo.uid, sInfo.packageName,
10671 sInfo.name);
10672 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010673 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010674 res.setService(r);
10675 mServices.put(name, r);
10676 mServicesByIntent.put(filter, r);
10677
10678 // Make sure this component isn't in the pending list.
10679 int N = mPendingServices.size();
10680 for (int i=0; i<N; i++) {
10681 ServiceRecord pr = mPendingServices.get(i);
10682 if (pr.name.equals(name)) {
10683 mPendingServices.remove(i);
10684 i--;
10685 N--;
10686 }
10687 }
10688 }
10689 } catch (RemoteException ex) {
10690 // pm is in same process, this will never happen.
10691 }
10692 }
10693 if (r != null) {
10694 if (checkComponentPermission(r.permission,
10695 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10696 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010697 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010698 + " from pid=" + Binder.getCallingPid()
10699 + ", uid=" + Binder.getCallingUid()
10700 + " requires " + r.permission);
10701 return new ServiceLookupResult(null, r.permission);
10702 }
10703 return new ServiceLookupResult(r, null);
10704 }
10705 return null;
10706 }
10707
10708 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10709 long now = SystemClock.uptimeMillis();
10710 if (r.executeNesting == 0 && r.app != null) {
10711 if (r.app.executingServices.size() == 0) {
10712 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10713 msg.obj = r.app;
10714 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10715 }
10716 r.app.executingServices.add(r);
10717 }
10718 r.executeNesting++;
10719 r.executingStart = now;
10720 }
10721
10722 private final void sendServiceArgsLocked(ServiceRecord r,
10723 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010724 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725 if (N == 0) {
10726 return;
10727 }
10728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010729 int i = 0;
10730 while (i < N) {
10731 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010732 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010733 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010734 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010735 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010736 // If somehow we got a dummy start at the front, then
10737 // just drop it here.
10738 i++;
10739 continue;
10740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010741 bumpServiceExecutingLocked(r);
10742 if (!oomAdjusted) {
10743 oomAdjusted = true;
10744 updateOomAdjLocked(r.app);
10745 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010746 int flags = 0;
10747 if (si.deliveryCount > 0) {
10748 flags |= Service.START_FLAG_RETRY;
10749 }
10750 if (si.doneExecutingCount > 0) {
10751 flags |= Service.START_FLAG_REDELIVERY;
10752 }
10753 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10754 si.deliveredTime = SystemClock.uptimeMillis();
10755 r.deliveredStarts.add(si);
10756 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010758 } catch (RemoteException e) {
10759 // Remote process gone... we'll let the normal cleanup take
10760 // care of this.
10761 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010762 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010763 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764 break;
10765 }
10766 }
10767 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010768 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 } else {
10770 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010771 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010772 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010773 }
10774 }
10775 }
10776
10777 private final boolean requestServiceBindingLocked(ServiceRecord r,
10778 IntentBindRecord i, boolean rebind) {
10779 if (r.app == null || r.app.thread == null) {
10780 // If service is not currently running, can't yet bind.
10781 return false;
10782 }
10783 if ((!i.requested || rebind) && i.apps.size() > 0) {
10784 try {
10785 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010786 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787 + ": shouldUnbind=" + i.hasBound);
10788 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10789 if (!rebind) {
10790 i.requested = true;
10791 }
10792 i.hasBound = true;
10793 i.doRebind = false;
10794 } catch (RemoteException e) {
10795 return false;
10796 }
10797 }
10798 return true;
10799 }
10800
10801 private final void requestServiceBindingsLocked(ServiceRecord r) {
10802 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10803 while (bindings.hasNext()) {
10804 IntentBindRecord i = bindings.next();
10805 if (!requestServiceBindingLocked(r, i, false)) {
10806 break;
10807 }
10808 }
10809 }
10810
10811 private final void realStartServiceLocked(ServiceRecord r,
10812 ProcessRecord app) throws RemoteException {
10813 if (app.thread == null) {
10814 throw new RemoteException();
10815 }
10816
10817 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010818 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010819
10820 app.services.add(r);
10821 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010822 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010823
10824 boolean created = false;
10825 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010826 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010828 mStringBuilder.setLength(0);
10829 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010830 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010831 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010832 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833 synchronized (r.stats.getBatteryStats()) {
10834 r.stats.startLaunchedLocked();
10835 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010836 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010837 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010838 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 created = true;
10840 } finally {
10841 if (!created) {
10842 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010843 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010844 }
10845 }
10846
10847 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010848
10849 // If the service is in the started state, and there are no
10850 // pending arguments, then fake up one so its onStartCommand() will
10851 // be called.
10852 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10853 r.lastStartId++;
10854 if (r.lastStartId < 1) {
10855 r.lastStartId = 1;
10856 }
10857 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10858 }
10859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010860 sendServiceArgsLocked(r, true);
10861 }
10862
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010863 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10864 boolean allowCancel) {
10865 boolean canceled = false;
10866
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010867 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010868 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010869 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010870
10871 // Any delivered but not yet finished starts should be put back
10872 // on the pending list.
10873 final int N = r.deliveredStarts.size();
10874 if (N > 0) {
10875 for (int i=N-1; i>=0; i--) {
10876 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10877 if (si.intent == null) {
10878 // We'll generate this again if needed.
10879 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10880 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10881 r.pendingStarts.add(0, si);
10882 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10883 dur *= 2;
10884 if (minDuration < dur) minDuration = dur;
10885 if (resetTime < dur) resetTime = dur;
10886 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010887 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010888 + r.name);
10889 canceled = true;
10890 }
10891 }
10892 r.deliveredStarts.clear();
10893 }
10894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010895 r.totalRestartCount++;
10896 if (r.restartDelay == 0) {
10897 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010898 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010899 } else {
10900 // If it has been a "reasonably long time" since the service
10901 // was started, then reset our restart duration back to
10902 // the beginning, so we don't infinitely increase the duration
10903 // on a service that just occasionally gets killed (which is
10904 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010905 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010907 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010909 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010910 if (r.restartDelay < minDuration) {
10911 r.restartDelay = minDuration;
10912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913 }
10914 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010915
10916 r.nextRestartTime = now + r.restartDelay;
10917
10918 // Make sure that we don't end up restarting a bunch of services
10919 // all at the same time.
10920 boolean repeat;
10921 do {
10922 repeat = false;
10923 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10924 ServiceRecord r2 = mRestartingServices.get(i);
10925 if (r2 != r && r.nextRestartTime
10926 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10927 && r.nextRestartTime
10928 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10929 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10930 r.restartDelay = r.nextRestartTime - now;
10931 repeat = true;
10932 break;
10933 }
10934 }
10935 } while (repeat);
10936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010937 if (!mRestartingServices.contains(r)) {
10938 mRestartingServices.add(r);
10939 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010940
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010941 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010943 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010944 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010945 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010946 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010947 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010948 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010949 r.shortName, r.restartDelay);
10950
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010951 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010952 }
10953
10954 final void performServiceRestartLocked(ServiceRecord r) {
10955 if (!mRestartingServices.contains(r)) {
10956 return;
10957 }
10958 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10959 }
10960
10961 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10962 if (r.restartDelay == 0) {
10963 return false;
10964 }
10965 r.resetRestartCounter();
10966 mRestartingServices.remove(r);
10967 mHandler.removeCallbacks(r.restarter);
10968 return true;
10969 }
10970
10971 private final boolean bringUpServiceLocked(ServiceRecord r,
10972 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010973 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010974 //r.dump(" ");
10975
Dianne Hackborn36124872009-10-08 16:22:03 -070010976 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010977 sendServiceArgsLocked(r, false);
10978 return true;
10979 }
10980
10981 if (!whileRestarting && r.restartDelay > 0) {
10982 // If waiting for a restart, then do nothing.
10983 return true;
10984 }
10985
Joe Onorato8a9b2202010-02-26 18:56:32 -080010986 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987 + " " + r.intent);
10988
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010989 // We are now bringing the service up, so no longer in the
10990 // restarting state.
10991 mRestartingServices.remove(r);
10992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010993 final String appName = r.processName;
10994 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10995 if (app != null && app.thread != null) {
10996 try {
10997 realStartServiceLocked(r, app);
10998 return true;
10999 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011000 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 }
11002
11003 // If a dead object exception was thrown -- fall through to
11004 // restart the application.
11005 }
11006
Dianne Hackborn36124872009-10-08 16:22:03 -070011007 // Not running -- get it started, and enqueue this service record
11008 // to be executed when the app comes up.
11009 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11010 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011011 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011012 + r.appInfo.packageName + "/"
11013 + r.appInfo.uid + " for service "
11014 + r.intent.getIntent() + ": process is bad");
11015 bringDownServiceLocked(r, true);
11016 return false;
11017 }
11018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011019 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011020 mPendingServices.add(r);
11021 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 return true;
11024 }
11025
11026 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011027 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011028 //r.dump(" ");
11029
11030 // Does it still need to run?
11031 if (!force && r.startRequested) {
11032 return;
11033 }
11034 if (r.connections.size() > 0) {
11035 if (!force) {
11036 // XXX should probably keep a count of the number of auto-create
11037 // connections directly in the service.
11038 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11039 while (it.hasNext()) {
11040 ConnectionRecord cr = it.next();
11041 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11042 return;
11043 }
11044 }
11045 }
11046
11047 // Report to all of the connections that the service is no longer
11048 // available.
11049 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11050 while (it.hasNext()) {
11051 ConnectionRecord c = it.next();
11052 try {
11053 // todo: shouldn't be a synchronous call!
11054 c.conn.connected(r.name, null);
11055 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011056 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 " to connection " + c.conn.asBinder() +
11058 " (in " + c.binding.client.processName + ")", e);
11059 }
11060 }
11061 }
11062
11063 // Tell the service that it has been unbound.
11064 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11065 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11066 while (it.hasNext()) {
11067 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011068 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011069 + ": hasBound=" + ibr.hasBound);
11070 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11071 try {
11072 bumpServiceExecutingLocked(r);
11073 updateOomAdjLocked(r.app);
11074 ibr.hasBound = false;
11075 r.app.thread.scheduleUnbindService(r,
11076 ibr.intent.getIntent());
11077 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011078 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 + r.shortName, e);
11080 serviceDoneExecutingLocked(r, true);
11081 }
11082 }
11083 }
11084 }
11085
Joe Onorato8a9b2202010-02-26 18:56:32 -080011086 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011088 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089 System.identityHashCode(r), r.shortName,
11090 (r.app != null) ? r.app.pid : -1);
11091
11092 mServices.remove(r.name);
11093 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011094 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011095 r.totalRestartCount = 0;
11096 unscheduleServiceRestartLocked(r);
11097
11098 // Also make sure it is not on the pending list.
11099 int N = mPendingServices.size();
11100 for (int i=0; i<N; i++) {
11101 if (mPendingServices.get(i) == r) {
11102 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011103 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 TAG, "Removed pending service: " + r.shortName);
11105 i--;
11106 N--;
11107 }
11108 }
11109
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011110 r.cancelNotification();
11111 r.isForeground = false;
11112 r.foregroundId = 0;
11113 r.foregroundNoti = null;
11114
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011115 // Clear start entries.
11116 r.deliveredStarts.clear();
11117 r.pendingStarts.clear();
11118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011119 if (r.app != null) {
11120 synchronized (r.stats.getBatteryStats()) {
11121 r.stats.stopLaunchedLocked();
11122 }
11123 r.app.services.remove(r);
11124 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011125 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011126 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011127 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011128 bumpServiceExecutingLocked(r);
11129 mStoppingServices.add(r);
11130 updateOomAdjLocked(r.app);
11131 r.app.thread.scheduleStopService(r);
11132 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011133 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011134 + r.shortName, e);
11135 serviceDoneExecutingLocked(r, true);
11136 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011137 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011138 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011139 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 TAG, "Removed service that has no process: " + r.shortName);
11141 }
11142 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011143 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011144 TAG, "Removed service that is not running: " + r.shortName);
11145 }
11146 }
11147
11148 ComponentName startServiceLocked(IApplicationThread caller,
11149 Intent service, String resolvedType,
11150 int callingPid, int callingUid) {
11151 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011152 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011153 + " type=" + resolvedType + " args=" + service.getExtras());
11154
11155 if (caller != null) {
11156 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11157 if (callerApp == null) {
11158 throw new SecurityException(
11159 "Unable to find app for caller " + caller
11160 + " (pid=" + Binder.getCallingPid()
11161 + ") when starting service " + service);
11162 }
11163 }
11164
11165 ServiceLookupResult res =
11166 retrieveServiceLocked(service, resolvedType,
11167 callingPid, callingUid);
11168 if (res == null) {
11169 return null;
11170 }
11171 if (res.record == null) {
11172 return new ComponentName("!", res.permission != null
11173 ? res.permission : "private to package");
11174 }
11175 ServiceRecord r = res.record;
11176 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011177 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011178 + r.shortName);
11179 }
11180 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011181 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011182 r.lastStartId++;
11183 if (r.lastStartId < 1) {
11184 r.lastStartId = 1;
11185 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011186 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011187 r.lastActivity = SystemClock.uptimeMillis();
11188 synchronized (r.stats.getBatteryStats()) {
11189 r.stats.startRunningLocked();
11190 }
11191 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11192 return new ComponentName("!", "Service process is bad");
11193 }
11194 return r.name;
11195 }
11196 }
11197
11198 public ComponentName startService(IApplicationThread caller, Intent service,
11199 String resolvedType) {
11200 // Refuse possible leaked file descriptors
11201 if (service != null && service.hasFileDescriptors() == true) {
11202 throw new IllegalArgumentException("File descriptors passed in Intent");
11203 }
11204
11205 synchronized(this) {
11206 final int callingPid = Binder.getCallingPid();
11207 final int callingUid = Binder.getCallingUid();
11208 final long origId = Binder.clearCallingIdentity();
11209 ComponentName res = startServiceLocked(caller, service,
11210 resolvedType, callingPid, callingUid);
11211 Binder.restoreCallingIdentity(origId);
11212 return res;
11213 }
11214 }
11215
11216 ComponentName startServiceInPackage(int uid,
11217 Intent service, String resolvedType) {
11218 synchronized(this) {
11219 final long origId = Binder.clearCallingIdentity();
11220 ComponentName res = startServiceLocked(null, service,
11221 resolvedType, -1, uid);
11222 Binder.restoreCallingIdentity(origId);
11223 return res;
11224 }
11225 }
11226
11227 public int stopService(IApplicationThread caller, Intent service,
11228 String resolvedType) {
11229 // Refuse possible leaked file descriptors
11230 if (service != null && service.hasFileDescriptors() == true) {
11231 throw new IllegalArgumentException("File descriptors passed in Intent");
11232 }
11233
11234 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011235 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011236 + " type=" + resolvedType);
11237
11238 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11239 if (caller != null && callerApp == null) {
11240 throw new SecurityException(
11241 "Unable to find app for caller " + caller
11242 + " (pid=" + Binder.getCallingPid()
11243 + ") when stopping service " + service);
11244 }
11245
11246 // If this service is active, make sure it is stopped.
11247 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11248 if (r != null) {
11249 if (r.record != null) {
11250 synchronized (r.record.stats.getBatteryStats()) {
11251 r.record.stats.stopRunningLocked();
11252 }
11253 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011254 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011255 final long origId = Binder.clearCallingIdentity();
11256 bringDownServiceLocked(r.record, false);
11257 Binder.restoreCallingIdentity(origId);
11258 return 1;
11259 }
11260 return -1;
11261 }
11262 }
11263
11264 return 0;
11265 }
11266
11267 public IBinder peekService(Intent service, String resolvedType) {
11268 // Refuse possible leaked file descriptors
11269 if (service != null && service.hasFileDescriptors() == true) {
11270 throw new IllegalArgumentException("File descriptors passed in Intent");
11271 }
11272
11273 IBinder ret = null;
11274
11275 synchronized(this) {
11276 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11277
11278 if (r != null) {
11279 // r.record is null if findServiceLocked() failed the caller permission check
11280 if (r.record == null) {
11281 throw new SecurityException(
11282 "Permission Denial: Accessing service " + r.record.name
11283 + " from pid=" + Binder.getCallingPid()
11284 + ", uid=" + Binder.getCallingUid()
11285 + " requires " + r.permission);
11286 }
11287 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11288 if (ib != null) {
11289 ret = ib.binder;
11290 }
11291 }
11292 }
11293
11294 return ret;
11295 }
11296
11297 public boolean stopServiceToken(ComponentName className, IBinder token,
11298 int startId) {
11299 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011300 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011301 + " " + token + " startId=" + startId);
11302 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011303 if (r != null) {
11304 if (startId >= 0) {
11305 // Asked to only stop if done with all work. Note that
11306 // to avoid leaks, we will take this as dropping all
11307 // start items up to and including this one.
11308 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11309 if (si != null) {
11310 while (r.deliveredStarts.size() > 0) {
11311 if (r.deliveredStarts.remove(0) == si) {
11312 break;
11313 }
11314 }
11315 }
11316
11317 if (r.lastStartId != startId) {
11318 return false;
11319 }
11320
11321 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011322 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011323 + " is last, but have " + r.deliveredStarts.size()
11324 + " remaining args");
11325 }
11326 }
11327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011328 synchronized (r.stats.getBatteryStats()) {
11329 r.stats.stopRunningLocked();
11330 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011331 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011332 }
11333 final long origId = Binder.clearCallingIdentity();
11334 bringDownServiceLocked(r, false);
11335 Binder.restoreCallingIdentity(origId);
11336 return true;
11337 }
11338 }
11339 return false;
11340 }
11341
11342 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011343 int id, Notification notification, boolean removeNotification) {
11344 final long origId = Binder.clearCallingIdentity();
11345 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011346 synchronized(this) {
11347 ServiceRecord r = findServiceLocked(className, token);
11348 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011349 if (id != 0) {
11350 if (notification == null) {
11351 throw new IllegalArgumentException("null notification");
11352 }
11353 if (r.foregroundId != id) {
11354 r.cancelNotification();
11355 r.foregroundId = id;
11356 }
11357 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11358 r.foregroundNoti = notification;
11359 r.isForeground = true;
11360 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011361 if (r.app != null) {
11362 updateServiceForegroundLocked(r.app, true);
11363 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011364 } else {
11365 if (r.isForeground) {
11366 r.isForeground = false;
11367 if (r.app != null) {
11368 updateServiceForegroundLocked(r.app, true);
11369 }
11370 }
11371 if (removeNotification) {
11372 r.cancelNotification();
11373 r.foregroundId = 0;
11374 r.foregroundNoti = null;
11375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011376 }
11377 }
11378 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011379 } finally {
11380 Binder.restoreCallingIdentity(origId);
11381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011382 }
11383
11384 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11385 boolean anyForeground = false;
11386 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11387 if (sr.isForeground) {
11388 anyForeground = true;
11389 break;
11390 }
11391 }
11392 if (anyForeground != proc.foregroundServices) {
11393 proc.foregroundServices = anyForeground;
11394 if (oomAdj) {
11395 updateOomAdjLocked();
11396 }
11397 }
11398 }
11399
11400 public int bindService(IApplicationThread caller, IBinder token,
11401 Intent service, String resolvedType,
11402 IServiceConnection connection, int flags) {
11403 // Refuse possible leaked file descriptors
11404 if (service != null && service.hasFileDescriptors() == true) {
11405 throw new IllegalArgumentException("File descriptors passed in Intent");
11406 }
11407
11408 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011409 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011410 + " type=" + resolvedType + " conn=" + connection.asBinder()
11411 + " flags=0x" + Integer.toHexString(flags));
11412 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11413 if (callerApp == null) {
11414 throw new SecurityException(
11415 "Unable to find app for caller " + caller
11416 + " (pid=" + Binder.getCallingPid()
11417 + ") when binding service " + service);
11418 }
11419
11420 HistoryRecord activity = null;
11421 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011422 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011423 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011424 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011425 return 0;
11426 }
11427 activity = (HistoryRecord)mHistory.get(aindex);
11428 }
11429
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011430 int clientLabel = 0;
11431 PendingIntent clientIntent = null;
11432
11433 if (callerApp.info.uid == Process.SYSTEM_UID) {
11434 // Hacky kind of thing -- allow system stuff to tell us
11435 // what they are, so we can report this elsewhere for
11436 // others to know why certain services are running.
11437 try {
11438 clientIntent = (PendingIntent)service.getParcelableExtra(
11439 Intent.EXTRA_CLIENT_INTENT);
11440 } catch (RuntimeException e) {
11441 }
11442 if (clientIntent != null) {
11443 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11444 if (clientLabel != 0) {
11445 // There are no useful extras in the intent, trash them.
11446 // System code calling with this stuff just needs to know
11447 // this will happen.
11448 service = service.cloneFilter();
11449 }
11450 }
11451 }
11452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011453 ServiceLookupResult res =
11454 retrieveServiceLocked(service, resolvedType,
11455 Binder.getCallingPid(), Binder.getCallingUid());
11456 if (res == null) {
11457 return 0;
11458 }
11459 if (res.record == null) {
11460 return -1;
11461 }
11462 ServiceRecord s = res.record;
11463
11464 final long origId = Binder.clearCallingIdentity();
11465
11466 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011467 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011468 + s.shortName);
11469 }
11470
11471 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11472 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011473 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474
11475 IBinder binder = connection.asBinder();
11476 s.connections.put(binder, c);
11477 b.connections.add(c);
11478 if (activity != null) {
11479 if (activity.connections == null) {
11480 activity.connections = new HashSet<ConnectionRecord>();
11481 }
11482 activity.connections.add(c);
11483 }
11484 b.client.connections.add(c);
11485 mServiceConnections.put(binder, c);
11486
11487 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11488 s.lastActivity = SystemClock.uptimeMillis();
11489 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11490 return 0;
11491 }
11492 }
11493
11494 if (s.app != null) {
11495 // This could have made the service more important.
11496 updateOomAdjLocked(s.app);
11497 }
11498
Joe Onorato8a9b2202010-02-26 18:56:32 -080011499 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 + ": received=" + b.intent.received
11501 + " apps=" + b.intent.apps.size()
11502 + " doRebind=" + b.intent.doRebind);
11503
11504 if (s.app != null && b.intent.received) {
11505 // Service is already running, so we can immediately
11506 // publish the connection.
11507 try {
11508 c.conn.connected(s.name, b.intent.binder);
11509 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011510 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 + " to connection " + c.conn.asBinder()
11512 + " (in " + c.binding.client.processName + ")", e);
11513 }
11514
11515 // If this is the first app connected back to this binding,
11516 // and the service had previously asked to be told when
11517 // rebound, then do so.
11518 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11519 requestServiceBindingLocked(s, b.intent, true);
11520 }
11521 } else if (!b.intent.requested) {
11522 requestServiceBindingLocked(s, b.intent, false);
11523 }
11524
11525 Binder.restoreCallingIdentity(origId);
11526 }
11527
11528 return 1;
11529 }
11530
11531 private void removeConnectionLocked(
11532 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11533 IBinder binder = c.conn.asBinder();
11534 AppBindRecord b = c.binding;
11535 ServiceRecord s = b.service;
11536 s.connections.remove(binder);
11537 b.connections.remove(c);
11538 if (c.activity != null && c.activity != skipAct) {
11539 if (c.activity.connections != null) {
11540 c.activity.connections.remove(c);
11541 }
11542 }
11543 if (b.client != skipApp) {
11544 b.client.connections.remove(c);
11545 }
11546 mServiceConnections.remove(binder);
11547
11548 if (b.connections.size() == 0) {
11549 b.intent.apps.remove(b.client);
11550 }
11551
Joe Onorato8a9b2202010-02-26 18:56:32 -080011552 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011553 + ": shouldUnbind=" + b.intent.hasBound);
11554 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11555 && b.intent.hasBound) {
11556 try {
11557 bumpServiceExecutingLocked(s);
11558 updateOomAdjLocked(s.app);
11559 b.intent.hasBound = false;
11560 // Assume the client doesn't want to know about a rebind;
11561 // we will deal with that later if it asks for one.
11562 b.intent.doRebind = false;
11563 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11564 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011565 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566 serviceDoneExecutingLocked(s, true);
11567 }
11568 }
11569
11570 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11571 bringDownServiceLocked(s, false);
11572 }
11573 }
11574
11575 public boolean unbindService(IServiceConnection connection) {
11576 synchronized (this) {
11577 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011578 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011579 ConnectionRecord r = mServiceConnections.get(binder);
11580 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011581 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011582 + connection.asBinder());
11583 return false;
11584 }
11585
11586 final long origId = Binder.clearCallingIdentity();
11587
11588 removeConnectionLocked(r, null, null);
11589
11590 if (r.binding.service.app != null) {
11591 // This could have made the service less important.
11592 updateOomAdjLocked(r.binding.service.app);
11593 }
11594
11595 Binder.restoreCallingIdentity(origId);
11596 }
11597
11598 return true;
11599 }
11600
11601 public void publishService(IBinder token, Intent intent, IBinder service) {
11602 // Refuse possible leaked file descriptors
11603 if (intent != null && intent.hasFileDescriptors() == true) {
11604 throw new IllegalArgumentException("File descriptors passed in Intent");
11605 }
11606
11607 synchronized(this) {
11608 if (!(token instanceof ServiceRecord)) {
11609 throw new IllegalArgumentException("Invalid service token");
11610 }
11611 ServiceRecord r = (ServiceRecord)token;
11612
11613 final long origId = Binder.clearCallingIdentity();
11614
Joe Onorato8a9b2202010-02-26 18:56:32 -080011615 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 + " " + intent + ": " + service);
11617 if (r != null) {
11618 Intent.FilterComparison filter
11619 = new Intent.FilterComparison(intent);
11620 IntentBindRecord b = r.bindings.get(filter);
11621 if (b != null && !b.received) {
11622 b.binder = service;
11623 b.requested = true;
11624 b.received = true;
11625 if (r.connections.size() > 0) {
11626 Iterator<ConnectionRecord> it
11627 = r.connections.values().iterator();
11628 while (it.hasNext()) {
11629 ConnectionRecord c = it.next();
11630 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011631 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011632 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011633 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011634 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011635 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 TAG, "Published intent: " + intent);
11637 continue;
11638 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011639 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011640 try {
11641 c.conn.connected(r.name, service);
11642 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011643 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 " to connection " + c.conn.asBinder() +
11645 " (in " + c.binding.client.processName + ")", e);
11646 }
11647 }
11648 }
11649 }
11650
11651 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11652
11653 Binder.restoreCallingIdentity(origId);
11654 }
11655 }
11656 }
11657
11658 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11659 // Refuse possible leaked file descriptors
11660 if (intent != null && intent.hasFileDescriptors() == true) {
11661 throw new IllegalArgumentException("File descriptors passed in Intent");
11662 }
11663
11664 synchronized(this) {
11665 if (!(token instanceof ServiceRecord)) {
11666 throw new IllegalArgumentException("Invalid service token");
11667 }
11668 ServiceRecord r = (ServiceRecord)token;
11669
11670 final long origId = Binder.clearCallingIdentity();
11671
11672 if (r != null) {
11673 Intent.FilterComparison filter
11674 = new Intent.FilterComparison(intent);
11675 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011676 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011677 + " at " + b + ": apps="
11678 + (b != null ? b.apps.size() : 0));
11679 if (b != null) {
11680 if (b.apps.size() > 0) {
11681 // Applications have already bound since the last
11682 // unbind, so just rebind right here.
11683 requestServiceBindingLocked(r, b, true);
11684 } else {
11685 // Note to tell the service the next time there is
11686 // a new client.
11687 b.doRebind = true;
11688 }
11689 }
11690
11691 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11692
11693 Binder.restoreCallingIdentity(origId);
11694 }
11695 }
11696 }
11697
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011698 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011699 synchronized(this) {
11700 if (!(token instanceof ServiceRecord)) {
11701 throw new IllegalArgumentException("Invalid service token");
11702 }
11703 ServiceRecord r = (ServiceRecord)token;
11704 boolean inStopping = mStoppingServices.contains(token);
11705 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011706 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 + ": nesting=" + r.executeNesting
11708 + ", inStopping=" + inStopping);
11709 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011710 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011711 + " with incorrect token: given " + token
11712 + ", expected " + r);
11713 return;
11714 }
11715
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011716 if (type == 1) {
11717 // This is a call from a service start... take care of
11718 // book-keeping.
11719 r.callStart = true;
11720 switch (res) {
11721 case Service.START_STICKY_COMPATIBILITY:
11722 case Service.START_STICKY: {
11723 // We are done with the associated start arguments.
11724 r.findDeliveredStart(startId, true);
11725 // Don't stop if killed.
11726 r.stopIfKilled = false;
11727 break;
11728 }
11729 case Service.START_NOT_STICKY: {
11730 // We are done with the associated start arguments.
11731 r.findDeliveredStart(startId, true);
11732 if (r.lastStartId == startId) {
11733 // There is no more work, and this service
11734 // doesn't want to hang around if killed.
11735 r.stopIfKilled = true;
11736 }
11737 break;
11738 }
11739 case Service.START_REDELIVER_INTENT: {
11740 // We'll keep this item until they explicitly
11741 // call stop for it, but keep track of the fact
11742 // that it was delivered.
11743 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11744 if (si != null) {
11745 si.deliveryCount = 0;
11746 si.doneExecutingCount++;
11747 // Don't stop if killed.
11748 r.stopIfKilled = true;
11749 }
11750 break;
11751 }
11752 default:
11753 throw new IllegalArgumentException(
11754 "Unknown service start result: " + res);
11755 }
11756 if (res == Service.START_STICKY_COMPATIBILITY) {
11757 r.callStart = false;
11758 }
11759 }
11760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761 final long origId = Binder.clearCallingIdentity();
11762 serviceDoneExecutingLocked(r, inStopping);
11763 Binder.restoreCallingIdentity(origId);
11764 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011765 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011766 + " with token " + token);
11767 }
11768 }
11769 }
11770
11771 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11772 r.executeNesting--;
11773 if (r.executeNesting <= 0 && r.app != null) {
11774 r.app.executingServices.remove(r);
11775 if (r.app.executingServices.size() == 0) {
11776 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11777 }
11778 if (inStopping) {
11779 mStoppingServices.remove(r);
11780 }
11781 updateOomAdjLocked(r.app);
11782 }
11783 }
11784
11785 void serviceTimeout(ProcessRecord proc) {
11786 synchronized(this) {
11787 if (proc.executingServices.size() == 0 || proc.thread == null) {
11788 return;
11789 }
11790 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11791 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11792 ServiceRecord timeout = null;
11793 long nextTime = 0;
11794 while (it.hasNext()) {
11795 ServiceRecord sr = it.next();
11796 if (sr.executingStart < maxTime) {
11797 timeout = sr;
11798 break;
11799 }
11800 if (sr.executingStart > nextTime) {
11801 nextTime = sr.executingStart;
11802 }
11803 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011804 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011805 Slog.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011806 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807 } else {
11808 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11809 msg.obj = proc;
11810 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11811 }
11812 }
11813 }
11814
11815 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011816 // BACKUP AND RESTORE
11817 // =========================================================
11818
11819 // Cause the target app to be launched if necessary and its backup agent
11820 // instantiated. The backup agent will invoke backupAgentCreated() on the
11821 // activity manager to announce its creation.
11822 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011823 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011824 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11825
11826 synchronized(this) {
11827 // !!! TODO: currently no check here that we're already bound
11828 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11829 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11830 synchronized (stats) {
11831 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11832 }
11833
11834 BackupRecord r = new BackupRecord(ss, app, backupMode);
11835 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11836 // startProcessLocked() returns existing proc's record if it's already running
11837 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011838 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011839 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011840 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011841 return false;
11842 }
11843
11844 r.app = proc;
11845 mBackupTarget = r;
11846 mBackupAppName = app.packageName;
11847
Christopher Tate6fa95972009-06-05 18:43:55 -070011848 // Try not to kill the process during backup
11849 updateOomAdjLocked(proc);
11850
Christopher Tate181fafa2009-05-14 11:12:14 -070011851 // If the process is already attached, schedule the creation of the backup agent now.
11852 // If it is not yet live, this will be done when it attaches to the framework.
11853 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011854 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011855 try {
11856 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11857 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011858 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011859 }
11860 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011861 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011862 }
11863 // Invariants: at this point, the target app process exists and the application
11864 // is either already running or in the process of coming up. mBackupTarget and
11865 // mBackupAppName describe the app, so that when it binds back to the AM we
11866 // know that it's scheduled for a backup-agent operation.
11867 }
11868
11869 return true;
11870 }
11871
11872 // A backup agent has just come up
11873 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011874 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011875 + " = " + agent);
11876
11877 synchronized(this) {
11878 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011879 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011880 return;
11881 }
11882
Christopher Tate043dadc2009-06-02 16:11:00 -070011883 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011884 try {
11885 IBackupManager bm = IBackupManager.Stub.asInterface(
11886 ServiceManager.getService(Context.BACKUP_SERVICE));
11887 bm.agentConnected(agentPackageName, agent);
11888 } catch (RemoteException e) {
11889 // can't happen; the backup manager service is local
11890 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011891 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070011892 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011893 } finally {
11894 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011895 }
11896 }
11897 }
11898
11899 // done with this agent
11900 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011901 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011902 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011903 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011904 return;
11905 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011906
11907 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011908 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011909 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011910 return;
11911 }
11912
Christopher Tate181fafa2009-05-14 11:12:14 -070011913 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011914 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011915 return;
11916 }
11917
Christopher Tate6fa95972009-06-05 18:43:55 -070011918 ProcessRecord proc = mBackupTarget.app;
11919 mBackupTarget = null;
11920 mBackupAppName = null;
11921
11922 // Not backing this app up any more; reset its OOM adjustment
11923 updateOomAdjLocked(proc);
11924
Christopher Tatec7b31e32009-06-10 15:49:30 -070011925 // If the app crashed during backup, 'thread' will be null here
11926 if (proc.thread != null) {
11927 try {
11928 proc.thread.scheduleDestroyBackupAgent(appInfo);
11929 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011930 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070011931 e.printStackTrace();
11932 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011933 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011934 }
11935 }
11936 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011937 // BROADCASTS
11938 // =========================================================
11939
11940 private final List getStickies(String action, IntentFilter filter,
11941 List cur) {
11942 final ContentResolver resolver = mContext.getContentResolver();
11943 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11944 if (list == null) {
11945 return cur;
11946 }
11947 int N = list.size();
11948 for (int i=0; i<N; i++) {
11949 Intent intent = list.get(i);
11950 if (filter.match(resolver, intent, true, TAG) >= 0) {
11951 if (cur == null) {
11952 cur = new ArrayList<Intent>();
11953 }
11954 cur.add(intent);
11955 }
11956 }
11957 return cur;
11958 }
11959
11960 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011961 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011962 + mBroadcastsScheduled);
11963
11964 if (mBroadcastsScheduled) {
11965 return;
11966 }
11967 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11968 mBroadcastsScheduled = true;
11969 }
11970
11971 public Intent registerReceiver(IApplicationThread caller,
11972 IIntentReceiver receiver, IntentFilter filter, String permission) {
11973 synchronized(this) {
11974 ProcessRecord callerApp = null;
11975 if (caller != null) {
11976 callerApp = getRecordForAppLocked(caller);
11977 if (callerApp == null) {
11978 throw new SecurityException(
11979 "Unable to find app for caller " + caller
11980 + " (pid=" + Binder.getCallingPid()
11981 + ") when registering receiver " + receiver);
11982 }
11983 }
11984
11985 List allSticky = null;
11986
11987 // Look for any matching sticky broadcasts...
11988 Iterator actions = filter.actionsIterator();
11989 if (actions != null) {
11990 while (actions.hasNext()) {
11991 String action = (String)actions.next();
11992 allSticky = getStickies(action, filter, allSticky);
11993 }
11994 } else {
11995 allSticky = getStickies(null, filter, allSticky);
11996 }
11997
11998 // The first sticky in the list is returned directly back to
11999 // the client.
12000 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12001
Joe Onorato8a9b2202010-02-26 18:56:32 -080012002 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012003 + ": " + sticky);
12004
12005 if (receiver == null) {
12006 return sticky;
12007 }
12008
12009 ReceiverList rl
12010 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12011 if (rl == null) {
12012 rl = new ReceiverList(this, callerApp,
12013 Binder.getCallingPid(),
12014 Binder.getCallingUid(), receiver);
12015 if (rl.app != null) {
12016 rl.app.receivers.add(rl);
12017 } else {
12018 try {
12019 receiver.asBinder().linkToDeath(rl, 0);
12020 } catch (RemoteException e) {
12021 return sticky;
12022 }
12023 rl.linkedToDeath = true;
12024 }
12025 mRegisteredReceivers.put(receiver.asBinder(), rl);
12026 }
12027 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12028 rl.add(bf);
12029 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012030 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012031 }
12032 mReceiverResolver.addFilter(bf);
12033
12034 // Enqueue broadcasts for all existing stickies that match
12035 // this filter.
12036 if (allSticky != null) {
12037 ArrayList receivers = new ArrayList();
12038 receivers.add(bf);
12039
12040 int N = allSticky.size();
12041 for (int i=0; i<N; i++) {
12042 Intent intent = (Intent)allSticky.get(i);
12043 BroadcastRecord r = new BroadcastRecord(intent, null,
12044 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012045 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012046 if (mParallelBroadcasts.size() == 0) {
12047 scheduleBroadcastsLocked();
12048 }
12049 mParallelBroadcasts.add(r);
12050 }
12051 }
12052
12053 return sticky;
12054 }
12055 }
12056
12057 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012058 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012059
12060 boolean doNext = false;
12061
12062 synchronized(this) {
12063 ReceiverList rl
12064 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12065 if (rl != null) {
12066 if (rl.curBroadcast != null) {
12067 BroadcastRecord r = rl.curBroadcast;
12068 doNext = finishReceiverLocked(
12069 receiver.asBinder(), r.resultCode, r.resultData,
12070 r.resultExtras, r.resultAbort, true);
12071 }
12072
12073 if (rl.app != null) {
12074 rl.app.receivers.remove(rl);
12075 }
12076 removeReceiverLocked(rl);
12077 if (rl.linkedToDeath) {
12078 rl.linkedToDeath = false;
12079 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12080 }
12081 }
12082 }
12083
12084 if (!doNext) {
12085 return;
12086 }
12087
12088 final long origId = Binder.clearCallingIdentity();
12089 processNextBroadcast(false);
12090 trimApplications();
12091 Binder.restoreCallingIdentity(origId);
12092 }
12093
12094 void removeReceiverLocked(ReceiverList rl) {
12095 mRegisteredReceivers.remove(rl.receiver.asBinder());
12096 int N = rl.size();
12097 for (int i=0; i<N; i++) {
12098 mReceiverResolver.removeFilter(rl.get(i));
12099 }
12100 }
12101
12102 private final int broadcastIntentLocked(ProcessRecord callerApp,
12103 String callerPackage, Intent intent, String resolvedType,
12104 IIntentReceiver resultTo, int resultCode, String resultData,
12105 Bundle map, String requiredPermission,
12106 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12107 intent = new Intent(intent);
12108
Joe Onorato8a9b2202010-02-26 18:56:32 -080012109 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012110 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12111 + " ordered=" + ordered);
12112 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012113 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012114 }
12115
12116 // Handle special intents: if this broadcast is from the package
12117 // manager about a package being removed, we need to remove all of
12118 // its activities from the history stack.
12119 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12120 intent.getAction());
12121 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12122 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012123 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012124 || uidRemoved) {
12125 if (checkComponentPermission(
12126 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12127 callingPid, callingUid, -1)
12128 == PackageManager.PERMISSION_GRANTED) {
12129 if (uidRemoved) {
12130 final Bundle intentExtras = intent.getExtras();
12131 final int uid = intentExtras != null
12132 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12133 if (uid >= 0) {
12134 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12135 synchronized (bs) {
12136 bs.removeUidStatsLocked(uid);
12137 }
12138 }
12139 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012140 // If resources are unvailble just force stop all
12141 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012142 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012143 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12144 if (list != null && (list.length > 0)) {
12145 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012146 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012147 }
12148 }
12149 } else {
12150 Uri data = intent.getData();
12151 String ssp;
12152 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12153 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12154 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012155 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012157 }
12158 }
12159 }
12160 } else {
12161 String msg = "Permission Denial: " + intent.getAction()
12162 + " broadcast from " + callerPackage + " (pid=" + callingPid
12163 + ", uid=" + callingUid + ")"
12164 + " requires "
12165 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012166 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012167 throw new SecurityException(msg);
12168 }
12169 }
12170
12171 /*
12172 * If this is the time zone changed action, queue up a message that will reset the timezone
12173 * of all currently running processes. This message will get queued up before the broadcast
12174 * happens.
12175 */
12176 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12177 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12178 }
12179
Dianne Hackborn854060af2009-07-09 18:14:31 -070012180 /*
12181 * Prevent non-system code (defined here to be non-persistent
12182 * processes) from sending protected broadcasts.
12183 */
12184 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12185 || callingUid == Process.SHELL_UID || callingUid == 0) {
12186 // Always okay.
12187 } else if (callerApp == null || !callerApp.persistent) {
12188 try {
12189 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12190 intent.getAction())) {
12191 String msg = "Permission Denial: not allowed to send broadcast "
12192 + intent.getAction() + " from pid="
12193 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012194 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012195 throw new SecurityException(msg);
12196 }
12197 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012198 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012199 return BROADCAST_SUCCESS;
12200 }
12201 }
12202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012203 // Add to the sticky list if requested.
12204 if (sticky) {
12205 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12206 callingPid, callingUid)
12207 != PackageManager.PERMISSION_GRANTED) {
12208 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12209 + callingPid + ", uid=" + callingUid
12210 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012211 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012212 throw new SecurityException(msg);
12213 }
12214 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012215 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012216 + " and enforce permission " + requiredPermission);
12217 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12218 }
12219 if (intent.getComponent() != null) {
12220 throw new SecurityException(
12221 "Sticky broadcasts can't target a specific component");
12222 }
12223 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12224 if (list == null) {
12225 list = new ArrayList<Intent>();
12226 mStickyBroadcasts.put(intent.getAction(), list);
12227 }
12228 int N = list.size();
12229 int i;
12230 for (i=0; i<N; i++) {
12231 if (intent.filterEquals(list.get(i))) {
12232 // This sticky already exists, replace it.
12233 list.set(i, new Intent(intent));
12234 break;
12235 }
12236 }
12237 if (i >= N) {
12238 list.add(new Intent(intent));
12239 }
12240 }
12241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012242 // Figure out who all will receive this broadcast.
12243 List receivers = null;
12244 List<BroadcastFilter> registeredReceivers = null;
12245 try {
12246 if (intent.getComponent() != null) {
12247 // Broadcast is going to one specific receiver class...
12248 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012249 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012250 if (ai != null) {
12251 receivers = new ArrayList();
12252 ResolveInfo ri = new ResolveInfo();
12253 ri.activityInfo = ai;
12254 receivers.add(ri);
12255 }
12256 } else {
12257 // Need to resolve the intent to interested receivers...
12258 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12259 == 0) {
12260 receivers =
12261 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012262 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012263 }
Mihai Preda074edef2009-05-18 17:13:31 +020012264 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012265 }
12266 } catch (RemoteException ex) {
12267 // pm is in same process, this will never happen.
12268 }
12269
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012270 final boolean replacePending =
12271 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12272
Joe Onorato8a9b2202010-02-26 18:56:32 -080012273 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012274 + " replacePending=" + replacePending);
12275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012276 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12277 if (!ordered && NR > 0) {
12278 // If we are not serializing this broadcast, then send the
12279 // registered receivers separately so they don't wait for the
12280 // components to be launched.
12281 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12282 callerPackage, callingPid, callingUid, requiredPermission,
12283 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012284 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012285 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012286 TAG, "Enqueueing parallel broadcast " + r
12287 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012288 boolean replaced = false;
12289 if (replacePending) {
12290 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12291 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012292 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012293 "***** DROPPING PARALLEL: " + intent);
12294 mParallelBroadcasts.set(i, r);
12295 replaced = true;
12296 break;
12297 }
12298 }
12299 }
12300 if (!replaced) {
12301 mParallelBroadcasts.add(r);
12302 scheduleBroadcastsLocked();
12303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012304 registeredReceivers = null;
12305 NR = 0;
12306 }
12307
12308 // Merge into one list.
12309 int ir = 0;
12310 if (receivers != null) {
12311 // A special case for PACKAGE_ADDED: do not allow the package
12312 // being added to see this broadcast. This prevents them from
12313 // using this as a back door to get run as soon as they are
12314 // installed. Maybe in the future we want to have a special install
12315 // broadcast or such for apps, but we'd like to deliberately make
12316 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012317 String skipPackages[] = null;
12318 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12319 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12320 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12321 Uri data = intent.getData();
12322 if (data != null) {
12323 String pkgName = data.getSchemeSpecificPart();
12324 if (pkgName != null) {
12325 skipPackages = new String[] { pkgName };
12326 }
12327 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012328 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012329 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012330 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012331 if (skipPackages != null && (skipPackages.length > 0)) {
12332 for (String skipPackage : skipPackages) {
12333 if (skipPackage != null) {
12334 int NT = receivers.size();
12335 for (int it=0; it<NT; it++) {
12336 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12337 if (curt.activityInfo.packageName.equals(skipPackage)) {
12338 receivers.remove(it);
12339 it--;
12340 NT--;
12341 }
12342 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012343 }
12344 }
12345 }
12346
12347 int NT = receivers != null ? receivers.size() : 0;
12348 int it = 0;
12349 ResolveInfo curt = null;
12350 BroadcastFilter curr = null;
12351 while (it < NT && ir < NR) {
12352 if (curt == null) {
12353 curt = (ResolveInfo)receivers.get(it);
12354 }
12355 if (curr == null) {
12356 curr = registeredReceivers.get(ir);
12357 }
12358 if (curr.getPriority() >= curt.priority) {
12359 // Insert this broadcast record into the final list.
12360 receivers.add(it, curr);
12361 ir++;
12362 curr = null;
12363 it++;
12364 NT++;
12365 } else {
12366 // Skip to the next ResolveInfo in the final list.
12367 it++;
12368 curt = null;
12369 }
12370 }
12371 }
12372 while (ir < NR) {
12373 if (receivers == null) {
12374 receivers = new ArrayList();
12375 }
12376 receivers.add(registeredReceivers.get(ir));
12377 ir++;
12378 }
12379
12380 if ((receivers != null && receivers.size() > 0)
12381 || resultTo != null) {
12382 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12383 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012384 receivers, resultTo, resultCode, resultData, map, ordered,
12385 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012386 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012387 TAG, "Enqueueing ordered broadcast " + r
12388 + ": prev had " + mOrderedBroadcasts.size());
12389 if (DEBUG_BROADCAST) {
12390 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012391 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012392 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012393 boolean replaced = false;
12394 if (replacePending) {
12395 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12396 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012397 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012398 "***** DROPPING ORDERED: " + intent);
12399 mOrderedBroadcasts.set(i, r);
12400 replaced = true;
12401 break;
12402 }
12403 }
12404 }
12405 if (!replaced) {
12406 mOrderedBroadcasts.add(r);
12407 scheduleBroadcastsLocked();
12408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012409 }
12410
12411 return BROADCAST_SUCCESS;
12412 }
12413
12414 public final int broadcastIntent(IApplicationThread caller,
12415 Intent intent, String resolvedType, IIntentReceiver resultTo,
12416 int resultCode, String resultData, Bundle map,
12417 String requiredPermission, boolean serialized, boolean sticky) {
12418 // Refuse possible leaked file descriptors
12419 if (intent != null && intent.hasFileDescriptors() == true) {
12420 throw new IllegalArgumentException("File descriptors passed in Intent");
12421 }
12422
12423 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012424 int flags = intent.getFlags();
12425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012426 if (!mSystemReady) {
12427 // if the caller really truly claims to know what they're doing, go
12428 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012429 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12430 intent = new Intent(intent);
12431 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12432 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012433 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012434 + " before boot completion");
12435 throw new IllegalStateException("Cannot broadcast before boot completed");
12436 }
12437 }
12438
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012439 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12440 throw new IllegalArgumentException(
12441 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12442 }
12443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012444 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12445 final int callingPid = Binder.getCallingPid();
12446 final int callingUid = Binder.getCallingUid();
12447 final long origId = Binder.clearCallingIdentity();
12448 int res = broadcastIntentLocked(callerApp,
12449 callerApp != null ? callerApp.info.packageName : null,
12450 intent, resolvedType, resultTo,
12451 resultCode, resultData, map, requiredPermission, serialized,
12452 sticky, callingPid, callingUid);
12453 Binder.restoreCallingIdentity(origId);
12454 return res;
12455 }
12456 }
12457
12458 int broadcastIntentInPackage(String packageName, int uid,
12459 Intent intent, String resolvedType, IIntentReceiver resultTo,
12460 int resultCode, String resultData, Bundle map,
12461 String requiredPermission, boolean serialized, boolean sticky) {
12462 synchronized(this) {
12463 final long origId = Binder.clearCallingIdentity();
12464 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12465 resultTo, resultCode, resultData, map, requiredPermission,
12466 serialized, sticky, -1, uid);
12467 Binder.restoreCallingIdentity(origId);
12468 return res;
12469 }
12470 }
12471
12472 public final void unbroadcastIntent(IApplicationThread caller,
12473 Intent intent) {
12474 // Refuse possible leaked file descriptors
12475 if (intent != null && intent.hasFileDescriptors() == true) {
12476 throw new IllegalArgumentException("File descriptors passed in Intent");
12477 }
12478
12479 synchronized(this) {
12480 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12481 != PackageManager.PERMISSION_GRANTED) {
12482 String msg = "Permission Denial: unbroadcastIntent() from pid="
12483 + Binder.getCallingPid()
12484 + ", uid=" + Binder.getCallingUid()
12485 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012486 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012487 throw new SecurityException(msg);
12488 }
12489 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12490 if (list != null) {
12491 int N = list.size();
12492 int i;
12493 for (i=0; i<N; i++) {
12494 if (intent.filterEquals(list.get(i))) {
12495 list.remove(i);
12496 break;
12497 }
12498 }
12499 }
12500 }
12501 }
12502
12503 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12504 String resultData, Bundle resultExtras, boolean resultAbort,
12505 boolean explicit) {
12506 if (mOrderedBroadcasts.size() == 0) {
12507 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012508 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012509 }
12510 return false;
12511 }
12512 BroadcastRecord r = mOrderedBroadcasts.get(0);
12513 if (r.receiver == null) {
12514 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012515 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012516 }
12517 return false;
12518 }
12519 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012520 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012521 return false;
12522 }
12523 int state = r.state;
12524 r.state = r.IDLE;
12525 if (state == r.IDLE) {
12526 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012527 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012528 }
12529 }
12530 r.receiver = null;
12531 r.intent.setComponent(null);
12532 if (r.curApp != null) {
12533 r.curApp.curReceiver = null;
12534 }
12535 if (r.curFilter != null) {
12536 r.curFilter.receiverList.curBroadcast = null;
12537 }
12538 r.curFilter = null;
12539 r.curApp = null;
12540 r.curComponent = null;
12541 r.curReceiver = null;
12542 mPendingBroadcast = null;
12543
12544 r.resultCode = resultCode;
12545 r.resultData = resultData;
12546 r.resultExtras = resultExtras;
12547 r.resultAbort = resultAbort;
12548
12549 // We will process the next receiver right now if this is finishing
12550 // an app receiver (which is always asynchronous) or after we have
12551 // come back from calling a receiver.
12552 return state == BroadcastRecord.APP_RECEIVE
12553 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12554 }
12555
12556 public void finishReceiver(IBinder who, int resultCode, String resultData,
12557 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012558 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012559
12560 // Refuse possible leaked file descriptors
12561 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12562 throw new IllegalArgumentException("File descriptors passed in Bundle");
12563 }
12564
12565 boolean doNext;
12566
12567 final long origId = Binder.clearCallingIdentity();
12568
12569 synchronized(this) {
12570 doNext = finishReceiverLocked(
12571 who, resultCode, resultData, resultExtras, resultAbort, true);
12572 }
12573
12574 if (doNext) {
12575 processNextBroadcast(false);
12576 }
12577 trimApplications();
12578
12579 Binder.restoreCallingIdentity(origId);
12580 }
12581
12582 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12583 if (r.nextReceiver > 0) {
12584 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12585 if (curReceiver instanceof BroadcastFilter) {
12586 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012587 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012588 System.identityHashCode(r),
12589 r.intent.getAction(),
12590 r.nextReceiver - 1,
12591 System.identityHashCode(bf));
12592 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012593 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012594 System.identityHashCode(r),
12595 r.intent.getAction(),
12596 r.nextReceiver - 1,
12597 ((ResolveInfo)curReceiver).toString());
12598 }
12599 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012600 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012601 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012602 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012603 System.identityHashCode(r),
12604 r.intent.getAction(),
12605 r.nextReceiver,
12606 "NONE");
12607 }
12608 }
12609
12610 private final void broadcastTimeout() {
12611 synchronized (this) {
12612 if (mOrderedBroadcasts.size() == 0) {
12613 return;
12614 }
12615 long now = SystemClock.uptimeMillis();
12616 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012617 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012618 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012619 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012620 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012621 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012622 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012623 return;
12624 }
12625
Joe Onorato8a9b2202010-02-26 18:56:32 -080012626 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012627 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012628 r.anrCount++;
12629
12630 // Current receiver has passed its expiration date.
12631 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012632 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012633 return;
12634 }
12635
12636 ProcessRecord app = null;
12637
12638 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012639 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012640 logBroadcastReceiverDiscard(r);
12641 if (curReceiver instanceof BroadcastFilter) {
12642 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12643 if (bf.receiverList.pid != 0
12644 && bf.receiverList.pid != MY_PID) {
12645 synchronized (this.mPidsSelfLocked) {
12646 app = this.mPidsSelfLocked.get(
12647 bf.receiverList.pid);
12648 }
12649 }
12650 } else {
12651 app = r.curApp;
12652 }
12653
12654 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012655 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012656 }
12657
12658 if (mPendingBroadcast == r) {
12659 mPendingBroadcast = null;
12660 }
12661
12662 // Move on to the next receiver.
12663 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12664 r.resultExtras, r.resultAbort, true);
12665 scheduleBroadcastsLocked();
12666 }
12667 }
12668
12669 private final void processCurBroadcastLocked(BroadcastRecord r,
12670 ProcessRecord app) throws RemoteException {
12671 if (app.thread == null) {
12672 throw new RemoteException();
12673 }
12674 r.receiver = app.thread.asBinder();
12675 r.curApp = app;
12676 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012677 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012678
12679 // Tell the application to launch this receiver.
12680 r.intent.setComponent(r.curComponent);
12681
12682 boolean started = false;
12683 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012684 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012685 "Delivering to component " + r.curComponent
12686 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012687 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012688 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12689 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12690 started = true;
12691 } finally {
12692 if (!started) {
12693 r.receiver = null;
12694 r.curApp = null;
12695 app.curReceiver = null;
12696 }
12697 }
12698
12699 }
12700
12701 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012702 Intent intent, int resultCode, String data, Bundle extras,
12703 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012704 if (app != null && app.thread != null) {
12705 // If we have an app thread, do the call through that so it is
12706 // correctly ordered with other one-way calls.
12707 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012708 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012709 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012710 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012711 }
12712 }
12713
12714 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12715 BroadcastFilter filter, boolean ordered) {
12716 boolean skip = false;
12717 if (filter.requiredPermission != null) {
12718 int perm = checkComponentPermission(filter.requiredPermission,
12719 r.callingPid, r.callingUid, -1);
12720 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012721 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012722 + r.intent.toString()
12723 + " from " + r.callerPackage + " (pid="
12724 + r.callingPid + ", uid=" + r.callingUid + ")"
12725 + " requires " + filter.requiredPermission
12726 + " due to registered receiver " + filter);
12727 skip = true;
12728 }
12729 }
12730 if (r.requiredPermission != null) {
12731 int perm = checkComponentPermission(r.requiredPermission,
12732 filter.receiverList.pid, filter.receiverList.uid, -1);
12733 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012734 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012735 + r.intent.toString()
12736 + " to " + filter.receiverList.app
12737 + " (pid=" + filter.receiverList.pid
12738 + ", uid=" + filter.receiverList.uid + ")"
12739 + " requires " + r.requiredPermission
12740 + " due to sender " + r.callerPackage
12741 + " (uid " + r.callingUid + ")");
12742 skip = true;
12743 }
12744 }
12745
12746 if (!skip) {
12747 // If this is not being sent as an ordered broadcast, then we
12748 // don't want to touch the fields that keep track of the current
12749 // state of ordered broadcasts.
12750 if (ordered) {
12751 r.receiver = filter.receiverList.receiver.asBinder();
12752 r.curFilter = filter;
12753 filter.receiverList.curBroadcast = r;
12754 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012755 if (filter.receiverList.app != null) {
12756 // Bump hosting application to no longer be in background
12757 // scheduling class. Note that we can't do that if there
12758 // isn't an app... but we can only be in that case for
12759 // things that directly call the IActivityManager API, which
12760 // are already core system stuff so don't matter for this.
12761 r.curApp = filter.receiverList.app;
12762 filter.receiverList.app.curReceiver = r;
12763 updateOomAdjLocked();
12764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012765 }
12766 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012767 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012768 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012769 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012770 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012771 }
12772 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12773 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012774 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012775 if (ordered) {
12776 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12777 }
12778 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012779 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012780 if (ordered) {
12781 r.receiver = null;
12782 r.curFilter = null;
12783 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012784 if (filter.receiverList.app != null) {
12785 filter.receiverList.app.curReceiver = null;
12786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012787 }
12788 }
12789 }
12790 }
12791
Dianne Hackborn12527f92009-11-11 17:39:50 -080012792 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12793 if (r.callingUid < 0) {
12794 // This was from a registerReceiver() call; ignore it.
12795 return;
12796 }
12797 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12798 MAX_BROADCAST_HISTORY-1);
12799 r.finishTime = SystemClock.uptimeMillis();
12800 mBroadcastHistory[0] = r;
12801 }
12802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012803 private final void processNextBroadcast(boolean fromMsg) {
12804 synchronized(this) {
12805 BroadcastRecord r;
12806
Joe Onorato8a9b2202010-02-26 18:56:32 -080012807 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012808 + mParallelBroadcasts.size() + " broadcasts, "
12809 + mOrderedBroadcasts.size() + " serialized broadcasts");
12810
12811 updateCpuStats();
12812
12813 if (fromMsg) {
12814 mBroadcastsScheduled = false;
12815 }
12816
12817 // First, deliver any non-serialized broadcasts right away.
12818 while (mParallelBroadcasts.size() > 0) {
12819 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012820 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012821 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012822 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012823 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012824 for (int i=0; i<N; i++) {
12825 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012826 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012827 "Delivering non-serialized to registered "
12828 + target + ": " + r);
12829 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12830 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012831 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012832 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012833 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012834 }
12835
12836 // Now take care of the next serialized one...
12837
12838 // If we are waiting for a process to come up to handle the next
12839 // broadcast, then do nothing at this point. Just in case, we
12840 // check that the process we're waiting for still exists.
12841 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012842 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012843 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012844 + mPendingBroadcast.curApp);
12845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012846
12847 boolean isDead;
12848 synchronized (mPidsSelfLocked) {
12849 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12850 }
12851 if (!isDead) {
12852 // It's still alive, so keep waiting
12853 return;
12854 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012855 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012856 + " died before responding to broadcast");
12857 mPendingBroadcast = null;
12858 }
12859 }
12860
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012861 boolean looped = false;
12862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012863 do {
12864 if (mOrderedBroadcasts.size() == 0) {
12865 // No more broadcasts pending, so all done!
12866 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012867 if (looped) {
12868 // If we had finished the last ordered broadcast, then
12869 // make sure all processes have correct oom and sched
12870 // adjustments.
12871 updateOomAdjLocked();
12872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012873 return;
12874 }
12875 r = mOrderedBroadcasts.get(0);
12876 boolean forceReceive = false;
12877
12878 // Ensure that even if something goes awry with the timeout
12879 // detection, we catch "hung" broadcasts here, discard them,
12880 // and continue to make progress.
12881 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12882 long now = SystemClock.uptimeMillis();
12883 if (r.dispatchTime > 0) {
12884 if ((numReceivers > 0) &&
12885 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012886 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012887 + " now=" + now
12888 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012889 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012890 + " intent=" + r.intent
12891 + " numReceivers=" + numReceivers
12892 + " nextReceiver=" + r.nextReceiver
12893 + " state=" + r.state);
12894 broadcastTimeout(); // forcibly finish this broadcast
12895 forceReceive = true;
12896 r.state = BroadcastRecord.IDLE;
12897 }
12898 }
12899
12900 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012901 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012902 "processNextBroadcast() called when not idle (state="
12903 + r.state + ")");
12904 return;
12905 }
12906
12907 if (r.receivers == null || r.nextReceiver >= numReceivers
12908 || r.resultAbort || forceReceive) {
12909 // No more receivers for this broadcast! Send the final
12910 // result if requested...
12911 if (r.resultTo != null) {
12912 try {
12913 if (DEBUG_BROADCAST) {
12914 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012915 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012916 + " seq=" + seq + " app=" + r.callerApp);
12917 }
12918 performReceive(r.callerApp, r.resultTo,
12919 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012920 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012921 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012922 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012923 }
12924 }
12925
Joe Onorato8a9b2202010-02-26 18:56:32 -080012926 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012927 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12928
Joe Onorato8a9b2202010-02-26 18:56:32 -080012929 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012930 + r);
12931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012932 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012933 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012934 mOrderedBroadcasts.remove(0);
12935 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012936 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012937 continue;
12938 }
12939 } while (r == null);
12940
12941 // Get the next receiver...
12942 int recIdx = r.nextReceiver++;
12943
12944 // Keep track of when this receiver started, and make sure there
12945 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012946 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012947 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012948 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012949
Joe Onorato8a9b2202010-02-26 18:56:32 -080012950 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012951 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012952 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012953 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012954 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012955 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012956 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012957 }
12958
12959 Object nextReceiver = r.receivers.get(recIdx);
12960 if (nextReceiver instanceof BroadcastFilter) {
12961 // Simple case: this is a registered receiver who gets
12962 // a direct call.
12963 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012964 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012965 "Delivering serialized to registered "
12966 + filter + ": " + r);
12967 deliverToRegisteredReceiver(r, filter, r.ordered);
12968 if (r.receiver == null || !r.ordered) {
12969 // The receiver has already finished, so schedule to
12970 // process the next one.
12971 r.state = BroadcastRecord.IDLE;
12972 scheduleBroadcastsLocked();
12973 }
12974 return;
12975 }
12976
12977 // Hard case: need to instantiate the receiver, possibly
12978 // starting its application process to host it.
12979
12980 ResolveInfo info =
12981 (ResolveInfo)nextReceiver;
12982
12983 boolean skip = false;
12984 int perm = checkComponentPermission(info.activityInfo.permission,
12985 r.callingPid, r.callingUid,
12986 info.activityInfo.exported
12987 ? -1 : info.activityInfo.applicationInfo.uid);
12988 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012989 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012990 + r.intent.toString()
12991 + " from " + r.callerPackage + " (pid=" + r.callingPid
12992 + ", uid=" + r.callingUid + ")"
12993 + " requires " + info.activityInfo.permission
12994 + " due to receiver " + info.activityInfo.packageName
12995 + "/" + info.activityInfo.name);
12996 skip = true;
12997 }
12998 if (r.callingUid != Process.SYSTEM_UID &&
12999 r.requiredPermission != null) {
13000 try {
13001 perm = ActivityThread.getPackageManager().
13002 checkPermission(r.requiredPermission,
13003 info.activityInfo.applicationInfo.packageName);
13004 } catch (RemoteException e) {
13005 perm = PackageManager.PERMISSION_DENIED;
13006 }
13007 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013008 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013009 + r.intent + " to "
13010 + info.activityInfo.applicationInfo.packageName
13011 + " requires " + r.requiredPermission
13012 + " due to sender " + r.callerPackage
13013 + " (uid " + r.callingUid + ")");
13014 skip = true;
13015 }
13016 }
13017 if (r.curApp != null && r.curApp.crashing) {
13018 // If the target process is crashing, just skip it.
13019 skip = true;
13020 }
13021
13022 if (skip) {
13023 r.receiver = null;
13024 r.curFilter = null;
13025 r.state = BroadcastRecord.IDLE;
13026 scheduleBroadcastsLocked();
13027 return;
13028 }
13029
13030 r.state = BroadcastRecord.APP_RECEIVE;
13031 String targetProcess = info.activityInfo.processName;
13032 r.curComponent = new ComponentName(
13033 info.activityInfo.applicationInfo.packageName,
13034 info.activityInfo.name);
13035 r.curReceiver = info.activityInfo;
13036
13037 // Is this receiver's application already running?
13038 ProcessRecord app = getProcessRecordLocked(targetProcess,
13039 info.activityInfo.applicationInfo.uid);
13040 if (app != null && app.thread != null) {
13041 try {
13042 processCurBroadcastLocked(r, app);
13043 return;
13044 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013045 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013046 + r.curComponent, e);
13047 }
13048
13049 // If a dead object exception was thrown -- fall through to
13050 // restart the application.
13051 }
13052
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013053 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013054 if ((r.curApp=startProcessLocked(targetProcess,
13055 info.activityInfo.applicationInfo, true,
13056 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013057 "broadcast", r.curComponent,
13058 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13059 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013060 // Ah, this recipient is unavailable. Finish it if necessary,
13061 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013062 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013063 + info.activityInfo.applicationInfo.packageName + "/"
13064 + info.activityInfo.applicationInfo.uid + " for broadcast "
13065 + r.intent + ": process is bad");
13066 logBroadcastReceiverDiscard(r);
13067 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13068 r.resultExtras, r.resultAbort, true);
13069 scheduleBroadcastsLocked();
13070 r.state = BroadcastRecord.IDLE;
13071 return;
13072 }
13073
13074 mPendingBroadcast = r;
13075 }
13076 }
13077
13078 // =========================================================
13079 // INSTRUMENTATION
13080 // =========================================================
13081
13082 public boolean startInstrumentation(ComponentName className,
13083 String profileFile, int flags, Bundle arguments,
13084 IInstrumentationWatcher watcher) {
13085 // Refuse possible leaked file descriptors
13086 if (arguments != null && arguments.hasFileDescriptors()) {
13087 throw new IllegalArgumentException("File descriptors passed in Bundle");
13088 }
13089
13090 synchronized(this) {
13091 InstrumentationInfo ii = null;
13092 ApplicationInfo ai = null;
13093 try {
13094 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013095 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013096 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013097 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013098 } catch (PackageManager.NameNotFoundException e) {
13099 }
13100 if (ii == null) {
13101 reportStartInstrumentationFailure(watcher, className,
13102 "Unable to find instrumentation info for: " + className);
13103 return false;
13104 }
13105 if (ai == null) {
13106 reportStartInstrumentationFailure(watcher, className,
13107 "Unable to find instrumentation target package: " + ii.targetPackage);
13108 return false;
13109 }
13110
13111 int match = mContext.getPackageManager().checkSignatures(
13112 ii.targetPackage, ii.packageName);
13113 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13114 String msg = "Permission Denial: starting instrumentation "
13115 + className + " from pid="
13116 + Binder.getCallingPid()
13117 + ", uid=" + Binder.getCallingPid()
13118 + " not allowed because package " + ii.packageName
13119 + " does not have a signature matching the target "
13120 + ii.targetPackage;
13121 reportStartInstrumentationFailure(watcher, className, msg);
13122 throw new SecurityException(msg);
13123 }
13124
13125 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013126 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013127 ProcessRecord app = addAppLocked(ai);
13128 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013129 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013130 app.instrumentationProfileFile = profileFile;
13131 app.instrumentationArguments = arguments;
13132 app.instrumentationWatcher = watcher;
13133 app.instrumentationResultClass = className;
13134 Binder.restoreCallingIdentity(origId);
13135 }
13136
13137 return true;
13138 }
13139
13140 /**
13141 * Report errors that occur while attempting to start Instrumentation. Always writes the
13142 * error to the logs, but if somebody is watching, send the report there too. This enables
13143 * the "am" command to report errors with more information.
13144 *
13145 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13146 * @param cn The component name of the instrumentation.
13147 * @param report The error report.
13148 */
13149 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13150 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013151 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013152 try {
13153 if (watcher != null) {
13154 Bundle results = new Bundle();
13155 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13156 results.putString("Error", report);
13157 watcher.instrumentationStatus(cn, -1, results);
13158 }
13159 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013160 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013161 }
13162 }
13163
13164 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13165 if (app.instrumentationWatcher != null) {
13166 try {
13167 // NOTE: IInstrumentationWatcher *must* be oneway here
13168 app.instrumentationWatcher.instrumentationFinished(
13169 app.instrumentationClass,
13170 resultCode,
13171 results);
13172 } catch (RemoteException e) {
13173 }
13174 }
13175 app.instrumentationWatcher = null;
13176 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013177 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013178 app.instrumentationProfileFile = null;
13179 app.instrumentationArguments = null;
13180
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013181 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013182 }
13183
13184 public void finishInstrumentation(IApplicationThread target,
13185 int resultCode, Bundle results) {
13186 // Refuse possible leaked file descriptors
13187 if (results != null && results.hasFileDescriptors()) {
13188 throw new IllegalArgumentException("File descriptors passed in Intent");
13189 }
13190
13191 synchronized(this) {
13192 ProcessRecord app = getRecordForAppLocked(target);
13193 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013194 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013195 return;
13196 }
13197 final long origId = Binder.clearCallingIdentity();
13198 finishInstrumentationLocked(app, resultCode, results);
13199 Binder.restoreCallingIdentity(origId);
13200 }
13201 }
13202
13203 // =========================================================
13204 // CONFIGURATION
13205 // =========================================================
13206
13207 public ConfigurationInfo getDeviceConfigurationInfo() {
13208 ConfigurationInfo config = new ConfigurationInfo();
13209 synchronized (this) {
13210 config.reqTouchScreen = mConfiguration.touchscreen;
13211 config.reqKeyboardType = mConfiguration.keyboard;
13212 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013213 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13214 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013215 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13216 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013217 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13218 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013219 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13220 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013221 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013222 }
13223 return config;
13224 }
13225
13226 public Configuration getConfiguration() {
13227 Configuration ci;
13228 synchronized(this) {
13229 ci = new Configuration(mConfiguration);
13230 }
13231 return ci;
13232 }
13233
13234 public void updateConfiguration(Configuration values) {
13235 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13236 "updateConfiguration()");
13237
13238 synchronized(this) {
13239 if (values == null && mWindowManager != null) {
13240 // sentinel: fetch the current configuration from the window manager
13241 values = mWindowManager.computeNewConfiguration();
13242 }
13243
13244 final long origId = Binder.clearCallingIdentity();
13245 updateConfigurationLocked(values, null);
13246 Binder.restoreCallingIdentity(origId);
13247 }
13248 }
13249
13250 /**
13251 * Do either or both things: (1) change the current configuration, and (2)
13252 * make sure the given activity is running with the (now) current
13253 * configuration. Returns true if the activity has been left running, or
13254 * false if <var>starting</var> is being destroyed to match the new
13255 * configuration.
13256 */
13257 public boolean updateConfigurationLocked(Configuration values,
13258 HistoryRecord starting) {
13259 int changes = 0;
13260
13261 boolean kept = true;
13262
13263 if (values != null) {
13264 Configuration newConfig = new Configuration(mConfiguration);
13265 changes = newConfig.updateFrom(values);
13266 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013267 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013268 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013269 }
13270
Doug Zongker2bec3d42009-12-04 12:52:44 -080013271 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013272
13273 if (values.locale != null) {
13274 saveLocaleLocked(values.locale,
13275 !values.locale.equals(mConfiguration.locale),
13276 values.userSetLocale);
13277 }
13278
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013279 mConfigurationSeq++;
13280 if (mConfigurationSeq <= 0) {
13281 mConfigurationSeq = 1;
13282 }
13283 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013284 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013285 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013286
13287 AttributeCache ac = AttributeCache.instance();
13288 if (ac != null) {
13289 ac.updateConfiguration(mConfiguration);
13290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013291
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013292 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13293 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13294 msg.obj = new Configuration(mConfiguration);
13295 mHandler.sendMessage(msg);
13296 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013297
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013298 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13299 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013300 try {
13301 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013302 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013303 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013304 app.thread.scheduleConfigurationChanged(mConfiguration);
13305 }
13306 } catch (Exception e) {
13307 }
13308 }
13309 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013310 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13311 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013312 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13313 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013314 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13315 broadcastIntentLocked(null, null,
13316 new Intent(Intent.ACTION_LOCALE_CHANGED),
13317 null, null, 0, null, null,
13318 null, false, false, MY_PID, Process.SYSTEM_UID);
13319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013320 }
13321 }
13322
13323 if (changes != 0 && starting == null) {
13324 // If the configuration changed, and the caller is not already
13325 // in the process of starting an activity, then find the top
13326 // activity to check if its configuration needs to change.
13327 starting = topRunningActivityLocked(null);
13328 }
13329
13330 if (starting != null) {
13331 kept = ensureActivityConfigurationLocked(starting, changes);
13332 if (kept) {
13333 // If this didn't result in the starting activity being
13334 // destroyed, then we need to make sure at this point that all
13335 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013336 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013337 + ", ensuring others are correct.");
13338 ensureActivitiesVisibleLocked(starting, changes);
13339 }
13340 }
13341
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013342 if (values != null && mWindowManager != null) {
13343 mWindowManager.setNewConfiguration(mConfiguration);
13344 }
13345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013346 return kept;
13347 }
13348
13349 private final boolean relaunchActivityLocked(HistoryRecord r,
13350 int changes, boolean andResume) {
13351 List<ResultInfo> results = null;
13352 List<Intent> newIntents = null;
13353 if (andResume) {
13354 results = r.results;
13355 newIntents = r.newIntents;
13356 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013357 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013358 + " with results=" + results + " newIntents=" + newIntents
13359 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013360 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13361 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013362 r.task.taskId, r.shortComponentName);
13363
13364 r.startFreezingScreenLocked(r.app, 0);
13365
13366 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013367 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013368 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013369 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013370 // Note: don't need to call pauseIfSleepingLocked() here, because
13371 // the caller will only pass in 'andResume' if this activity is
13372 // currently resumed, which implies we aren't sleeping.
13373 } catch (RemoteException e) {
13374 return false;
13375 }
13376
13377 if (andResume) {
13378 r.results = null;
13379 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013380 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381 }
13382
13383 return true;
13384 }
13385
13386 /**
13387 * Make sure the given activity matches the current configuration. Returns
13388 * false if the activity had to be destroyed. Returns true if the
13389 * configuration is the same, or the activity will remain running as-is
13390 * for whatever reason. Ensures the HistoryRecord is updated with the
13391 * correct configuration and all other bookkeeping is handled.
13392 */
13393 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13394 int globalChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013395 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013396 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013397
13398 // Short circuit: if the two configurations are the exact same
13399 // object (the common case), then there is nothing to do.
13400 Configuration newConfig = mConfiguration;
13401 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013402 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013403 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013404 return true;
13405 }
13406
13407 // We don't worry about activities that are finishing.
13408 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013409 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013410 "Configuration doesn't matter in finishing " + r);
13411 r.stopFreezingScreenLocked(false);
13412 return true;
13413 }
13414
13415 // Okay we now are going to make this activity have the new config.
13416 // But then we need to figure out how it needs to deal with that.
13417 Configuration oldConfig = r.configuration;
13418 r.configuration = newConfig;
13419
13420 // If the activity isn't currently running, just leave the new
13421 // configuration and it will pick that up next time it starts.
13422 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013423 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013424 "Configuration doesn't matter not running " + r);
13425 r.stopFreezingScreenLocked(false);
13426 return true;
13427 }
13428
13429 // If the activity isn't persistent, there is a chance we will
13430 // need to restart it.
13431 if (!r.persistent) {
13432
13433 // Figure out what has changed between the two configurations.
13434 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013435 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013436 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013437 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013438 + Integer.toHexString(r.info.configChanges)
13439 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013440 }
13441 if ((changes&(~r.info.configChanges)) != 0) {
13442 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13443 r.configChangeFlags |= changes;
13444 r.startFreezingScreenLocked(r.app, globalChanges);
13445 if (r.app == null || r.app.thread == null) {
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 destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013448 destroyActivityLocked(r, true);
13449 } else if (r.state == ActivityState.PAUSING) {
13450 // A little annoying: we are waiting for this activity to
13451 // finish pausing. Let's not do anything now, but just
13452 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013453 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013454 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013455 r.configDestroy = true;
13456 return true;
13457 } else if (r.state == ActivityState.RESUMED) {
13458 // Try to optimize this case: the configuration is changing
13459 // and we need to restart the top, resumed activity.
13460 // Instead of doing the normal handshaking, just say
13461 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013462 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013463 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013464 relaunchActivityLocked(r, r.configChangeFlags, true);
13465 r.configChangeFlags = 0;
13466 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013467 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013468 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013469 relaunchActivityLocked(r, r.configChangeFlags, false);
13470 r.configChangeFlags = 0;
13471 }
13472
13473 // All done... tell the caller we weren't able to keep this
13474 // activity around.
13475 return false;
13476 }
13477 }
13478
13479 // Default case: the activity can handle this new configuration, so
13480 // hand it over. Note that we don't need to give it the new
13481 // configuration, since we always send configuration changes to all
13482 // process when they happen so it can just use whatever configuration
13483 // it last got.
13484 if (r.app != null && r.app.thread != null) {
13485 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013486 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013487 r.app.thread.scheduleActivityConfigurationChanged(r);
13488 } catch (RemoteException e) {
13489 // If process died, whatever.
13490 }
13491 }
13492 r.stopFreezingScreenLocked(false);
13493
13494 return true;
13495 }
13496
13497 /**
13498 * Save the locale. You must be inside a synchronized (this) block.
13499 */
13500 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13501 if(isDiff) {
13502 SystemProperties.set("user.language", l.getLanguage());
13503 SystemProperties.set("user.region", l.getCountry());
13504 }
13505
13506 if(isPersist) {
13507 SystemProperties.set("persist.sys.language", l.getLanguage());
13508 SystemProperties.set("persist.sys.country", l.getCountry());
13509 SystemProperties.set("persist.sys.localevar", l.getVariant());
13510 }
13511 }
13512
13513 // =========================================================
13514 // LIFETIME MANAGEMENT
13515 // =========================================================
13516
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013517 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13518 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013519 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013520 // This adjustment has already been computed. If we are calling
13521 // from the top, we may have already computed our adjustment with
13522 // an earlier hidden adjustment that isn't really for us... if
13523 // so, use the new hidden adjustment.
13524 if (!recursed && app.hidden) {
13525 app.curAdj = hiddenAdj;
13526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013527 return app.curAdj;
13528 }
13529
13530 if (app.thread == null) {
13531 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013532 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013533 return (app.curAdj=EMPTY_APP_ADJ);
13534 }
13535
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013536 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13537 // The max adjustment doesn't allow this app to be anything
13538 // below foreground, so it is not worth doing work for it.
13539 app.adjType = "fixed";
13540 app.adjSeq = mAdjSeq;
13541 app.curRawAdj = app.maxAdj;
13542 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13543 return (app.curAdj=app.maxAdj);
13544 }
13545
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013546 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013547 app.adjSource = null;
13548 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013549 app.empty = false;
13550 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013551
The Android Open Source Project4df24232009-03-05 14:34:35 -080013552 // Determine the importance of the process, starting with most
13553 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013554 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013555 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013556 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013557 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013558 // The last app on the list is the foreground app.
13559 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013560 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013561 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013562 } else if (app.instrumentationClass != null) {
13563 // Don't want to kill running instrumentation.
13564 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013565 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013566 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013567 } else if (app.persistentActivities > 0) {
13568 // Special persistent activities... shouldn't be used these days.
13569 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013570 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013571 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013572 } else if (app.curReceiver != null ||
13573 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13574 // An app that is currently receiving a broadcast also
13575 // counts as being in the foreground.
13576 adj = FOREGROUND_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 = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013579 } else if (app.executingServices.size() > 0) {
13580 // An app that is currently executing a service callback also
13581 // counts as being in the foreground.
13582 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013583 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013584 app.adjType = "exec-service";
13585 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013586 // The user is aware of this app, so make it visible.
13587 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013588 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013589 app.adjType = "foreground-service";
13590 } else if (app.forcingToForeground != null) {
13591 // The user is aware of this app, so make it visible.
13592 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013593 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013594 app.adjType = "force-foreground";
13595 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013596 } else if (app == mHomeProcess) {
13597 // This process is hosting what we currently consider to be the
13598 // home app, so we don't want to let it go into the background.
13599 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013600 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013601 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013602 } else if ((N=app.activities.size()) != 0) {
13603 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013604 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013605 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013606 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013607 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013608 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013609 for (int j=0; j<N; j++) {
13610 if (((HistoryRecord)app.activities.get(j)).visible) {
13611 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013612 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013613 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013614 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013615 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013616 break;
13617 }
13618 }
13619 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013620 // A very not-needed process. If this is lower in the lru list,
13621 // we will push it in to the empty bucket.
13622 app.hidden = true;
13623 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013624 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013625 adj = hiddenAdj;
13626 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013627 }
13628
Joe Onorato8a9b2202010-02-26 18:56:32 -080013629 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013630
The Android Open Source Project4df24232009-03-05 14:34:35 -080013631 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013632 // there are applications dependent on our services or providers, but
13633 // this gives us a baseline and makes sure we don't get into an
13634 // infinite recursion.
13635 app.adjSeq = mAdjSeq;
13636 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013637
Christopher Tate6fa95972009-06-05 18:43:55 -070013638 if (mBackupTarget != null && app == mBackupTarget.app) {
13639 // If possible we want to avoid killing apps while they're being backed up
13640 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013641 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013642 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013643 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013644 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013645 }
13646 }
13647
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013648 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13649 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013650 final long now = SystemClock.uptimeMillis();
13651 // This process is more important if the top activity is
13652 // bound to the service.
13653 Iterator jt = app.services.iterator();
13654 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13655 ServiceRecord s = (ServiceRecord)jt.next();
13656 if (s.startRequested) {
13657 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13658 // This service has seen some activity within
13659 // recent memory, so we will keep its process ahead
13660 // of the background processes.
13661 if (adj > SECONDARY_SERVER_ADJ) {
13662 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013663 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013664 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013665 }
13666 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013667 // If we have let the service slide into the background
13668 // state, still have some text describing what it is doing
13669 // even though the service no longer has an impact.
13670 if (adj > SECONDARY_SERVER_ADJ) {
13671 app.adjType = "started-bg-services";
13672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013673 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013674 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13675 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013676 Iterator<ConnectionRecord> kt
13677 = s.connections.values().iterator();
13678 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13679 // XXX should compute this based on the max of
13680 // all connected clients.
13681 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013682 if (cr.binding.client == app) {
13683 // Binding to ourself is not interesting.
13684 continue;
13685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013686 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13687 ProcessRecord client = cr.binding.client;
13688 int myHiddenAdj = hiddenAdj;
13689 if (myHiddenAdj > client.hiddenAdj) {
13690 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13691 myHiddenAdj = client.hiddenAdj;
13692 } else {
13693 myHiddenAdj = VISIBLE_APP_ADJ;
13694 }
13695 }
13696 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013697 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013698 if (adj > clientAdj) {
13699 adj = clientAdj > VISIBLE_APP_ADJ
13700 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013701 if (!client.hidden) {
13702 app.hidden = false;
13703 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013704 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013705 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13706 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013707 app.adjSource = cr.binding.client;
13708 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013709 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013710 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13711 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13712 schedGroup = Process.THREAD_GROUP_DEFAULT;
13713 }
13714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013715 }
13716 HistoryRecord a = cr.activity;
13717 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013718 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013719 //}
13720 if (a != null && adj > FOREGROUND_APP_ADJ &&
13721 (a.state == ActivityState.RESUMED
13722 || a.state == ActivityState.PAUSING)) {
13723 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013724 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013725 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013726 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013727 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13728 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013729 app.adjSource = a;
13730 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013731 }
13732 }
13733 }
13734 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013735
13736 // Finally, f this process has active services running in it, we
13737 // would like to avoid killing it unless it would prevent the current
13738 // application from running. By default we put the process in
13739 // with the rest of the background processes; as we scan through
13740 // its services we may bump it up from there.
13741 if (adj > hiddenAdj) {
13742 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013743 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013744 app.adjType = "bg-services";
13745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013746 }
13747
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013748 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13749 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013750 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013751 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13752 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013753 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13754 if (cpr.clients.size() != 0) {
13755 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13756 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13757 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013758 if (client == app) {
13759 // Being our own client is not interesting.
13760 continue;
13761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013762 int myHiddenAdj = hiddenAdj;
13763 if (myHiddenAdj > client.hiddenAdj) {
13764 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13765 myHiddenAdj = client.hiddenAdj;
13766 } else {
13767 myHiddenAdj = FOREGROUND_APP_ADJ;
13768 }
13769 }
13770 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013771 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013772 if (adj > clientAdj) {
13773 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013774 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013775 if (!client.hidden) {
13776 app.hidden = false;
13777 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013778 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013779 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13780 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013781 app.adjSource = client;
13782 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013783 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013784 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13785 schedGroup = Process.THREAD_GROUP_DEFAULT;
13786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013787 }
13788 }
13789 // If the provider has external (non-framework) process
13790 // dependencies, ensure that its adjustment is at least
13791 // FOREGROUND_APP_ADJ.
13792 if (cpr.externals != 0) {
13793 if (adj > FOREGROUND_APP_ADJ) {
13794 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013795 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013796 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013797 app.adjType = "provider";
13798 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013799 }
13800 }
13801 }
13802 }
13803
13804 app.curRawAdj = adj;
13805
Joe Onorato8a9b2202010-02-26 18:56:32 -080013806 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013807 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13808 if (adj > app.maxAdj) {
13809 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013810 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13811 schedGroup = Process.THREAD_GROUP_DEFAULT;
13812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013813 }
13814
13815 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013816 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013818 return adj;
13819 }
13820
13821 /**
13822 * Ask a given process to GC right now.
13823 */
13824 final void performAppGcLocked(ProcessRecord app) {
13825 try {
13826 app.lastRequestedGc = SystemClock.uptimeMillis();
13827 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013828 if (app.reportLowMemory) {
13829 app.reportLowMemory = false;
13830 app.thread.scheduleLowMemory();
13831 } else {
13832 app.thread.processInBackground();
13833 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013834 }
13835 } catch (Exception e) {
13836 // whatever.
13837 }
13838 }
13839
13840 /**
13841 * Returns true if things are idle enough to perform GCs.
13842 */
13843 private final boolean canGcNow() {
13844 return mParallelBroadcasts.size() == 0
13845 && mOrderedBroadcasts.size() == 0
13846 && (mSleeping || (mResumedActivity != null &&
13847 mResumedActivity.idle));
13848 }
13849
13850 /**
13851 * Perform GCs on all processes that are waiting for it, but only
13852 * if things are idle.
13853 */
13854 final void performAppGcsLocked() {
13855 final int N = mProcessesToGc.size();
13856 if (N <= 0) {
13857 return;
13858 }
13859 if (canGcNow()) {
13860 while (mProcessesToGc.size() > 0) {
13861 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013862 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13863 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13864 <= SystemClock.uptimeMillis()) {
13865 // To avoid spamming the system, we will GC processes one
13866 // at a time, waiting a few seconds between each.
13867 performAppGcLocked(proc);
13868 scheduleAppGcsLocked();
13869 return;
13870 } else {
13871 // It hasn't been long enough since we last GCed this
13872 // process... put it in the list to wait for its time.
13873 addProcessToGcListLocked(proc);
13874 break;
13875 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013876 }
13877 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013878
13879 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013880 }
13881 }
13882
13883 /**
13884 * If all looks good, perform GCs on all processes waiting for them.
13885 */
13886 final void performAppGcsIfAppropriateLocked() {
13887 if (canGcNow()) {
13888 performAppGcsLocked();
13889 return;
13890 }
13891 // Still not idle, wait some more.
13892 scheduleAppGcsLocked();
13893 }
13894
13895 /**
13896 * Schedule the execution of all pending app GCs.
13897 */
13898 final void scheduleAppGcsLocked() {
13899 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013900
13901 if (mProcessesToGc.size() > 0) {
13902 // Schedule a GC for the time to the next process.
13903 ProcessRecord proc = mProcessesToGc.get(0);
13904 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13905
13906 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13907 long now = SystemClock.uptimeMillis();
13908 if (when < (now+GC_TIMEOUT)) {
13909 when = now + GC_TIMEOUT;
13910 }
13911 mHandler.sendMessageAtTime(msg, when);
13912 }
13913 }
13914
13915 /**
13916 * Add a process to the array of processes waiting to be GCed. Keeps the
13917 * list in sorted order by the last GC time. The process can't already be
13918 * on the list.
13919 */
13920 final void addProcessToGcListLocked(ProcessRecord proc) {
13921 boolean added = false;
13922 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13923 if (mProcessesToGc.get(i).lastRequestedGc <
13924 proc.lastRequestedGc) {
13925 added = true;
13926 mProcessesToGc.add(i+1, proc);
13927 break;
13928 }
13929 }
13930 if (!added) {
13931 mProcessesToGc.add(0, proc);
13932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013933 }
13934
13935 /**
13936 * Set up to ask a process to GC itself. This will either do it
13937 * immediately, or put it on the list of processes to gc the next
13938 * time things are idle.
13939 */
13940 final void scheduleAppGcLocked(ProcessRecord app) {
13941 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013942 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013943 return;
13944 }
13945 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013946 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013947 scheduleAppGcsLocked();
13948 }
13949 }
13950
13951 private final boolean updateOomAdjLocked(
13952 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13953 app.hiddenAdj = hiddenAdj;
13954
13955 if (app.thread == null) {
13956 return true;
13957 }
13958
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013959 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013960
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013961 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013962 if (app.curRawAdj != app.setRawAdj) {
13963 if (app.curRawAdj > FOREGROUND_APP_ADJ
13964 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13965 // If this app is transitioning from foreground to
13966 // non-foreground, have it do a gc.
13967 scheduleAppGcLocked(app);
13968 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13969 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13970 // Likewise do a gc when an app is moving in to the
13971 // background (such as a service stopping).
13972 scheduleAppGcLocked(app);
13973 }
13974 app.setRawAdj = app.curRawAdj;
13975 }
13976 if (adj != app.setAdj) {
13977 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013978 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013979 TAG, "Set app " + app.processName +
13980 " oom adj to " + adj);
13981 app.setAdj = adj;
13982 } else {
13983 return false;
13984 }
13985 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013986 if (app.setSchedGroup != app.curSchedGroup) {
13987 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013988 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013989 "Setting process group of " + app.processName
13990 + " to " + app.curSchedGroup);
13991 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013992 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013993 try {
13994 Process.setProcessGroup(app.pid, app.curSchedGroup);
13995 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013996 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013997 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013998 e.printStackTrace();
13999 } finally {
14000 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014001 }
14002 }
14003 if (false) {
14004 if (app.thread != null) {
14005 try {
14006 app.thread.setSchedulingGroup(app.curSchedGroup);
14007 } catch (RemoteException e) {
14008 }
14009 }
14010 }
14011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014012 }
14013
14014 return true;
14015 }
14016
14017 private final HistoryRecord resumedAppLocked() {
14018 HistoryRecord resumedActivity = mResumedActivity;
14019 if (resumedActivity == null || resumedActivity.app == null) {
14020 resumedActivity = mPausingActivity;
14021 if (resumedActivity == null || resumedActivity.app == null) {
14022 resumedActivity = topRunningActivityLocked(null);
14023 }
14024 }
14025 return resumedActivity;
14026 }
14027
14028 private final boolean updateOomAdjLocked(ProcessRecord app) {
14029 final HistoryRecord TOP_ACT = resumedAppLocked();
14030 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14031 int curAdj = app.curAdj;
14032 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14033 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14034
14035 mAdjSeq++;
14036
14037 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14038 if (res) {
14039 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14040 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14041 if (nowHidden != wasHidden) {
14042 // Changed to/from hidden state, so apps after it in the LRU
14043 // list may also be changed.
14044 updateOomAdjLocked();
14045 }
14046 }
14047 return res;
14048 }
14049
14050 private final boolean updateOomAdjLocked() {
14051 boolean didOomAdj = true;
14052 final HistoryRecord TOP_ACT = resumedAppLocked();
14053 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14054
14055 if (false) {
14056 RuntimeException e = new RuntimeException();
14057 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014058 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014059 }
14060
14061 mAdjSeq++;
14062
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014063 // Let's determine how many processes we have running vs.
14064 // how many slots we have for background processes; we may want
14065 // to put multiple processes in a slot of there are enough of
14066 // them.
14067 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14068 int factor = (mLruProcesses.size()-4)/numSlots;
14069 if (factor < 1) factor = 1;
14070 int step = 0;
14071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014072 // First try updating the OOM adjustment for each of the
14073 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014074 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014075 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14076 while (i > 0) {
14077 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014078 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014079 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014080 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014081 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014082 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014083 step++;
14084 if (step >= factor) {
14085 step = 0;
14086 curHiddenAdj++;
14087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014088 }
14089 } else {
14090 didOomAdj = false;
14091 }
14092 }
14093
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014094 // If we return false, we will fall back on killing processes to
14095 // have a fixed limit. Do this if a limit has been requested; else
14096 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014097 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14098 }
14099
14100 private final void trimApplications() {
14101 synchronized (this) {
14102 int i;
14103
14104 // First remove any unused application processes whose package
14105 // has been removed.
14106 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14107 final ProcessRecord app = mRemovedProcesses.get(i);
14108 if (app.activities.size() == 0
14109 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014110 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014111 TAG, "Exiting empty application process "
14112 + app.processName + " ("
14113 + (app.thread != null ? app.thread.asBinder() : null)
14114 + ")\n");
14115 if (app.pid > 0 && app.pid != MY_PID) {
14116 Process.killProcess(app.pid);
14117 } else {
14118 try {
14119 app.thread.scheduleExit();
14120 } catch (Exception e) {
14121 // Ignore exceptions.
14122 }
14123 }
14124 cleanUpApplicationRecordLocked(app, false, -1);
14125 mRemovedProcesses.remove(i);
14126
14127 if (app.persistent) {
14128 if (app.persistent) {
14129 addAppLocked(app.info);
14130 }
14131 }
14132 }
14133 }
14134
14135 // Now try updating the OOM adjustment for each of the
14136 // application processes based on their current state.
14137 // If the setOomAdj() API is not supported, then go with our
14138 // back-up plan...
14139 if (!updateOomAdjLocked()) {
14140
14141 // Count how many processes are running services.
14142 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014143 for (i=mLruProcesses.size()-1; i>=0; i--) {
14144 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014145
14146 if (app.persistent || app.services.size() != 0
14147 || app.curReceiver != null
14148 || app.persistentActivities > 0) {
14149 // Don't count processes holding services against our
14150 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014151 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014152 TAG, "Not trimming app " + app + " with services: "
14153 + app.services);
14154 numServiceProcs++;
14155 }
14156 }
14157
14158 int curMaxProcs = mProcessLimit;
14159 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14160 if (mAlwaysFinishActivities) {
14161 curMaxProcs = 1;
14162 }
14163 curMaxProcs += numServiceProcs;
14164
14165 // Quit as many processes as we can to get down to the desired
14166 // process count. First remove any processes that no longer
14167 // have activites running in them.
14168 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014169 i<mLruProcesses.size()
14170 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014171 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014172 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014173 // Quit an application only if it is not currently
14174 // running any activities.
14175 if (!app.persistent && app.activities.size() == 0
14176 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014177 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014178 TAG, "Exiting empty application process "
14179 + app.processName + " ("
14180 + (app.thread != null ? app.thread.asBinder() : null)
14181 + ")\n");
14182 if (app.pid > 0 && app.pid != MY_PID) {
14183 Process.killProcess(app.pid);
14184 } else {
14185 try {
14186 app.thread.scheduleExit();
14187 } catch (Exception e) {
14188 // Ignore exceptions.
14189 }
14190 }
14191 // todo: For now we assume the application is not buggy
14192 // or evil, and will quit as a result of our request.
14193 // Eventually we need to drive this off of the death
14194 // notification, and kill the process if it takes too long.
14195 cleanUpApplicationRecordLocked(app, false, i);
14196 i--;
14197 }
14198 }
14199
14200 // If we still have too many processes, now from the least
14201 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014202 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014203 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014204 " of " + curMaxProcs + " processes");
14205 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014206 i<mLruProcesses.size()
14207 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014208 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014209 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014210 // Quit the application only if we have a state saved for
14211 // all of its activities.
14212 boolean canQuit = !app.persistent && app.curReceiver == null
14213 && app.services.size() == 0
14214 && app.persistentActivities == 0;
14215 int NUMA = app.activities.size();
14216 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014217 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014218 TAG, "Looking to quit " + app.processName);
14219 for (j=0; j<NUMA && canQuit; j++) {
14220 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014221 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014222 TAG, " " + r.intent.getComponent().flattenToShortString()
14223 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14224 canQuit = (r.haveState || !r.stateNotNeeded)
14225 && !r.visible && r.stopped;
14226 }
14227 if (canQuit) {
14228 // Finish all of the activities, and then the app itself.
14229 for (j=0; j<NUMA; j++) {
14230 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14231 if (!r.finishing) {
14232 destroyActivityLocked(r, false);
14233 }
14234 r.resultTo = null;
14235 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014236 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014237 + app.processName + " ("
14238 + (app.thread != null ? app.thread.asBinder() : null)
14239 + ")\n");
14240 if (app.pid > 0 && app.pid != MY_PID) {
14241 Process.killProcess(app.pid);
14242 } else {
14243 try {
14244 app.thread.scheduleExit();
14245 } catch (Exception e) {
14246 // Ignore exceptions.
14247 }
14248 }
14249 // todo: For now we assume the application is not buggy
14250 // or evil, and will quit as a result of our request.
14251 // Eventually we need to drive this off of the death
14252 // notification, and kill the process if it takes too long.
14253 cleanUpApplicationRecordLocked(app, false, i);
14254 i--;
14255 //dump();
14256 }
14257 }
14258
14259 }
14260
14261 int curMaxActivities = MAX_ACTIVITIES;
14262 if (mAlwaysFinishActivities) {
14263 curMaxActivities = 1;
14264 }
14265
14266 // Finally, if there are too many activities now running, try to
14267 // finish as many as we can to get back down to the limit.
14268 for ( i=0;
14269 i<mLRUActivities.size()
14270 && mLRUActivities.size() > curMaxActivities;
14271 i++) {
14272 final HistoryRecord r
14273 = (HistoryRecord)mLRUActivities.get(i);
14274
14275 // We can finish this one if we have its icicle saved and
14276 // it is not persistent.
14277 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14278 && r.stopped && !r.persistent && !r.finishing) {
14279 final int origSize = mLRUActivities.size();
14280 destroyActivityLocked(r, true);
14281
14282 // This will remove it from the LRU list, so keep
14283 // our index at the same value. Note that this check to
14284 // see if the size changes is just paranoia -- if
14285 // something unexpected happens, we don't want to end up
14286 // in an infinite loop.
14287 if (origSize > mLRUActivities.size()) {
14288 i--;
14289 }
14290 }
14291 }
14292 }
14293 }
14294
14295 /** This method sends the specified signal to each of the persistent apps */
14296 public void signalPersistentProcesses(int sig) throws RemoteException {
14297 if (sig != Process.SIGNAL_USR1) {
14298 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14299 }
14300
14301 synchronized (this) {
14302 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14303 != PackageManager.PERMISSION_GRANTED) {
14304 throw new SecurityException("Requires permission "
14305 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14306 }
14307
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014308 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14309 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014310 if (r.thread != null && r.persistent) {
14311 Process.sendSignal(r.pid, sig);
14312 }
14313 }
14314 }
14315 }
14316
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014317 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014318 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014319
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014320 try {
14321 synchronized (this) {
14322 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14323 // its own permission.
14324 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14325 != PackageManager.PERMISSION_GRANTED) {
14326 throw new SecurityException("Requires permission "
14327 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014328 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014329
14330 if (start && fd == null) {
14331 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014332 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014333
14334 ProcessRecord proc = null;
14335 try {
14336 int pid = Integer.parseInt(process);
14337 synchronized (mPidsSelfLocked) {
14338 proc = mPidsSelfLocked.get(pid);
14339 }
14340 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014341 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014342
14343 if (proc == null) {
14344 HashMap<String, SparseArray<ProcessRecord>> all
14345 = mProcessNames.getMap();
14346 SparseArray<ProcessRecord> procs = all.get(process);
14347 if (procs != null && procs.size() > 0) {
14348 proc = procs.valueAt(0);
14349 }
14350 }
14351
14352 if (proc == null || proc.thread == null) {
14353 throw new IllegalArgumentException("Unknown process: " + process);
14354 }
14355
14356 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14357 if (isSecure) {
14358 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14359 throw new SecurityException("Process not debuggable: " + proc);
14360 }
14361 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014362
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014363 proc.thread.profilerControl(start, path, fd);
14364 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014365 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014366 }
14367 } catch (RemoteException e) {
14368 throw new IllegalStateException("Process disappeared");
14369 } finally {
14370 if (fd != null) {
14371 try {
14372 fd.close();
14373 } catch (IOException e) {
14374 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014375 }
14376 }
14377 }
14378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014379 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14380 public void monitor() {
14381 synchronized (this) { }
14382 }
14383}