blob: a263b23f3233259efbb79c5e8d40a8dd895a7641 [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 Tate181fafa2009-05-14 11:12:14 -070049import android.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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import java.io.PrintWriter;
115import java.lang.IllegalStateException;
116import java.lang.ref.WeakReference;
117import java.util.ArrayList;
118import java.util.HashMap;
119import java.util.HashSet;
120import java.util.Iterator;
121import java.util.List;
122import java.util.Locale;
123import java.util.Map;
124
125public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
126 static final String TAG = "ActivityManager";
127 static final boolean DEBUG = false;
128 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
129 static final boolean DEBUG_SWITCH = localLOGV || false;
130 static final boolean DEBUG_TASKS = localLOGV || false;
131 static final boolean DEBUG_PAUSE = localLOGV || false;
132 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
133 static final boolean DEBUG_TRANSITION = localLOGV || false;
134 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700135 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 static final boolean DEBUG_SERVICE = localLOGV || false;
137 static final boolean DEBUG_VISBILITY = localLOGV || false;
138 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700139 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800140 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700142 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700143 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700144 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean VALIDATE_TOKENS = false;
146 static final boolean SHOW_ACTIVITY_START_TIME = true;
147
148 // Control over CPU and battery monitoring.
149 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
150 static final boolean MONITOR_CPU_USAGE = true;
151 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
152 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
153 static final boolean MONITOR_THREAD_CPU_USAGE = false;
154
Dianne Hackborn1655be42009-05-08 14:29:01 -0700155 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700156 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 private static final String SYSTEM_SECURE = "ro.secure";
159
160 // This is the maximum number of application processes we would like
161 // to have running. Due to the asynchronous nature of things, we can
162 // temporarily go beyond this limit.
163 static final int MAX_PROCESSES = 2;
164
165 // Set to false to leave processes running indefinitely, relying on
166 // the kernel killing them as resources are required.
167 static final boolean ENFORCE_PROCESS_LIMIT = false;
168
169 // This is the maximum number of activities that we would like to have
170 // running at a given time.
171 static final int MAX_ACTIVITIES = 20;
172
173 // Maximum number of recent tasks that we can remember.
174 static final int MAX_RECENT_TASKS = 20;
175
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700176 // Amount of time after a call to stopAppSwitches() during which we will
177 // prevent further untrusted switches from happening.
178 static final long APP_SWITCH_DELAY_TIME = 5*1000;
179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 // How long until we reset a task when the user returns to it. Currently
181 // 30 minutes.
182 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
183
184 // Set to true to disable the icon that is shown while a new activity
185 // is being started.
186 static final boolean SHOW_APP_STARTING_ICON = true;
187
188 // How long we wait until giving up on the last activity to pause. This
189 // is short because it directly impacts the responsiveness of starting the
190 // next activity.
191 static final int PAUSE_TIMEOUT = 500;
192
193 /**
194 * How long we can hold the launch wake lock before giving up.
195 */
196 static final int LAUNCH_TIMEOUT = 10*1000;
197
198 // How long we wait for a launched process to attach to the activity manager
199 // before we decide it's never going to come up for real.
200 static final int PROC_START_TIMEOUT = 10*1000;
201
202 // How long we wait until giving up on the last activity telling us it
203 // is idle.
204 static final int IDLE_TIMEOUT = 10*1000;
205
206 // How long to wait after going idle before forcing apps to GC.
207 static final int GC_TIMEOUT = 5*1000;
208
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700209 // The minimum amount of time between successive GC requests for a process.
210 static final int GC_MIN_INTERVAL = 60*1000;
211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 // How long we wait until giving up on an activity telling us it has
213 // finished destroying itself.
214 static final int DESTROY_TIMEOUT = 10*1000;
215
216 // How long we allow a receiver to run before giving up on it.
217 static final int BROADCAST_TIMEOUT = 10*1000;
218
219 // How long we wait for a service to finish executing.
220 static final int SERVICE_TIMEOUT = 20*1000;
221
222 // How long a service needs to be running until restarting its process
223 // is no longer considered to be a relaunch of the service.
224 static final int SERVICE_RESTART_DURATION = 5*1000;
225
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700226 // How long a service needs to be running until it will start back at
227 // SERVICE_RESTART_DURATION after being killed.
228 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
229
230 // Multiplying factor to increase restart duration time by, for each time
231 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
232 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
233
234 // The minimum amount of time between restarting services that we allow.
235 // That is, when multiple services are restarting, we won't allow each
236 // to restart less than this amount of time from the last one.
237 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 // Maximum amount of time for there to be no activity on a service before
240 // we consider it non-essential and allow its process to go on the
241 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700242 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243
244 // How long we wait until we timeout on key dispatching.
245 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
246
247 // The minimum time we allow between crashes, for us to consider this
248 // application to be bad and stop and its services and reject broadcasts.
249 static final int MIN_CRASH_INTERVAL = 60*1000;
250
251 // How long we wait until we timeout on key dispatching during instrumentation.
252 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
253
254 // OOM adjustments for processes in various states:
255
256 // This is a process without anything currently running in it. Definitely
257 // the first to go! Value set in system/rootdir/init.rc on startup.
258 // This value is initalized in the constructor, careful when refering to
259 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800260 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261
262 // This is a process only hosting activities that are not visible,
263 // so it can be killed without any disruption. Value set in
264 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800265 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 static int HIDDEN_APP_MIN_ADJ;
267
The Android Open Source Project4df24232009-03-05 14:34:35 -0800268 // This is a process holding the home application -- we want to try
269 // avoiding killing it, even if it would normally be in the background,
270 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800271 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800272
Christopher Tate6fa95972009-06-05 18:43:55 -0700273 // This is a process currently hosting a backup operation. Killing it
274 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 // This is a process holding a secondary server -- killing it will not
278 // have much of an impact as far as the user is concerned. Value set in
279 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800280 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281
282 // This is a process only hosting activities that are visible to the
283 // user, so we'd prefer they don't disappear. Value set in
284 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800285 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286
287 // This is the process running the current foreground app. We'd really
288 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
291 // This is a process running a core server, such as telephony. Definitely
292 // don't want to kill it, but doing so is not completely fatal.
293 static final int CORE_SERVER_ADJ = -12;
294
295 // The system process runs at the default adjustment.
296 static final int SYSTEM_ADJ = -16;
297
298 // Memory pages are 4K.
299 static final int PAGE_SIZE = 4*1024;
300
301 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800302 static final int EMPTY_APP_MEM;
303 static final int HIDDEN_APP_MEM;
304 static final int HOME_APP_MEM;
305 static final int BACKUP_APP_MEM;
306 static final int SECONDARY_SERVER_MEM;
307 static final int VISIBLE_APP_MEM;
308 static final int FOREGROUND_APP_MEM;
309
310 // The minimum number of hidden apps we want to be able to keep around,
311 // without empty apps being able to push them out of memory.
312 static final int MIN_HIDDEN_APPS = 2;
313
314 // We put empty content processes after any hidden processes that have
315 // been idle for less than 30 seconds.
316 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
317
318 // We put empty content processes after any hidden processes that have
319 // been idle for less than 60 seconds.
320 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
321
322 static {
323 // These values are set in system/rootdir/init.rc on startup.
324 FOREGROUND_APP_ADJ =
325 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
326 VISIBLE_APP_ADJ =
327 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
328 SECONDARY_SERVER_ADJ =
329 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
330 BACKUP_APP_ADJ =
331 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
332 HOME_APP_ADJ =
333 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
334 HIDDEN_APP_MIN_ADJ =
335 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
336 EMPTY_APP_ADJ =
337 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
338 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
339 FOREGROUND_APP_MEM =
340 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
341 VISIBLE_APP_MEM =
342 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
343 SECONDARY_SERVER_MEM =
344 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
345 BACKUP_APP_MEM =
346 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
347 HOME_APP_MEM =
348 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
349 HIDDEN_APP_MEM =
350 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
351 EMPTY_APP_MEM =
352 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354
Dan Egnor42471dd2010-01-07 17:25:22 -0800355 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356
357 static final String[] EMPTY_STRING_ARRAY = new String[0];
358
359 enum ActivityState {
360 INITIALIZING,
361 RESUMED,
362 PAUSING,
363 PAUSED,
364 STOPPING,
365 STOPPED,
366 FINISHING,
367 DESTROYING,
368 DESTROYED
369 }
370
371 /**
372 * The back history of all previous (and possibly still
373 * running) activities. It contains HistoryRecord objects.
374 */
375 final ArrayList mHistory = new ArrayList();
376
377 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700378 * Description of a request to start a new activity, which has been held
379 * due to app switches being disabled.
380 */
381 class PendingActivityLaunch {
382 HistoryRecord r;
383 HistoryRecord sourceRecord;
384 Uri[] grantedUriPermissions;
385 int grantedMode;
386 boolean onlyIfNeeded;
387 }
388
389 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
390 = new ArrayList<PendingActivityLaunch>();
391
392 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800393 * List of people waiting to find out about the next launched activity.
394 */
395 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
396 = new ArrayList<IActivityManager.WaitResult>();
397
398 /**
399 * List of people waiting to find out about the next visible activity.
400 */
401 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
402 = new ArrayList<IActivityManager.WaitResult>();
403
404 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 * List of all active broadcasts that are to be executed immediately
406 * (without waiting for another broadcast to finish). Currently this only
407 * contains broadcasts to registered receivers, to avoid spinning up
408 * a bunch of processes to execute IntentReceiver components.
409 */
410 final ArrayList<BroadcastRecord> mParallelBroadcasts
411 = new ArrayList<BroadcastRecord>();
412
413 /**
414 * List of all active broadcasts that are to be executed one at a time.
415 * The object at the top of the list is the currently activity broadcasts;
416 * those after it are waiting for the top to finish..
417 */
418 final ArrayList<BroadcastRecord> mOrderedBroadcasts
419 = new ArrayList<BroadcastRecord>();
420
421 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800422 * Historical data of past broadcasts, for debugging.
423 */
424 static final int MAX_BROADCAST_HISTORY = 100;
425 final BroadcastRecord[] mBroadcastHistory
426 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
427
428 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 * Set when we current have a BROADCAST_INTENT_MSG in flight.
430 */
431 boolean mBroadcastsScheduled = false;
432
433 /**
434 * Set to indicate whether to issue an onUserLeaving callback when a
435 * newly launched activity is being brought in front of us.
436 */
437 boolean mUserLeaving = false;
438
439 /**
440 * When we are in the process of pausing an activity, before starting the
441 * next one, this variable holds the activity that is currently being paused.
442 */
443 HistoryRecord mPausingActivity = null;
444
445 /**
446 * Current activity that is resumed, or null if there is none.
447 */
448 HistoryRecord mResumedActivity = null;
449
450 /**
451 * Activity we have told the window manager to have key focus.
452 */
453 HistoryRecord mFocusedActivity = null;
454
455 /**
456 * This is the last activity that we put into the paused state. This is
457 * used to determine if we need to do an activity transition while sleeping,
458 * when we normally hold the top activity paused.
459 */
460 HistoryRecord mLastPausedActivity = null;
461
462 /**
463 * List of activities that are waiting for a new activity
464 * to become visible before completing whatever operation they are
465 * supposed to do.
466 */
467 final ArrayList mWaitingVisibleActivities = new ArrayList();
468
469 /**
470 * List of activities that are ready to be stopped, but waiting
471 * for the next activity to settle down before doing so. It contains
472 * HistoryRecord objects.
473 */
474 final ArrayList<HistoryRecord> mStoppingActivities
475 = new ArrayList<HistoryRecord>();
476
477 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700478 * Animations that for the current transition have requested not to
479 * be considered for the transition animation.
480 */
481 final ArrayList<HistoryRecord> mNoAnimActivities
482 = new ArrayList<HistoryRecord>();
483
484 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 * List of intents that were used to start the most recent tasks.
486 */
487 final ArrayList<TaskRecord> mRecentTasks
488 = new ArrayList<TaskRecord>();
489
490 /**
491 * List of activities that are ready to be finished, but waiting
492 * for the previous activity to settle down before doing so. It contains
493 * HistoryRecord objects.
494 */
495 final ArrayList mFinishingActivities = new ArrayList();
496
497 /**
498 * All of the applications we currently have running organized by name.
499 * The keys are strings of the application package name (as
500 * returned by the package manager), and the keys are ApplicationRecord
501 * objects.
502 */
503 final ProcessMap<ProcessRecord> mProcessNames
504 = new ProcessMap<ProcessRecord>();
505
506 /**
507 * The last time that various processes have crashed.
508 */
509 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
510
511 /**
512 * Set of applications that we consider to be bad, and will reject
513 * incoming broadcasts from (which the user has no control over).
514 * Processes are added to this set when they have crashed twice within
515 * a minimum amount of time; they are removed from it when they are
516 * later restarted (hopefully due to some user action). The value is the
517 * time it was added to the list.
518 */
519 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
520
521 /**
522 * All of the processes we currently have running organized by pid.
523 * The keys are the pid running the application.
524 *
525 * <p>NOTE: This object is protected by its own lock, NOT the global
526 * activity manager lock!
527 */
528 final SparseArray<ProcessRecord> mPidsSelfLocked
529 = new SparseArray<ProcessRecord>();
530
531 /**
532 * All of the processes that have been forced to be foreground. The key
533 * is the pid of the caller who requested it (we hold a death
534 * link on it).
535 */
536 abstract class ForegroundToken implements IBinder.DeathRecipient {
537 int pid;
538 IBinder token;
539 }
540 final SparseArray<ForegroundToken> mForegroundProcesses
541 = new SparseArray<ForegroundToken>();
542
543 /**
544 * List of records for processes that someone had tried to start before the
545 * system was ready. We don't start them at that point, but ensure they
546 * are started by the time booting is complete.
547 */
548 final ArrayList<ProcessRecord> mProcessesOnHold
549 = new ArrayList<ProcessRecord>();
550
551 /**
552 * List of records for processes that we have started and are waiting
553 * for them to call back. This is really only needed when running in
554 * single processes mode, in which case we do not have a unique pid for
555 * each process.
556 */
557 final ArrayList<ProcessRecord> mStartingProcesses
558 = new ArrayList<ProcessRecord>();
559
560 /**
561 * List of persistent applications that are in the process
562 * of being started.
563 */
564 final ArrayList<ProcessRecord> mPersistentStartingProcesses
565 = new ArrayList<ProcessRecord>();
566
567 /**
568 * Processes that are being forcibly torn down.
569 */
570 final ArrayList<ProcessRecord> mRemovedProcesses
571 = new ArrayList<ProcessRecord>();
572
573 /**
574 * List of running applications, sorted by recent usage.
575 * The first entry in the list is the least recently used.
576 * It contains ApplicationRecord objects. This list does NOT include
577 * any persistent application records (since we never want to exit them).
578 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800579 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 = new ArrayList<ProcessRecord>();
581
582 /**
583 * List of processes that should gc as soon as things are idle.
584 */
585 final ArrayList<ProcessRecord> mProcessesToGc
586 = new ArrayList<ProcessRecord>();
587
588 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800589 * This is the process holding what we currently consider to be
590 * the "home" activity.
591 */
592 private ProcessRecord mHomeProcess;
593
594 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 * List of running activities, sorted by recent usage.
596 * The first entry in the list is the least recently used.
597 * It contains HistoryRecord objects.
598 */
599 private final ArrayList mLRUActivities = new ArrayList();
600
601 /**
602 * Set of PendingResultRecord objects that are currently active.
603 */
604 final HashSet mPendingResultRecords = new HashSet();
605
606 /**
607 * Set of IntentSenderRecord objects that are currently active.
608 */
609 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
610 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
611
612 /**
613 * Intent broadcast that we have tried to start, but are
614 * waiting for its application's process to be created. We only
615 * need one (instead of a list) because we always process broadcasts
616 * one at a time, so no others can be started while waiting for this
617 * one.
618 */
619 BroadcastRecord mPendingBroadcast = null;
620
621 /**
622 * Keeps track of all IIntentReceivers that have been registered for
623 * broadcasts. Hash keys are the receiver IBinder, hash value is
624 * a ReceiverList.
625 */
626 final HashMap mRegisteredReceivers = new HashMap();
627
628 /**
629 * Resolver for broadcast intents to registered receivers.
630 * Holds BroadcastFilter (subclass of IntentFilter).
631 */
632 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
633 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
634 @Override
635 protected boolean allowFilterResult(
636 BroadcastFilter filter, List<BroadcastFilter> dest) {
637 IBinder target = filter.receiverList.receiver.asBinder();
638 for (int i=dest.size()-1; i>=0; i--) {
639 if (dest.get(i).receiverList.receiver.asBinder() == target) {
640 return false;
641 }
642 }
643 return true;
644 }
645 };
646
647 /**
648 * State of all active sticky broadcasts. Keys are the action of the
649 * sticky Intent, values are an ArrayList of all broadcasted intents with
650 * that action (which should usually be one).
651 */
652 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
653 new HashMap<String, ArrayList<Intent>>();
654
655 /**
656 * All currently running services.
657 */
658 final HashMap<ComponentName, ServiceRecord> mServices =
659 new HashMap<ComponentName, ServiceRecord>();
660
661 /**
662 * All currently running services indexed by the Intent used to start them.
663 */
664 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
665 new HashMap<Intent.FilterComparison, ServiceRecord>();
666
667 /**
668 * All currently bound service connections. Keys are the IBinder of
669 * the client's IServiceConnection.
670 */
671 final HashMap<IBinder, ConnectionRecord> mServiceConnections
672 = new HashMap<IBinder, ConnectionRecord>();
673
674 /**
675 * List of services that we have been asked to start,
676 * but haven't yet been able to. It is used to hold start requests
677 * while waiting for their corresponding application thread to get
678 * going.
679 */
680 final ArrayList<ServiceRecord> mPendingServices
681 = new ArrayList<ServiceRecord>();
682
683 /**
684 * List of services that are scheduled to restart following a crash.
685 */
686 final ArrayList<ServiceRecord> mRestartingServices
687 = new ArrayList<ServiceRecord>();
688
689 /**
690 * List of services that are in the process of being stopped.
691 */
692 final ArrayList<ServiceRecord> mStoppingServices
693 = new ArrayList<ServiceRecord>();
694
695 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700696 * Backup/restore process management
697 */
698 String mBackupAppName = null;
699 BackupRecord mBackupTarget = null;
700
701 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 * List of PendingThumbnailsRecord objects of clients who are still
703 * waiting to receive all of the thumbnails for a task.
704 */
705 final ArrayList mPendingThumbnails = new ArrayList();
706
707 /**
708 * List of HistoryRecord objects that have been finished and must
709 * still report back to a pending thumbnail receiver.
710 */
711 final ArrayList mCancelledThumbnails = new ArrayList();
712
713 /**
714 * All of the currently running global content providers. Keys are a
715 * string containing the provider name and values are a
716 * ContentProviderRecord object containing the data about it. Note
717 * that a single provider may be published under multiple names, so
718 * there may be multiple entries here for a single one in mProvidersByClass.
719 */
720 final HashMap mProvidersByName = new HashMap();
721
722 /**
723 * All of the currently running global content providers. Keys are a
724 * string containing the provider's implementation class and values are a
725 * ContentProviderRecord object containing the data about it.
726 */
727 final HashMap mProvidersByClass = new HashMap();
728
729 /**
730 * List of content providers who have clients waiting for them. The
731 * application is currently being launched and the provider will be
732 * removed from this list once it is published.
733 */
734 final ArrayList mLaunchingProviders = new ArrayList();
735
736 /**
737 * Global set of specific Uri permissions that have been granted.
738 */
739 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
740 = new SparseArray<HashMap<Uri, UriPermission>>();
741
742 /**
743 * Thread-local storage used to carry caller permissions over through
744 * indirect content-provider access.
745 * @see #ActivityManagerService.openContentUri()
746 */
747 private class Identity {
748 public int pid;
749 public int uid;
750
751 Identity(int _pid, int _uid) {
752 pid = _pid;
753 uid = _uid;
754 }
755 }
756 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
757
758 /**
759 * All information we have collected about the runtime performance of
760 * any user id that can impact battery performance.
761 */
762 final BatteryStatsService mBatteryStatsService;
763
764 /**
765 * information about component usage
766 */
767 final UsageStatsService mUsageStatsService;
768
769 /**
770 * Current configuration information. HistoryRecord objects are given
771 * a reference to this object to indicate which configuration they are
772 * currently running in, so this object must be kept immutable.
773 */
774 Configuration mConfiguration = new Configuration();
775
776 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800777 * Current sequencing integer of the configuration, for skipping old
778 * configurations.
779 */
780 int mConfigurationSeq = 0;
781
782 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700783 * Hardware-reported OpenGLES version.
784 */
785 final int GL_ES_VERSION;
786
787 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 * List of initialization arguments to pass to all processes when binding applications to them.
789 * For example, references to the commonly used services.
790 */
791 HashMap<String, IBinder> mAppBindArgs;
792
793 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700794 * Temporary to avoid allocations. Protected by main lock.
795 */
796 final StringBuilder mStringBuilder = new StringBuilder(256);
797
798 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 * Used to control how we initialize the service.
800 */
801 boolean mStartRunning = false;
802 ComponentName mTopComponent;
803 String mTopAction;
804 String mTopData;
805 boolean mSystemReady = false;
806 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700807 boolean mWaitingUpdate = false;
808 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809
810 Context mContext;
811
812 int mFactoryTest;
813
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700814 boolean mCheckedForSetup;
815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700817 * The time at which we will allow normal application switches again,
818 * after a call to {@link #stopAppSwitches()}.
819 */
820 long mAppSwitchesAllowedTime;
821
822 /**
823 * This is set to true after the first switch after mAppSwitchesAllowedTime
824 * is set; any switches after that will clear the time.
825 */
826 boolean mDidAppSwitch;
827
828 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 * Set while we are wanting to sleep, to prevent any
830 * activities from being started/resumed.
831 */
832 boolean mSleeping = false;
833
834 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700835 * Set if we are shutting down the system, similar to sleeping.
836 */
837 boolean mShuttingDown = false;
838
839 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 * Set when the system is going to sleep, until we have
841 * successfully paused the current activity and released our wake lock.
842 * At that point the system is allowed to actually sleep.
843 */
844 PowerManager.WakeLock mGoingToSleep;
845
846 /**
847 * We don't want to allow the device to go to sleep while in the process
848 * of launching an activity. This is primarily to allow alarm intent
849 * receivers to launch an activity and get that to run before the device
850 * goes back to sleep.
851 */
852 PowerManager.WakeLock mLaunchingActivity;
853
854 /**
855 * Task identifier that activities are currently being started
856 * in. Incremented each time a new task is created.
857 * todo: Replace this with a TokenSpace class that generates non-repeating
858 * integers that won't wrap.
859 */
860 int mCurTask = 1;
861
862 /**
863 * Current sequence id for oom_adj computation traversal.
864 */
865 int mAdjSeq = 0;
866
867 /**
868 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
869 * is set, indicating the user wants processes started in such a way
870 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
871 * running in each process (thus no pre-initialized process, etc).
872 */
873 boolean mSimpleProcessManagement = false;
874
875 /**
876 * System monitoring: number of processes that died since the last
877 * N procs were started.
878 */
879 int[] mProcDeaths = new int[20];
880
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700881 /**
882 * This is set if we had to do a delayed dexopt of an app before launching
883 * it, to increasing the ANR timeouts in that case.
884 */
885 boolean mDidDexOpt;
886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 String mDebugApp = null;
888 boolean mWaitForDebugger = false;
889 boolean mDebugTransient = false;
890 String mOrigDebugApp = null;
891 boolean mOrigWaitForDebugger = false;
892 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700893 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700895 final RemoteCallbackList<IActivityWatcher> mWatchers
896 = new RemoteCallbackList<IActivityWatcher>();
897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 /**
899 * Callback of last caller to {@link #requestPss}.
900 */
901 Runnable mRequestPssCallback;
902
903 /**
904 * Remaining processes for which we are waiting results from the last
905 * call to {@link #requestPss}.
906 */
907 final ArrayList<ProcessRecord> mRequestPssList
908 = new ArrayList<ProcessRecord>();
909
910 /**
911 * Runtime statistics collection thread. This object's lock is used to
912 * protect all related state.
913 */
914 final Thread mProcessStatsThread;
915
916 /**
917 * Used to collect process stats when showing not responding dialog.
918 * Protected by mProcessStatsThread.
919 */
920 final ProcessStats mProcessStats = new ProcessStats(
921 MONITOR_THREAD_CPU_USAGE);
922 long mLastCpuTime = 0;
923 long mLastWriteTime = 0;
924
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700925 long mInitialStartTime = 0;
926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 /**
928 * Set to true after the system has finished booting.
929 */
930 boolean mBooted = false;
931
932 int mProcessLimit = 0;
933
934 WindowManagerService mWindowManager;
935
936 static ActivityManagerService mSelf;
937 static ActivityThread mSystemThread;
938
939 private final class AppDeathRecipient implements IBinder.DeathRecipient {
940 final ProcessRecord mApp;
941 final int mPid;
942 final IApplicationThread mAppThread;
943
944 AppDeathRecipient(ProcessRecord app, int pid,
945 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800946 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 TAG, "New death recipient " + this
948 + " for thread " + thread.asBinder());
949 mApp = app;
950 mPid = pid;
951 mAppThread = thread;
952 }
953
954 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800955 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 TAG, "Death received in " + this
957 + " for thread " + mAppThread.asBinder());
958 removeRequestedPss(mApp);
959 synchronized(ActivityManagerService.this) {
960 appDiedLocked(mApp, mPid, mAppThread);
961 }
962 }
963 }
964
965 static final int SHOW_ERROR_MSG = 1;
966 static final int SHOW_NOT_RESPONDING_MSG = 2;
967 static final int SHOW_FACTORY_ERROR_MSG = 3;
968 static final int UPDATE_CONFIGURATION_MSG = 4;
969 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
970 static final int WAIT_FOR_DEBUGGER_MSG = 6;
971 static final int BROADCAST_INTENT_MSG = 7;
972 static final int BROADCAST_TIMEOUT_MSG = 8;
973 static final int PAUSE_TIMEOUT_MSG = 9;
974 static final int IDLE_TIMEOUT_MSG = 10;
975 static final int IDLE_NOW_MSG = 11;
976 static final int SERVICE_TIMEOUT_MSG = 12;
977 static final int UPDATE_TIME_ZONE = 13;
978 static final int SHOW_UID_ERROR_MSG = 14;
979 static final int IM_FEELING_LUCKY_MSG = 15;
980 static final int LAUNCH_TIMEOUT_MSG = 16;
981 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 static final int RESUME_TOP_ACTIVITY_MSG = 19;
983 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700984 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700985 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800986 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987
988 AlertDialog mUidAlert;
989
990 final Handler mHandler = new Handler() {
991 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800992 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 //}
994
995 public void handleMessage(Message msg) {
996 switch (msg.what) {
997 case SHOW_ERROR_MSG: {
998 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 synchronized (ActivityManagerService.this) {
1000 ProcessRecord proc = (ProcessRecord)data.get("app");
1001 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001002 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 return;
1004 }
1005 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001006 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001007 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001008 d.show();
1009 proc.crashDialog = d;
1010 } else {
1011 // The device is asleep, so just pretend that the user
1012 // saw a crash dialog and hit "force quit".
1013 res.set(0);
1014 }
1015 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001016
1017 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } break;
1019 case SHOW_NOT_RESPONDING_MSG: {
1020 synchronized (ActivityManagerService.this) {
1021 HashMap data = (HashMap) msg.obj;
1022 ProcessRecord proc = (ProcessRecord)data.get("app");
1023 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001024 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 return;
1026 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001027
1028 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1029 null, null, 0, null, null, null,
1030 false, false, MY_PID, Process.SYSTEM_UID);
1031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1033 mContext, proc, (HistoryRecord)data.get("activity"));
1034 d.show();
1035 proc.anrDialog = d;
1036 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001037
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001038 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 } break;
1040 case SHOW_FACTORY_ERROR_MSG: {
1041 Dialog d = new FactoryErrorDialog(
1042 mContext, msg.getData().getCharSequence("msg"));
1043 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001044 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 } break;
1046 case UPDATE_CONFIGURATION_MSG: {
1047 final ContentResolver resolver = mContext.getContentResolver();
1048 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1049 } break;
1050 case GC_BACKGROUND_PROCESSES_MSG: {
1051 synchronized (ActivityManagerService.this) {
1052 performAppGcsIfAppropriateLocked();
1053 }
1054 } break;
1055 case WAIT_FOR_DEBUGGER_MSG: {
1056 synchronized (ActivityManagerService.this) {
1057 ProcessRecord app = (ProcessRecord)msg.obj;
1058 if (msg.arg1 != 0) {
1059 if (!app.waitedForDebugger) {
1060 Dialog d = new AppWaitingForDebuggerDialog(
1061 ActivityManagerService.this,
1062 mContext, app);
1063 app.waitDialog = d;
1064 app.waitedForDebugger = true;
1065 d.show();
1066 }
1067 } else {
1068 if (app.waitDialog != null) {
1069 app.waitDialog.dismiss();
1070 app.waitDialog = null;
1071 }
1072 }
1073 }
1074 } break;
1075 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001076 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 TAG, "Received BROADCAST_INTENT_MSG");
1078 processNextBroadcast(true);
1079 } break;
1080 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001081 if (mDidDexOpt) {
1082 mDidDexOpt = false;
1083 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1084 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1085 return;
1086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 broadcastTimeout();
1088 } break;
1089 case PAUSE_TIMEOUT_MSG: {
1090 IBinder token = (IBinder)msg.obj;
1091 // We don't at this point know if the activity is fullscreen,
1092 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001093 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 activityPaused(token, null, true);
1095 } break;
1096 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001097 if (mDidDexOpt) {
1098 mDidDexOpt = false;
1099 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1100 nmsg.obj = msg.obj;
1101 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1102 return;
1103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 // We don't at this point know if the activity is fullscreen,
1105 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001106 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001107 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001108 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 } break;
1110 case DESTROY_TIMEOUT_MSG: {
1111 IBinder token = (IBinder)msg.obj;
1112 // We don't at this point know if the activity is fullscreen,
1113 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001114 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 activityDestroyed(token);
1116 } break;
1117 case IDLE_NOW_MSG: {
1118 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001119 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 } break;
1121 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001122 if (mDidDexOpt) {
1123 mDidDexOpt = false;
1124 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1125 nmsg.obj = msg.obj;
1126 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1127 return;
1128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 serviceTimeout((ProcessRecord)msg.obj);
1130 } break;
1131 case UPDATE_TIME_ZONE: {
1132 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001133 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1134 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 if (r.thread != null) {
1136 try {
1137 r.thread.updateTimeZone();
1138 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001139 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 }
1141 }
1142 }
1143 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001144 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 case SHOW_UID_ERROR_MSG: {
1146 // XXX This is a temporary dialog, no need to localize.
1147 AlertDialog d = new BaseErrorDialog(mContext);
1148 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1149 d.setCancelable(false);
1150 d.setTitle("System UIDs Inconsistent");
1151 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1152 d.setButton("I'm Feeling Lucky",
1153 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1154 mUidAlert = d;
1155 d.show();
1156 } break;
1157 case IM_FEELING_LUCKY_MSG: {
1158 if (mUidAlert != null) {
1159 mUidAlert.dismiss();
1160 mUidAlert = null;
1161 }
1162 } break;
1163 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001164 if (mDidDexOpt) {
1165 mDidDexOpt = false;
1166 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1167 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1168 return;
1169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 synchronized (ActivityManagerService.this) {
1171 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001172 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 mLaunchingActivity.release();
1174 }
1175 }
1176 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 case RESUME_TOP_ACTIVITY_MSG: {
1178 synchronized (ActivityManagerService.this) {
1179 resumeTopActivityLocked(null);
1180 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001181 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001183 if (mDidDexOpt) {
1184 mDidDexOpt = false;
1185 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1186 nmsg.obj = msg.obj;
1187 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1188 return;
1189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 ProcessRecord app = (ProcessRecord)msg.obj;
1191 synchronized (ActivityManagerService.this) {
1192 processStartTimedOutLocked(app);
1193 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001194 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001195 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1196 synchronized (ActivityManagerService.this) {
1197 doPendingActivityLaunchesLocked(true);
1198 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001199 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001200 case KILL_APPLICATION_MSG: {
1201 synchronized (ActivityManagerService.this) {
1202 int uid = msg.arg1;
1203 boolean restart = (msg.arg2 == 1);
1204 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001205 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001206 }
1207 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001208 case FINALIZE_PENDING_INTENT_MSG: {
1209 ((PendingIntentRecord)msg.obj).completeFinalize();
1210 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 }
1212 }
1213 };
1214
1215 public static void setSystemProcess() {
1216 try {
1217 ActivityManagerService m = mSelf;
1218
1219 ServiceManager.addService("activity", m);
1220 ServiceManager.addService("meminfo", new MemBinder(m));
1221 if (MONITOR_CPU_USAGE) {
1222 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 ServiceManager.addService("permission", new PermissionController(m));
1225
1226 ApplicationInfo info =
1227 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001228 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001229 mSystemThread.installSystemApplicationInfo(info);
1230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 synchronized (mSelf) {
1232 ProcessRecord app = mSelf.newProcessRecordLocked(
1233 mSystemThread.getApplicationThread(), info,
1234 info.processName);
1235 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001236 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 app.maxAdj = SYSTEM_ADJ;
1238 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1239 synchronized (mSelf.mPidsSelfLocked) {
1240 mSelf.mPidsSelfLocked.put(app.pid, app);
1241 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001242 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 }
1244 } catch (PackageManager.NameNotFoundException e) {
1245 throw new RuntimeException(
1246 "Unable to find android system package", e);
1247 }
1248 }
1249
1250 public void setWindowManager(WindowManagerService wm) {
1251 mWindowManager = wm;
1252 }
1253
1254 public static final Context main(int factoryTest) {
1255 AThread thr = new AThread();
1256 thr.start();
1257
1258 synchronized (thr) {
1259 while (thr.mService == null) {
1260 try {
1261 thr.wait();
1262 } catch (InterruptedException e) {
1263 }
1264 }
1265 }
1266
1267 ActivityManagerService m = thr.mService;
1268 mSelf = m;
1269 ActivityThread at = ActivityThread.systemMain();
1270 mSystemThread = at;
1271 Context context = at.getSystemContext();
1272 m.mContext = context;
1273 m.mFactoryTest = factoryTest;
1274 PowerManager pm =
1275 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1276 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1277 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1278 m.mLaunchingActivity.setReferenceCounted(false);
1279
1280 m.mBatteryStatsService.publish(context);
1281 m.mUsageStatsService.publish(context);
1282
1283 synchronized (thr) {
1284 thr.mReady = true;
1285 thr.notifyAll();
1286 }
1287
1288 m.startRunning(null, null, null, null);
1289
1290 return context;
1291 }
1292
1293 public static ActivityManagerService self() {
1294 return mSelf;
1295 }
1296
1297 static class AThread extends Thread {
1298 ActivityManagerService mService;
1299 boolean mReady = false;
1300
1301 public AThread() {
1302 super("ActivityManager");
1303 }
1304
1305 public void run() {
1306 Looper.prepare();
1307
1308 android.os.Process.setThreadPriority(
1309 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1310
1311 ActivityManagerService m = new ActivityManagerService();
1312
1313 synchronized (this) {
1314 mService = m;
1315 notifyAll();
1316 }
1317
1318 synchronized (this) {
1319 while (!mReady) {
1320 try {
1321 wait();
1322 } catch (InterruptedException e) {
1323 }
1324 }
1325 }
1326
1327 Looper.loop();
1328 }
1329 }
1330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 static class MemBinder extends Binder {
1332 ActivityManagerService mActivityManagerService;
1333 MemBinder(ActivityManagerService activityManagerService) {
1334 mActivityManagerService = activityManagerService;
1335 }
1336
1337 @Override
1338 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1339 ActivityManagerService service = mActivityManagerService;
1340 ArrayList<ProcessRecord> procs;
1341 synchronized (mActivityManagerService) {
1342 if (args != null && args.length > 0
1343 && args[0].charAt(0) != '-') {
1344 procs = new ArrayList<ProcessRecord>();
1345 int pid = -1;
1346 try {
1347 pid = Integer.parseInt(args[0]);
1348 } catch (NumberFormatException e) {
1349
1350 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001351 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1352 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 if (proc.pid == pid) {
1354 procs.add(proc);
1355 } else if (proc.processName.equals(args[0])) {
1356 procs.add(proc);
1357 }
1358 }
1359 if (procs.size() <= 0) {
1360 pw.println("No process found for: " + args[0]);
1361 return;
1362 }
1363 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001364 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 }
1366 }
1367 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1368 }
1369 }
1370
1371 static class CpuBinder extends Binder {
1372 ActivityManagerService mActivityManagerService;
1373 CpuBinder(ActivityManagerService activityManagerService) {
1374 mActivityManagerService = activityManagerService;
1375 }
1376
1377 @Override
1378 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1379 synchronized (mActivityManagerService.mProcessStatsThread) {
1380 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1381 }
1382 }
1383 }
1384
1385 private ActivityManagerService() {
1386 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1387 if (v != null && Integer.getInteger(v) != 0) {
1388 mSimpleProcessManagement = true;
1389 }
1390 v = System.getenv("ANDROID_DEBUG_APP");
1391 if (v != null) {
1392 mSimpleProcessManagement = true;
1393 }
1394
Joe Onorato8a9b2202010-02-26 18:56:32 -08001395 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 File dataDir = Environment.getDataDirectory();
1398 File systemDir = new File(dataDir, "system");
1399 systemDir.mkdirs();
1400 mBatteryStatsService = new BatteryStatsService(new File(
1401 systemDir, "batterystats.bin").toString());
1402 mBatteryStatsService.getActiveStatistics().readLocked();
1403 mBatteryStatsService.getActiveStatistics().writeLocked();
1404
1405 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001406 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407
Jack Palevichb90d28c2009-07-22 15:35:24 -07001408 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1409 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1410
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001411 mConfiguration.setToDefaults();
1412 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 mProcessStats.init();
1414
1415 // Add ourself to the Watchdog monitors.
1416 Watchdog.getInstance().addMonitor(this);
1417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 mProcessStatsThread = new Thread("ProcessStats") {
1419 public void run() {
1420 while (true) {
1421 try {
1422 try {
1423 synchronized(this) {
1424 final long now = SystemClock.uptimeMillis();
1425 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1426 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001427 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 // + ", write delay=" + nextWriteDelay);
1429 if (nextWriteDelay < nextCpuDelay) {
1430 nextCpuDelay = nextWriteDelay;
1431 }
1432 if (nextCpuDelay > 0) {
1433 this.wait(nextCpuDelay);
1434 }
1435 }
1436 } catch (InterruptedException e) {
1437 }
1438
1439 updateCpuStatsNow();
1440 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001441 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 }
1443 }
1444 }
1445 };
1446 mProcessStatsThread.start();
1447 }
1448
1449 @Override
1450 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1451 throws RemoteException {
1452 try {
1453 return super.onTransact(code, data, reply, flags);
1454 } catch (RuntimeException e) {
1455 // The activity manager only throws security exceptions, so let's
1456 // log all others.
1457 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001458 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 }
1460 throw e;
1461 }
1462 }
1463
1464 void updateCpuStats() {
1465 synchronized (mProcessStatsThread) {
1466 final long now = SystemClock.uptimeMillis();
1467 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1468 mProcessStatsThread.notify();
1469 }
1470 }
1471 }
1472
1473 void updateCpuStatsNow() {
1474 synchronized (mProcessStatsThread) {
1475 final long now = SystemClock.uptimeMillis();
1476 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 if (MONITOR_CPU_USAGE &&
1479 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1480 mLastCpuTime = now;
1481 haveNewCpuStats = true;
1482 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001483 //Slog.i(TAG, mProcessStats.printCurrentState());
1484 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 // + mProcessStats.getTotalCpuPercent() + "%");
1486
Joe Onorato8a9b2202010-02-26 18:56:32 -08001487 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 if ("true".equals(SystemProperties.get("events.cpu"))) {
1489 int user = mProcessStats.getLastUserTime();
1490 int system = mProcessStats.getLastSystemTime();
1491 int iowait = mProcessStats.getLastIoWaitTime();
1492 int irq = mProcessStats.getLastIrqTime();
1493 int softIrq = mProcessStats.getLastSoftIrqTime();
1494 int idle = mProcessStats.getLastIdleTime();
1495
1496 int total = user + system + iowait + irq + softIrq + idle;
1497 if (total == 0) total = 1;
1498
Doug Zongker2bec3d42009-12-04 12:52:44 -08001499 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 ((user+system+iowait+irq+softIrq) * 100) / total,
1501 (user * 100) / total,
1502 (system * 100) / total,
1503 (iowait * 100) / total,
1504 (irq * 100) / total,
1505 (softIrq * 100) / total);
1506 }
1507 }
1508
Amith Yamasanie43530a2009-08-21 13:11:37 -07001509 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001510 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001511 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 synchronized(mPidsSelfLocked) {
1513 if (haveNewCpuStats) {
1514 if (mBatteryStatsService.isOnBattery()) {
1515 final int N = mProcessStats.countWorkingStats();
1516 for (int i=0; i<N; i++) {
1517 ProcessStats.Stats st
1518 = mProcessStats.getWorkingStats(i);
1519 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1520 if (pr != null) {
1521 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1522 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001523 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001524 } else {
1525 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001526 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001527 if (ps != null) {
1528 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001529 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 }
1532 }
1533 }
1534 }
1535 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1538 mLastWriteTime = now;
1539 mBatteryStatsService.getActiveStatistics().writeLocked();
1540 }
1541 }
1542 }
1543 }
1544
1545 /**
1546 * Initialize the application bind args. These are passed to each
1547 * process when the bindApplication() IPC is sent to the process. They're
1548 * lazily setup to make sure the services are running when they're asked for.
1549 */
1550 private HashMap<String, IBinder> getCommonServicesLocked() {
1551 if (mAppBindArgs == null) {
1552 mAppBindArgs = new HashMap<String, IBinder>();
1553
1554 // Setup the application init args
1555 mAppBindArgs.put("package", ServiceManager.getService("package"));
1556 mAppBindArgs.put("window", ServiceManager.getService("window"));
1557 mAppBindArgs.put(Context.ALARM_SERVICE,
1558 ServiceManager.getService(Context.ALARM_SERVICE));
1559 }
1560 return mAppBindArgs;
1561 }
1562
1563 private final void setFocusedActivityLocked(HistoryRecord r) {
1564 if (mFocusedActivity != r) {
1565 mFocusedActivity = r;
1566 mWindowManager.setFocusedApp(r, true);
1567 }
1568 }
1569
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001570 private final void updateLruProcessLocked(ProcessRecord app,
1571 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001573 int lrui = mLruProcesses.indexOf(app);
1574 if (lrui >= 0) mLruProcesses.remove(lrui);
1575
1576 int i = mLruProcesses.size()-1;
1577 int skipTop = 0;
1578
1579 // compute the new weight for this process.
1580 if (updateActivityTime) {
1581 app.lastActivityTime = SystemClock.uptimeMillis();
1582 }
1583 if (app.activities.size() > 0) {
1584 // If this process has activities, we more strongly want to keep
1585 // it around.
1586 app.lruWeight = app.lastActivityTime;
1587 } else if (app.pubProviders.size() > 0) {
1588 // If this process contains content providers, we want to keep
1589 // it a little more strongly.
1590 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1591 // Also don't let it kick out the first few "real" hidden processes.
1592 skipTop = MIN_HIDDEN_APPS;
1593 } else {
1594 // If this process doesn't have activities, we less strongly
1595 // want to keep it around, and generally want to avoid getting
1596 // in front of any very recently used activities.
1597 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1598 // Also don't let it kick out the first few "real" hidden processes.
1599 skipTop = MIN_HIDDEN_APPS;
1600 }
1601 while (i >= 0) {
1602 ProcessRecord p = mLruProcesses.get(i);
1603 // If this app shouldn't be in front of the first N background
1604 // apps, then skip over that many that are currently hidden.
1605 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1606 skipTop--;
1607 }
1608 if (p.lruWeight <= app.lruWeight){
1609 mLruProcesses.add(i+1, app);
1610 break;
1611 }
1612 i--;
1613 }
1614 if (i < 0) {
1615 mLruProcesses.add(0, app);
1616 }
1617
Joe Onorato8a9b2202010-02-26 18:56:32 -08001618 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 if (oomAdj) {
1620 updateOomAdjLocked();
1621 }
1622 }
1623
1624 private final boolean updateLRUListLocked(HistoryRecord r) {
1625 final boolean hadit = mLRUActivities.remove(r);
1626 mLRUActivities.add(r);
1627 return hadit;
1628 }
1629
1630 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1631 int i = mHistory.size()-1;
1632 while (i >= 0) {
1633 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1634 if (!r.finishing && r != notTop) {
1635 return r;
1636 }
1637 i--;
1638 }
1639 return null;
1640 }
1641
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001642 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1643 int i = mHistory.size()-1;
1644 while (i >= 0) {
1645 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1646 if (!r.finishing && !r.delayedResume && r != notTop) {
1647 return r;
1648 }
1649 i--;
1650 }
1651 return null;
1652 }
1653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 /**
1655 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001656 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 *
1658 * @param token If non-null, any history records matching this token will be skipped.
1659 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1660 *
1661 * @return Returns the HistoryRecord of the next activity on the stack.
1662 */
1663 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1664 int i = mHistory.size()-1;
1665 while (i >= 0) {
1666 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1667 // Note: the taskId check depends on real taskId fields being non-zero
1668 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1669 return r;
1670 }
1671 i--;
1672 }
1673 return null;
1674 }
1675
1676 private final ProcessRecord getProcessRecordLocked(
1677 String processName, int uid) {
1678 if (uid == Process.SYSTEM_UID) {
1679 // The system gets to run in any process. If there are multiple
1680 // processes with the same uid, just pick the first (this
1681 // should never happen).
1682 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1683 processName);
1684 return procs != null ? procs.valueAt(0) : null;
1685 }
1686 ProcessRecord proc = mProcessNames.get(processName, uid);
1687 return proc;
1688 }
1689
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001690 private void ensurePackageDexOpt(String packageName) {
1691 IPackageManager pm = ActivityThread.getPackageManager();
1692 try {
1693 if (pm.performDexOpt(packageName)) {
1694 mDidDexOpt = true;
1695 }
1696 } catch (RemoteException e) {
1697 }
1698 }
1699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 private boolean isNextTransitionForward() {
1701 int transit = mWindowManager.getPendingAppTransition();
1702 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1703 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1704 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1705 }
1706
1707 private final boolean realStartActivityLocked(HistoryRecord r,
1708 ProcessRecord app, boolean andResume, boolean checkConfig)
1709 throws RemoteException {
1710
1711 r.startFreezingScreenLocked(app, 0);
1712 mWindowManager.setAppVisibility(r, true);
1713
1714 // Have the window manager re-evaluate the orientation of
1715 // the screen based on the new activity order. Note that
1716 // as a result of this, it can call back into the activity
1717 // manager with a new orientation. We don't care about that,
1718 // because the activity is not currently running so we are
1719 // just restarting it anyway.
1720 if (checkConfig) {
1721 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001722 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 r.mayFreezeScreenLocked(app) ? r : null);
1724 updateConfigurationLocked(config, r);
1725 }
1726
1727 r.app = app;
1728
Joe Onorato8a9b2202010-02-26 18:56:32 -08001729 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730
1731 int idx = app.activities.indexOf(r);
1732 if (idx < 0) {
1733 app.activities.add(r);
1734 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001735 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736
1737 try {
1738 if (app.thread == null) {
1739 throw new RemoteException();
1740 }
1741 List<ResultInfo> results = null;
1742 List<Intent> newIntents = null;
1743 if (andResume) {
1744 results = r.results;
1745 newIntents = r.newIntents;
1746 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001747 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 + " icicle=" + r.icicle
1749 + " with results=" + results + " newIntents=" + newIntents
1750 + " andResume=" + andResume);
1751 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001752 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 System.identityHashCode(r),
1754 r.task.taskId, r.shortComponentName);
1755 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001756 if (r.isHomeActivity) {
1757 mHomeProcess = app;
1758 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001759 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001761 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 r.info, r.icicle, results, newIntents, !andResume,
1763 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 } catch (RemoteException e) {
1765 if (r.launchFailed) {
1766 // This is the second time we failed -- finish activity
1767 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001768 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 + r.intent.getComponent().flattenToShortString()
1770 + ", giving up", e);
1771 appDiedLocked(app, app.pid, app.thread);
1772 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1773 "2nd-crash");
1774 return false;
1775 }
1776
1777 // This is the first time we failed -- restart process and
1778 // retry.
1779 app.activities.remove(r);
1780 throw e;
1781 }
1782
1783 r.launchFailed = false;
1784 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001785 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 + " being launched, but already in LRU list");
1787 }
1788
1789 if (andResume) {
1790 // As part of the process of launching, ActivityThread also performs
1791 // a resume.
1792 r.state = ActivityState.RESUMED;
1793 r.icicle = null;
1794 r.haveState = false;
1795 r.stopped = false;
1796 mResumedActivity = r;
1797 r.task.touchActiveTime();
1798 completeResumeLocked(r);
1799 pauseIfSleepingLocked();
1800 } else {
1801 // This activity is not starting in the resumed state... which
1802 // should look like we asked it to pause+stop (but remain visible),
1803 // and it has done so and reported back the current icicle and
1804 // other state.
1805 r.state = ActivityState.STOPPED;
1806 r.stopped = true;
1807 }
1808
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001809 // Launch the new version setup screen if needed. We do this -after-
1810 // launching the initial activity (that is, home), so that it can have
1811 // a chance to initialize itself while in the background, making the
1812 // switch back to it faster and look better.
1813 startSetupActivityLocked();
1814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 return true;
1816 }
1817
1818 private final void startSpecificActivityLocked(HistoryRecord r,
1819 boolean andResume, boolean checkConfig) {
1820 // Is this activity's application already running?
1821 ProcessRecord app = getProcessRecordLocked(r.processName,
1822 r.info.applicationInfo.uid);
1823
1824 if (r.startTime == 0) {
1825 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001826 if (mInitialStartTime == 0) {
1827 mInitialStartTime = r.startTime;
1828 }
1829 } else if (mInitialStartTime == 0) {
1830 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 }
1832
1833 if (app != null && app.thread != null) {
1834 try {
1835 realStartActivityLocked(r, app, andResume, checkConfig);
1836 return;
1837 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001838 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 + r.intent.getComponent().flattenToShortString(), e);
1840 }
1841
1842 // If a dead object exception was thrown -- fall through to
1843 // restart the application.
1844 }
1845
1846 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001847 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 }
1849
1850 private final ProcessRecord startProcessLocked(String processName,
1851 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001852 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1854 // We don't have to do anything more if:
1855 // (1) There is an existing application record; and
1856 // (2) The caller doesn't think it is dead, OR there is no thread
1857 // object attached to it so we know it couldn't have crashed; and
1858 // (3) There is a pid assigned to it, so it is either starting or
1859 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001860 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 + " app=" + app + " knownToBeDead=" + knownToBeDead
1862 + " thread=" + (app != null ? app.thread : null)
1863 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001864 if (app != null && app.pid > 0) {
1865 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001866 // We already have the app running, or are waiting for it to
1867 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001868 return app;
1869 } else {
1870 // An application record is attached to a previous process,
1871 // clean it up now.
1872 handleAppDiedLocked(app, true);
1873 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 String hostingNameStr = hostingName != null
1877 ? hostingName.flattenToShortString() : null;
1878
1879 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1880 // If we are in the background, then check to see if this process
1881 // is bad. If so, we will just silently fail.
1882 if (mBadProcesses.get(info.processName, info.uid) != null) {
1883 return null;
1884 }
1885 } else {
1886 // When the user is explicitly starting a process, then clear its
1887 // crash count so that we won't make it bad until they see at
1888 // least one crash dialog again, and make the process good again
1889 // if it had been bad.
1890 mProcessCrashTimes.remove(info.processName, info.uid);
1891 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001892 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 info.processName);
1894 mBadProcesses.remove(info.processName, info.uid);
1895 if (app != null) {
1896 app.bad = false;
1897 }
1898 }
1899 }
1900
1901 if (app == null) {
1902 app = newProcessRecordLocked(null, info, processName);
1903 mProcessNames.put(processName, info.uid, app);
1904 } else {
1905 // If this is a new package in the process, add the package to the list
1906 app.addPackage(info.packageName);
1907 }
1908
1909 // If the system is not ready yet, then hold off on starting this
1910 // process until it is.
1911 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001912 && !isAllowedWhileBooting(info)
1913 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 if (!mProcessesOnHold.contains(app)) {
1915 mProcessesOnHold.add(app);
1916 }
1917 return app;
1918 }
1919
1920 startProcessLocked(app, hostingType, hostingNameStr);
1921 return (app.pid != 0) ? app : null;
1922 }
1923
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001924 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1925 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1926 }
1927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001928 private final void startProcessLocked(ProcessRecord app,
1929 String hostingType, String hostingNameStr) {
1930 if (app.pid > 0 && app.pid != MY_PID) {
1931 synchronized (mPidsSelfLocked) {
1932 mPidsSelfLocked.remove(app.pid);
1933 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1934 }
1935 app.pid = 0;
1936 }
1937
1938 mProcessesOnHold.remove(app);
1939
1940 updateCpuStats();
1941
1942 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1943 mProcDeaths[0] = 0;
1944
1945 try {
1946 int uid = app.info.uid;
1947 int[] gids = null;
1948 try {
1949 gids = mContext.getPackageManager().getPackageGids(
1950 app.info.packageName);
1951 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001952 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001953 }
1954 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1955 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1956 && mTopComponent != null
1957 && app.processName.equals(mTopComponent.getPackageName())) {
1958 uid = 0;
1959 }
1960 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1961 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1962 uid = 0;
1963 }
1964 }
1965 int debugFlags = 0;
1966 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1967 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1968 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001969 // Run the app in safe mode if its manifest requests so or the
1970 // system is booted in safe mode.
1971 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1972 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001973 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1976 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1977 }
1978 if ("1".equals(SystemProperties.get("debug.assert"))) {
1979 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1980 }
1981 int pid = Process.start("android.app.ActivityThread",
1982 mSimpleProcessManagement ? app.processName : null, uid, uid,
1983 gids, debugFlags, null);
1984 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1985 synchronized (bs) {
1986 if (bs.isOnBattery()) {
1987 app.batteryStats.incStartsLocked();
1988 }
1989 }
1990
Doug Zongker2bec3d42009-12-04 12:52:44 -08001991 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001992 app.processName, hostingType,
1993 hostingNameStr != null ? hostingNameStr : "");
1994
1995 if (app.persistent) {
1996 Watchdog.getInstance().processStarted(app, app.processName, pid);
1997 }
1998
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001999 StringBuilder buf = mStringBuilder;
2000 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 buf.append("Start proc ");
2002 buf.append(app.processName);
2003 buf.append(" for ");
2004 buf.append(hostingType);
2005 if (hostingNameStr != null) {
2006 buf.append(" ");
2007 buf.append(hostingNameStr);
2008 }
2009 buf.append(": pid=");
2010 buf.append(pid);
2011 buf.append(" uid=");
2012 buf.append(uid);
2013 buf.append(" gids={");
2014 if (gids != null) {
2015 for (int gi=0; gi<gids.length; gi++) {
2016 if (gi != 0) buf.append(", ");
2017 buf.append(gids[gi]);
2018
2019 }
2020 }
2021 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002022 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002023 if (pid == 0 || pid == MY_PID) {
2024 // Processes are being emulated with threads.
2025 app.pid = MY_PID;
2026 app.removed = false;
2027 mStartingProcesses.add(app);
2028 } else if (pid > 0) {
2029 app.pid = pid;
2030 app.removed = false;
2031 synchronized (mPidsSelfLocked) {
2032 this.mPidsSelfLocked.put(pid, app);
2033 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2034 msg.obj = app;
2035 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2036 }
2037 } else {
2038 app.pid = 0;
2039 RuntimeException e = new RuntimeException(
2040 "Failure starting process " + app.processName
2041 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002042 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 }
2044 } catch (RuntimeException e) {
2045 // XXX do better error recovery.
2046 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002047 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 }
2049 }
2050
2051 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2052 if (mPausingActivity != null) {
2053 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002054 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 + mPausingActivity, e);
2056 }
2057 HistoryRecord prev = mResumedActivity;
2058 if (prev == null) {
2059 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002060 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 resumeTopActivityLocked(null);
2062 return;
2063 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002064 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 mResumedActivity = null;
2066 mPausingActivity = prev;
2067 mLastPausedActivity = prev;
2068 prev.state = ActivityState.PAUSING;
2069 prev.task.touchActiveTime();
2070
2071 updateCpuStats();
2072
2073 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002074 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002076 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 System.identityHashCode(prev),
2078 prev.shortComponentName);
2079 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2080 prev.configChangeFlags);
2081 updateUsageStats(prev, false);
2082 } catch (Exception e) {
2083 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002084 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 mPausingActivity = null;
2086 mLastPausedActivity = null;
2087 }
2088 } else {
2089 mPausingActivity = null;
2090 mLastPausedActivity = null;
2091 }
2092
2093 // If we are not going to sleep, we want to ensure the device is
2094 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002095 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 mLaunchingActivity.acquire();
2097 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2098 // To be safe, don't allow the wake lock to be held for too long.
2099 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2100 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2101 }
2102 }
2103
2104
2105 if (mPausingActivity != null) {
2106 // Have the window manager pause its key dispatching until the new
2107 // activity has started. If we're pausing the activity just because
2108 // the screen is being turned off and the UI is sleeping, don't interrupt
2109 // key dispatch; the same activity will pick it up again on wakeup.
2110 if (!uiSleeping) {
2111 prev.pauseKeyDispatchingLocked();
2112 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002113 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114 }
2115
2116 // Schedule a pause timeout in case the app doesn't respond.
2117 // We don't give it much time because this directly impacts the
2118 // responsiveness seen by the user.
2119 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2120 msg.obj = prev;
2121 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002122 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 } else {
2124 // This activity failed to schedule the
2125 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002126 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 resumeTopActivityLocked(null);
2128 }
2129 }
2130
2131 private final void completePauseLocked() {
2132 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002133 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002134
2135 if (prev != null) {
2136 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002137 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2139 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002140 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 if (prev.waitingVisible) {
2142 prev.waitingVisible = false;
2143 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002144 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145 TAG, "Complete pause, no longer waiting: " + prev);
2146 }
2147 if (prev.configDestroy) {
2148 // The previous is being paused because the configuration
2149 // is changing, which means it is actually stopping...
2150 // To juggle the fact that we are also starting a new
2151 // instance right now, we need to first completely stop
2152 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002153 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 destroyActivityLocked(prev, true);
2155 } else {
2156 mStoppingActivities.add(prev);
2157 if (mStoppingActivities.size() > 3) {
2158 // If we already have a few activities waiting to stop,
2159 // then give up on things going idle and start clearing
2160 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002161 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 Message msg = Message.obtain();
2163 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2164 mHandler.sendMessage(msg);
2165 }
2166 }
2167 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002168 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002169 prev = null;
2170 }
2171 mPausingActivity = null;
2172 }
2173
Dianne Hackborn55280a92009-05-07 15:53:46 -07002174 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 resumeTopActivityLocked(prev);
2176 } else {
2177 if (mGoingToSleep.isHeld()) {
2178 mGoingToSleep.release();
2179 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002180 if (mShuttingDown) {
2181 notifyAll();
2182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 }
2184
2185 if (prev != null) {
2186 prev.resumeKeyDispatchingLocked();
2187 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002188
2189 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2190 long diff = 0;
2191 synchronized (mProcessStatsThread) {
2192 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2193 }
2194 if (diff > 0) {
2195 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2196 synchronized (bsi) {
2197 BatteryStatsImpl.Uid.Proc ps =
2198 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2199 prev.info.packageName);
2200 if (ps != null) {
2201 ps.addForegroundTimeLocked(diff);
2202 }
2203 }
2204 }
2205 }
2206 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 }
2208
2209 /**
2210 * Once we know that we have asked an application to put an activity in
2211 * the resumed state (either by launching it or explicitly telling it),
2212 * this function updates the rest of our state to match that fact.
2213 */
2214 private final void completeResumeLocked(HistoryRecord next) {
2215 next.idle = false;
2216 next.results = null;
2217 next.newIntents = null;
2218
2219 // schedule an idle timeout in case the app doesn't do it for us.
2220 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2221 msg.obj = next;
2222 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2223
2224 if (false) {
2225 // The activity was never told to pause, so just keep
2226 // things going as-is. To maintain our own state,
2227 // we need to emulate it coming back and saying it is
2228 // idle.
2229 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2230 msg.obj = next;
2231 mHandler.sendMessage(msg);
2232 }
2233
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002234 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 next.thumbnail = null;
2237 setFocusedActivityLocked(next);
2238 next.resumeKeyDispatchingLocked();
2239 ensureActivitiesVisibleLocked(null, 0);
2240 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002241 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002242
2243 // Mark the point when the activity is resuming
2244 // TODO: To be more accurate, the mark should be before the onCreate,
2245 // not after the onResume. But for subsequent starts, onResume is fine.
2246 if (next.app != null) {
2247 synchronized (mProcessStatsThread) {
2248 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2249 }
2250 } else {
2251 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 }
2254
2255 /**
2256 * Make sure that all activities that need to be visible (that is, they
2257 * currently can be seen by the user) actually are.
2258 */
2259 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2260 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002261 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262 TAG, "ensureActivitiesVisible behind " + top
2263 + " configChanges=0x" + Integer.toHexString(configChanges));
2264
2265 // If the top activity is not fullscreen, then we need to
2266 // make sure any activities under it are now visible.
2267 final int count = mHistory.size();
2268 int i = count-1;
2269 while (mHistory.get(i) != top) {
2270 i--;
2271 }
2272 HistoryRecord r;
2273 boolean behindFullscreen = false;
2274 for (; i>=0; i--) {
2275 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002276 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 TAG, "Make visible? " + r + " finishing=" + r.finishing
2278 + " state=" + r.state);
2279 if (r.finishing) {
2280 continue;
2281 }
2282
2283 final boolean doThisProcess = onlyThisProcess == null
2284 || onlyThisProcess.equals(r.processName);
2285
2286 // First: if this is not the current activity being started, make
2287 // sure it matches the current configuration.
2288 if (r != starting && doThisProcess) {
2289 ensureActivityConfigurationLocked(r, 0);
2290 }
2291
2292 if (r.app == null || r.app.thread == null) {
2293 if (onlyThisProcess == null
2294 || onlyThisProcess.equals(r.processName)) {
2295 // This activity needs to be visible, but isn't even
2296 // running... get it started, but don't resume it
2297 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002298 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002299 TAG, "Start and freeze screen for " + r);
2300 if (r != starting) {
2301 r.startFreezingScreenLocked(r.app, configChanges);
2302 }
2303 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002304 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 TAG, "Starting and making visible: " + r);
2306 mWindowManager.setAppVisibility(r, true);
2307 }
2308 if (r != starting) {
2309 startSpecificActivityLocked(r, false, false);
2310 }
2311 }
2312
2313 } else if (r.visible) {
2314 // If this activity is already visible, then there is nothing
2315 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002316 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 TAG, "Skipping: already visible at " + r);
2318 r.stopFreezingScreenLocked(false);
2319
2320 } else if (onlyThisProcess == null) {
2321 // This activity is not currently visible, but is running.
2322 // Tell it to become visible.
2323 r.visible = true;
2324 if (r.state != ActivityState.RESUMED && r != starting) {
2325 // If this activity is paused, tell it
2326 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002327 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 TAG, "Making visible and scheduling visibility: " + r);
2329 try {
2330 mWindowManager.setAppVisibility(r, true);
2331 r.app.thread.scheduleWindowVisibility(r, true);
2332 r.stopFreezingScreenLocked(false);
2333 } catch (Exception e) {
2334 // Just skip on any failure; we'll make it
2335 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002336 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 + r.intent.getComponent(), e);
2338 }
2339 }
2340 }
2341
2342 // Aggregate current change flags.
2343 configChanges |= r.configChangeFlags;
2344
2345 if (r.fullscreen) {
2346 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002347 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 TAG, "Stopping: fullscreen at " + r);
2349 behindFullscreen = true;
2350 i--;
2351 break;
2352 }
2353 }
2354
2355 // Now for any activities that aren't visible to the user, make
2356 // sure they no longer are keeping the screen frozen.
2357 while (i >= 0) {
2358 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002359 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2361 + " state=" + r.state
2362 + " behindFullscreen=" + behindFullscreen);
2363 if (!r.finishing) {
2364 if (behindFullscreen) {
2365 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002366 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 TAG, "Making invisible: " + r);
2368 r.visible = false;
2369 try {
2370 mWindowManager.setAppVisibility(r, false);
2371 if ((r.state == ActivityState.STOPPING
2372 || r.state == ActivityState.STOPPED)
2373 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002374 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 TAG, "Scheduling invisibility: " + r);
2376 r.app.thread.scheduleWindowVisibility(r, false);
2377 }
2378 } catch (Exception e) {
2379 // Just skip on any failure; we'll make it
2380 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002381 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002382 + r.intent.getComponent(), e);
2383 }
2384 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002385 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002386 TAG, "Already invisible: " + r);
2387 }
2388 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002389 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 TAG, "Now behindFullscreen: " + r);
2391 behindFullscreen = true;
2392 }
2393 }
2394 i--;
2395 }
2396 }
2397
2398 /**
2399 * Version of ensureActivitiesVisible that can easily be called anywhere.
2400 */
2401 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2402 int configChanges) {
2403 HistoryRecord r = topRunningActivityLocked(null);
2404 if (r != null) {
2405 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2406 }
2407 }
2408
2409 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2410 if (resumed) {
2411 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2412 } else {
2413 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2414 }
2415 }
2416
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002417 private boolean startHomeActivityLocked() {
2418 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2419 && mTopAction == null) {
2420 // We are running in factory test mode, but unable to find
2421 // the factory test app, so just sit around displaying the
2422 // error message and don't try to start anything.
2423 return false;
2424 }
2425 Intent intent = new Intent(
2426 mTopAction,
2427 mTopData != null ? Uri.parse(mTopData) : null);
2428 intent.setComponent(mTopComponent);
2429 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2430 intent.addCategory(Intent.CATEGORY_HOME);
2431 }
2432 ActivityInfo aInfo =
2433 intent.resolveActivityInfo(mContext.getPackageManager(),
2434 STOCK_PM_FLAGS);
2435 if (aInfo != null) {
2436 intent.setComponent(new ComponentName(
2437 aInfo.applicationInfo.packageName, aInfo.name));
2438 // Don't do this if the home app is currently being
2439 // instrumented.
2440 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2441 aInfo.applicationInfo.uid);
2442 if (app == null || app.instrumentationClass == null) {
2443 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2444 startActivityLocked(null, intent, null, null, 0, aInfo,
2445 null, null, 0, 0, 0, false, false);
2446 }
2447 }
2448
2449
2450 return true;
2451 }
2452
2453 /**
2454 * Starts the "new version setup screen" if appropriate.
2455 */
2456 private void startSetupActivityLocked() {
2457 // Only do this once per boot.
2458 if (mCheckedForSetup) {
2459 return;
2460 }
2461
2462 // We will show this screen if the current one is a different
2463 // version than the last one shown, and we are not running in
2464 // low-level factory test mode.
2465 final ContentResolver resolver = mContext.getContentResolver();
2466 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2467 Settings.Secure.getInt(resolver,
2468 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2469 mCheckedForSetup = true;
2470
2471 // See if we should be showing the platform update setup UI.
2472 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2473 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2474 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2475
2476 // We don't allow third party apps to replace this.
2477 ResolveInfo ri = null;
2478 for (int i=0; ris != null && i<ris.size(); i++) {
2479 if ((ris.get(i).activityInfo.applicationInfo.flags
2480 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2481 ri = ris.get(i);
2482 break;
2483 }
2484 }
2485
2486 if (ri != null) {
2487 String vers = ri.activityInfo.metaData != null
2488 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2489 : null;
2490 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2491 vers = ri.activityInfo.applicationInfo.metaData.getString(
2492 Intent.METADATA_SETUP_VERSION);
2493 }
2494 String lastVers = Settings.Secure.getString(
2495 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2496 if (vers != null && !vers.equals(lastVers)) {
2497 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2498 intent.setComponent(new ComponentName(
2499 ri.activityInfo.packageName, ri.activityInfo.name));
2500 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2501 null, null, 0, 0, 0, false, false);
2502 }
2503 }
2504 }
2505 }
2506
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002507 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002508 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002509
2510 final int identHash = System.identityHashCode(r);
2511 updateUsageStats(r, true);
2512
2513 int i = mWatchers.beginBroadcast();
2514 while (i > 0) {
2515 i--;
2516 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2517 if (w != null) {
2518 try {
2519 w.activityResuming(identHash);
2520 } catch (RemoteException e) {
2521 }
2522 }
2523 }
2524 mWatchers.finishBroadcast();
2525 }
2526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 /**
2528 * Ensure that the top activity in the stack is resumed.
2529 *
2530 * @param prev The previously resumed activity, for when in the process
2531 * of pausing; can be null to call from elsewhere.
2532 *
2533 * @return Returns true if something is being resumed, or false if
2534 * nothing happened.
2535 */
2536 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2537 // Find the first activity that is not finishing.
2538 HistoryRecord next = topRunningActivityLocked(null);
2539
2540 // Remember how we'll process this pause/resume situation, and ensure
2541 // that the state is reset however we wind up proceeding.
2542 final boolean userLeaving = mUserLeaving;
2543 mUserLeaving = false;
2544
2545 if (next == null) {
2546 // There are no more activities! Let's just start up the
2547 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002548 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002549 }
2550
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002551 next.delayedResume = false;
2552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 // If the top activity is the resumed one, nothing to do.
2554 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2555 // Make sure we have executed any pending transitions, since there
2556 // should be nothing left to do at this point.
2557 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002558 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002559 return false;
2560 }
2561
2562 // If we are sleeping, and there is no resumed activity, and the top
2563 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002564 if ((mSleeping || mShuttingDown)
2565 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 // Make sure we have executed any pending transitions, since there
2567 // should be nothing left to do at this point.
2568 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002569 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 return false;
2571 }
2572
2573 // The activity may be waiting for stop, but that is no longer
2574 // appropriate for it.
2575 mStoppingActivities.remove(next);
2576 mWaitingVisibleActivities.remove(next);
2577
Joe Onorato8a9b2202010-02-26 18:56:32 -08002578 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579
2580 // If we are currently pausing an activity, then don't do anything
2581 // until that is done.
2582 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002583 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 return false;
2585 }
2586
2587 // We need to start pausing the current activity so the top one
2588 // can be resumed...
2589 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002590 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 startPausingLocked(userLeaving, false);
2592 return true;
2593 }
2594
2595 if (prev != null && prev != next) {
2596 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2597 prev.waitingVisible = true;
2598 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002599 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 TAG, "Resuming top, waiting visible to hide: " + prev);
2601 } else {
2602 // The next activity is already visible, so hide the previous
2603 // activity's windows right now so we can show the new one ASAP.
2604 // We only do this if the previous is finishing, which should mean
2605 // it is on top of the one being resumed so hiding it quickly
2606 // is good. Otherwise, we want to do the normal route of allowing
2607 // the resumed activity to be shown so we can decide if the
2608 // previous should actually be hidden depending on whether the
2609 // new one is found to be full-screen or not.
2610 if (prev.finishing) {
2611 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002612 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 + prev + ", waitingVisible="
2614 + (prev != null ? prev.waitingVisible : null)
2615 + ", nowVisible=" + next.nowVisible);
2616 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002617 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 + prev + ", waitingVisible="
2619 + (prev != null ? prev.waitingVisible : null)
2620 + ", nowVisible=" + next.nowVisible);
2621 }
2622 }
2623 }
2624
2625 // We are starting up the next activity, so tell the window manager
2626 // that the previous one will be hidden soon. This way it can know
2627 // to ignore it when computing the desired screen orientation.
2628 if (prev != null) {
2629 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002630 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002632 if (mNoAnimActivities.contains(prev)) {
2633 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2634 } else {
2635 mWindowManager.prepareAppTransition(prev.task == next.task
2636 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2637 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002639 mWindowManager.setAppWillBeHidden(prev);
2640 mWindowManager.setAppVisibility(prev, false);
2641 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002642 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002644 if (mNoAnimActivities.contains(next)) {
2645 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2646 } else {
2647 mWindowManager.prepareAppTransition(prev.task == next.task
2648 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2649 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2650 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 }
2652 if (false) {
2653 mWindowManager.setAppWillBeHidden(prev);
2654 mWindowManager.setAppVisibility(prev, false);
2655 }
2656 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002657 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002658 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002659 if (mNoAnimActivities.contains(next)) {
2660 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2661 } else {
2662 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2663 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 }
2665
2666 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002667 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668
2669 // This activity is now becoming visible.
2670 mWindowManager.setAppVisibility(next, true);
2671
2672 HistoryRecord lastResumedActivity = mResumedActivity;
2673 ActivityState lastState = next.state;
2674
2675 updateCpuStats();
2676
2677 next.state = ActivityState.RESUMED;
2678 mResumedActivity = next;
2679 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002680 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 updateLRUListLocked(next);
2682
2683 // Have the window manager re-evaluate the orientation of
2684 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002685 boolean updated;
2686 synchronized (this) {
2687 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2688 mConfiguration,
2689 next.mayFreezeScreenLocked(next.app) ? next : null);
2690 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002691 next.frozenBeforeDestroy = true;
2692 }
2693 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002695 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 // The configuration update wasn't able to keep the existing
2697 // instance of the activity, and instead started a new one.
2698 // We should be all done, but let's just make sure our activity
2699 // is still at the top and schedule another run if something
2700 // weird happened.
2701 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002702 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002703 "Activity config changed during resume: " + next
2704 + ", new next: " + nextNext);
2705 if (nextNext != next) {
2706 // Do over!
2707 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2708 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002709 setFocusedActivityLocked(next);
2710 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002712 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 return true;
2714 }
2715
2716 try {
2717 // Deliver all pending results.
2718 ArrayList a = next.results;
2719 if (a != null) {
2720 final int N = a.size();
2721 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002722 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723 TAG, "Delivering results to " + next
2724 + ": " + a);
2725 next.app.thread.scheduleSendResult(next, a);
2726 }
2727 }
2728
2729 if (next.newIntents != null) {
2730 next.app.thread.scheduleNewIntent(next.newIntents, next);
2731 }
2732
Doug Zongker2bec3d42009-12-04 12:52:44 -08002733 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 System.identityHashCode(next),
2735 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736
2737 next.app.thread.scheduleResumeActivity(next,
2738 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002740 pauseIfSleepingLocked();
2741
2742 } catch (Exception e) {
2743 // Whoops, need to restart this activity!
2744 next.state = lastState;
2745 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002746 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 if (!next.hasBeenLaunched) {
2748 next.hasBeenLaunched = true;
2749 } else {
2750 if (SHOW_APP_STARTING_ICON) {
2751 mWindowManager.setAppStartingWindow(
2752 next, next.packageName, next.theme,
2753 next.nonLocalizedLabel,
2754 next.labelRes, next.icon, null, true);
2755 }
2756 }
2757 startSpecificActivityLocked(next, true, false);
2758 return true;
2759 }
2760
2761 // From this point on, if something goes wrong there is no way
2762 // to recover the activity.
2763 try {
2764 next.visible = true;
2765 completeResumeLocked(next);
2766 } catch (Exception e) {
2767 // If any exception gets thrown, toss away this
2768 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002769 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002770 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2771 "resume-exception");
2772 return true;
2773 }
2774
2775 // Didn't need to use the icicle, and it is now out of date.
2776 next.icicle = null;
2777 next.haveState = false;
2778 next.stopped = false;
2779
2780 } else {
2781 // Whoops, need to restart this activity!
2782 if (!next.hasBeenLaunched) {
2783 next.hasBeenLaunched = true;
2784 } else {
2785 if (SHOW_APP_STARTING_ICON) {
2786 mWindowManager.setAppStartingWindow(
2787 next, next.packageName, next.theme,
2788 next.nonLocalizedLabel,
2789 next.labelRes, next.icon, null, true);
2790 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002791 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792 }
2793 startSpecificActivityLocked(next, true, true);
2794 }
2795
2796 return true;
2797 }
2798
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002799 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2800 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002801 final int NH = mHistory.size();
2802
2803 int addPos = -1;
2804
2805 if (!newTask) {
2806 // If starting in an existing task, find where that is...
2807 HistoryRecord next = null;
2808 boolean startIt = true;
2809 for (int i = NH-1; i >= 0; i--) {
2810 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2811 if (p.finishing) {
2812 continue;
2813 }
2814 if (p.task == r.task) {
2815 // Here it is! Now, if this is not yet visible to the
2816 // user, then just add it without starting; it will
2817 // get started when the user navigates back to it.
2818 addPos = i+1;
2819 if (!startIt) {
2820 mHistory.add(addPos, r);
2821 r.inHistory = true;
2822 r.task.numActivities++;
2823 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2824 r.info.screenOrientation, r.fullscreen);
2825 if (VALIDATE_TOKENS) {
2826 mWindowManager.validateAppTokens(mHistory);
2827 }
2828 return;
2829 }
2830 break;
2831 }
2832 if (p.fullscreen) {
2833 startIt = false;
2834 }
2835 next = p;
2836 }
2837 }
2838
2839 // Place a new activity at top of stack, so it is next to interact
2840 // with the user.
2841 if (addPos < 0) {
2842 addPos = mHistory.size();
2843 }
2844
2845 // If we are not placing the new activity frontmost, we do not want
2846 // to deliver the onUserLeaving callback to the actual frontmost
2847 // activity
2848 if (addPos < NH) {
2849 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002850 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 }
2852
2853 // Slot the activity into the history stack and proceed
2854 mHistory.add(addPos, r);
2855 r.inHistory = true;
2856 r.frontOfTask = newTask;
2857 r.task.numActivities++;
2858 if (NH > 0) {
2859 // We want to show the starting preview window if we are
2860 // switching to a new task, or the next activity's process is
2861 // not currently running.
2862 boolean showStartingIcon = newTask;
2863 ProcessRecord proc = r.app;
2864 if (proc == null) {
2865 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2866 }
2867 if (proc == null || proc.thread == null) {
2868 showStartingIcon = true;
2869 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002870 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002872 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2873 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2874 mNoAnimActivities.add(r);
2875 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2876 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2877 mNoAnimActivities.remove(r);
2878 } else {
2879 mWindowManager.prepareAppTransition(newTask
2880 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2881 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2882 mNoAnimActivities.remove(r);
2883 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 mWindowManager.addAppToken(
2885 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2886 boolean doShow = true;
2887 if (newTask) {
2888 // Even though this activity is starting fresh, we still need
2889 // to reset it to make sure we apply affinities to move any
2890 // existing activities from other tasks in to it.
2891 // If the caller has requested that the target task be
2892 // reset, then do so.
2893 if ((r.intent.getFlags()
2894 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2895 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002896 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 }
2898 }
2899 if (SHOW_APP_STARTING_ICON && doShow) {
2900 // Figure out if we are transitioning from another activity that is
2901 // "has the same starting icon" as the next one. This allows the
2902 // window manager to keep the previous window it had previously
2903 // created, if it still had one.
2904 HistoryRecord prev = mResumedActivity;
2905 if (prev != null) {
2906 // We don't want to reuse the previous starting preview if:
2907 // (1) The current activity is in a different task.
2908 if (prev.task != r.task) prev = null;
2909 // (2) The current activity is already displayed.
2910 else if (prev.nowVisible) prev = null;
2911 }
2912 mWindowManager.setAppStartingWindow(
2913 r, r.packageName, r.theme, r.nonLocalizedLabel,
2914 r.labelRes, r.icon, prev, showStartingIcon);
2915 }
2916 } else {
2917 // If this is the first activity, don't do any fancy animations,
2918 // because there is nothing for it to animate on top of.
2919 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2920 r.info.screenOrientation, r.fullscreen);
2921 }
2922 if (VALIDATE_TOKENS) {
2923 mWindowManager.validateAppTokens(mHistory);
2924 }
2925
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002926 if (doResume) {
2927 resumeTopActivityLocked(null);
2928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 }
2930
2931 /**
2932 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002933 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2934 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 * an instance of that activity in the stack and, if found, finish all
2936 * activities on top of it and return the instance.
2937 *
2938 * @param newR Description of the new activity being started.
2939 * @return Returns the old activity that should be continue to be used,
2940 * or null if none was found.
2941 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002942 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002943 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002945
2946 // First find the requested task.
2947 while (i > 0) {
2948 i--;
2949 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2950 if (r.task.taskId == taskId) {
2951 i++;
2952 break;
2953 }
2954 }
2955
2956 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002957 while (i > 0) {
2958 i--;
2959 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2960 if (r.finishing) {
2961 continue;
2962 }
2963 if (r.task.taskId != taskId) {
2964 return null;
2965 }
2966 if (r.realActivity.equals(newR.realActivity)) {
2967 // Here it is! Now finish everything in front...
2968 HistoryRecord ret = r;
2969 if (doClear) {
2970 while (i < (mHistory.size()-1)) {
2971 i++;
2972 r = (HistoryRecord)mHistory.get(i);
2973 if (r.finishing) {
2974 continue;
2975 }
2976 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2977 null, "clear")) {
2978 i--;
2979 }
2980 }
2981 }
2982
2983 // Finally, if this is a normal launch mode (that is, not
2984 // expecting onNewIntent()), then we will finish the current
2985 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002986 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2987 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002988 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002989 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 if (index >= 0) {
2991 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2992 null, "clear");
2993 }
2994 return null;
2995 }
2996 }
2997
2998 return ret;
2999 }
3000 }
3001
3002 return null;
3003 }
3004
3005 /**
3006 * Find the activity in the history stack within the given task. Returns
3007 * the index within the history at which it's found, or < 0 if not found.
3008 */
3009 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3010 int i = mHistory.size();
3011 while (i > 0) {
3012 i--;
3013 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3014 if (candidate.task.taskId != task) {
3015 break;
3016 }
3017 if (candidate.realActivity.equals(r.realActivity)) {
3018 return i;
3019 }
3020 }
3021
3022 return -1;
3023 }
3024
3025 /**
3026 * Reorder the history stack so that the activity at the given index is
3027 * brought to the front.
3028 */
3029 private final HistoryRecord moveActivityToFrontLocked(int where) {
3030 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3031 int top = mHistory.size();
3032 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3033 mHistory.add(top, newTop);
3034 oldTop.frontOfTask = false;
3035 newTop.frontOfTask = true;
3036 return newTop;
3037 }
3038
3039 /**
3040 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3041 * method will be called at the proper time.
3042 */
3043 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3044 boolean sent = false;
3045 if (r.state == ActivityState.RESUMED
3046 && r.app != null && r.app.thread != null) {
3047 try {
3048 ArrayList<Intent> ar = new ArrayList<Intent>();
3049 ar.add(new Intent(intent));
3050 r.app.thread.scheduleNewIntent(ar, r);
3051 sent = true;
3052 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003053 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 }
3055 }
3056 if (!sent) {
3057 r.addNewIntentLocked(new Intent(intent));
3058 }
3059 }
3060
3061 private final void logStartActivity(int tag, HistoryRecord r,
3062 TaskRecord task) {
3063 EventLog.writeEvent(tag,
3064 System.identityHashCode(r), task.taskId,
3065 r.shortComponentName, r.intent.getAction(),
3066 r.intent.getType(), r.intent.getDataString(),
3067 r.intent.getFlags());
3068 }
3069
3070 private final int startActivityLocked(IApplicationThread caller,
3071 Intent intent, String resolvedType,
3072 Uri[] grantedUriPermissions,
3073 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3074 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003075 int callingPid, int callingUid, boolean onlyIfNeeded,
3076 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003077 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078
3079 HistoryRecord sourceRecord = null;
3080 HistoryRecord resultRecord = null;
3081 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003082 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003083 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3085 if (index >= 0) {
3086 sourceRecord = (HistoryRecord)mHistory.get(index);
3087 if (requestCode >= 0 && !sourceRecord.finishing) {
3088 resultRecord = sourceRecord;
3089 }
3090 }
3091 }
3092
3093 int launchFlags = intent.getFlags();
3094
3095 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3096 && sourceRecord != null) {
3097 // Transfer the result target from the source activity to the new
3098 // one being started, including any failures.
3099 if (requestCode >= 0) {
3100 return START_FORWARD_AND_REQUEST_CONFLICT;
3101 }
3102 resultRecord = sourceRecord.resultTo;
3103 resultWho = sourceRecord.resultWho;
3104 requestCode = sourceRecord.requestCode;
3105 sourceRecord.resultTo = null;
3106 if (resultRecord != null) {
3107 resultRecord.removeResultsLocked(
3108 sourceRecord, resultWho, requestCode);
3109 }
3110 }
3111
3112 int err = START_SUCCESS;
3113
3114 if (intent.getComponent() == null) {
3115 // We couldn't find a class that can handle the given Intent.
3116 // That's the end of that!
3117 err = START_INTENT_NOT_RESOLVED;
3118 }
3119
3120 if (err == START_SUCCESS && aInfo == null) {
3121 // We couldn't find the specific class specified in the Intent.
3122 // Also the end of the line.
3123 err = START_CLASS_NOT_FOUND;
3124 }
3125
3126 ProcessRecord callerApp = null;
3127 if (err == START_SUCCESS && caller != null) {
3128 callerApp = getRecordForAppLocked(caller);
3129 if (callerApp != null) {
3130 callingPid = callerApp.pid;
3131 callingUid = callerApp.info.uid;
3132 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003133 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134 + " (pid=" + callingPid + ") when starting: "
3135 + intent.toString());
3136 err = START_PERMISSION_DENIED;
3137 }
3138 }
3139
3140 if (err != START_SUCCESS) {
3141 if (resultRecord != null) {
3142 sendActivityResultLocked(-1,
3143 resultRecord, resultWho, requestCode,
3144 Activity.RESULT_CANCELED, null);
3145 }
3146 return err;
3147 }
3148
3149 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3150 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3151 if (perm != PackageManager.PERMISSION_GRANTED) {
3152 if (resultRecord != null) {
3153 sendActivityResultLocked(-1,
3154 resultRecord, resultWho, requestCode,
3155 Activity.RESULT_CANCELED, null);
3156 }
3157 String msg = "Permission Denial: starting " + intent.toString()
3158 + " from " + callerApp + " (pid=" + callingPid
3159 + ", uid=" + callingUid + ")"
3160 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003161 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 throw new SecurityException(msg);
3163 }
3164
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003165 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 boolean abort = false;
3167 try {
3168 // The Intent we give to the watcher has the extra data
3169 // stripped off, since it can contain private information.
3170 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003171 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003172 aInfo.applicationInfo.packageName);
3173 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003174 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 }
3176
3177 if (abort) {
3178 if (resultRecord != null) {
3179 sendActivityResultLocked(-1,
3180 resultRecord, resultWho, requestCode,
3181 Activity.RESULT_CANCELED, null);
3182 }
3183 // We pretend to the caller that it was really started, but
3184 // they will just get a cancel result.
3185 return START_SUCCESS;
3186 }
3187 }
3188
3189 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3190 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003191 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003193 if (mResumedActivity == null
3194 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3195 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3196 PendingActivityLaunch pal = new PendingActivityLaunch();
3197 pal.r = r;
3198 pal.sourceRecord = sourceRecord;
3199 pal.grantedUriPermissions = grantedUriPermissions;
3200 pal.grantedMode = grantedMode;
3201 pal.onlyIfNeeded = onlyIfNeeded;
3202 mPendingActivityLaunches.add(pal);
3203 return START_SWITCHES_CANCELED;
3204 }
3205 }
3206
3207 if (mDidAppSwitch) {
3208 // This is the second allowed switch since we stopped switches,
3209 // so now just generally allow switches. Use case: user presses
3210 // home (switches disabled, switch to home, mDidAppSwitch now true);
3211 // user taps a home icon (coming from home so allowed, we hit here
3212 // and now allow anyone to switch again).
3213 mAppSwitchesAllowedTime = 0;
3214 } else {
3215 mDidAppSwitch = true;
3216 }
3217
3218 doPendingActivityLaunchesLocked(false);
3219
3220 return startActivityUncheckedLocked(r, sourceRecord,
3221 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3222 }
3223
3224 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3225 final int N = mPendingActivityLaunches.size();
3226 if (N <= 0) {
3227 return;
3228 }
3229 for (int i=0; i<N; i++) {
3230 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3231 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3232 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3233 doResume && i == (N-1));
3234 }
3235 mPendingActivityLaunches.clear();
3236 }
3237
3238 private final int startActivityUncheckedLocked(HistoryRecord r,
3239 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3240 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3241 final Intent intent = r.intent;
3242 final int callingUid = r.launchedFromUid;
3243
3244 int launchFlags = intent.getFlags();
3245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003246 // We'll invoke onUserLeaving before onPause only if the launching
3247 // activity did not explicitly state that this is an automated launch.
3248 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003249 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 "startActivity() => mUserLeaving=" + mUserLeaving);
3251
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003252 // If the caller has asked not to resume at this point, we make note
3253 // of this in the record so that we can skip it when trying to find
3254 // the top running activity.
3255 if (!doResume) {
3256 r.delayedResume = true;
3257 }
3258
3259 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3260 != 0 ? r : null;
3261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 // If the onlyIfNeeded flag is set, then we can do this if the activity
3263 // being launched is the same as the one making the call... or, as
3264 // a special case, if we do not know the caller then we count the
3265 // current top activity as the caller.
3266 if (onlyIfNeeded) {
3267 HistoryRecord checkedCaller = sourceRecord;
3268 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003269 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 }
3271 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3272 // Caller is not the same as launcher, so always needed.
3273 onlyIfNeeded = false;
3274 }
3275 }
3276
3277 if (grantedUriPermissions != null && callingUid > 0) {
3278 for (int i=0; i<grantedUriPermissions.length; i++) {
3279 grantUriPermissionLocked(callingUid, r.packageName,
3280 grantedUriPermissions[i], grantedMode, r);
3281 }
3282 }
3283
3284 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3285 intent, r);
3286
3287 if (sourceRecord == null) {
3288 // This activity is not being started from another... in this
3289 // case we -always- start a new task.
3290 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003291 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 -08003292 + intent);
3293 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3294 }
3295 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3296 // The original activity who is starting us is running as a single
3297 // instance... this new activity it is starting must go on its
3298 // own task.
3299 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3300 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3301 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3302 // The activity being started is a single instance... it always
3303 // gets launched into its own task.
3304 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3305 }
3306
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003307 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 // For whatever reason this activity is being launched into a new
3309 // task... yet the caller has requested a result back. Well, that
3310 // is pretty messed up, so instead immediately send back a cancel
3311 // and let the new task continue launched as normal without a
3312 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003313 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003315 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 Activity.RESULT_CANCELED, null);
3317 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003318 }
3319
3320 boolean addingToTask = false;
3321 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3322 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3323 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3324 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3325 // If bring to front is requested, and no result is requested, and
3326 // we can find a task that was started with this same
3327 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003328 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 // See if there is a task to bring to the front. If this is
3330 // a SINGLE_INSTANCE activity, there can be one and only one
3331 // instance of it in the history, and it is always in its own
3332 // unique task, so we do a special search.
3333 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3334 ? findTaskLocked(intent, r.info)
3335 : findActivityLocked(intent, r.info);
3336 if (taskTop != null) {
3337 if (taskTop.task.intent == null) {
3338 // This task was started because of movement of
3339 // the activity based on affinity... now that we
3340 // are actually launching it, we can assign the
3341 // base intent.
3342 taskTop.task.setIntent(intent, r.info);
3343 }
3344 // If the target task is not in the front, then we need
3345 // to bring it to the front... except... well, with
3346 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3347 // to have the same behavior as if a new instance was
3348 // being started, which means not bringing it to the front
3349 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003350 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 if (curTop.task != taskTop.task) {
3352 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3353 boolean callerAtFront = sourceRecord == null
3354 || curTop.task == sourceRecord.task;
3355 if (callerAtFront) {
3356 // We really do want to push this one into the
3357 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003358 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 }
3360 }
3361 // If the caller has requested that the target task be
3362 // reset, then do so.
3363 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3364 taskTop = resetTaskIfNeededLocked(taskTop, r);
3365 }
3366 if (onlyIfNeeded) {
3367 // We don't need to start a new activity, and
3368 // the client said not to do anything if that
3369 // is the case, so this is it! And for paranoia, make
3370 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003371 if (doResume) {
3372 resumeTopActivityLocked(null);
3373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 return START_RETURN_INTENT_TO_CALLER;
3375 }
3376 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3377 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3378 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3379 // In this situation we want to remove all activities
3380 // from the task up to the one being started. In most
3381 // cases this means we are resetting the task to its
3382 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003383 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003384 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 if (top != null) {
3386 if (top.frontOfTask) {
3387 // Activity aliases may mean we use different
3388 // intents for the top activity, so make sure
3389 // the task now has the identity of the new
3390 // intent.
3391 top.task.setIntent(r.intent, r.info);
3392 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003393 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003394 deliverNewIntentLocked(top, r.intent);
3395 } else {
3396 // A special case: we need to
3397 // start the activity because it is not currently
3398 // running, and the caller has asked to clear the
3399 // current task to have this activity at the top.
3400 addingToTask = true;
3401 // Now pretend like this activity is being started
3402 // by the top of its task, so it is put in the
3403 // right place.
3404 sourceRecord = taskTop;
3405 }
3406 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3407 // In this case the top activity on the task is the
3408 // same as the one being launched, so we take that
3409 // as a request to bring the task to the foreground.
3410 // If the top activity in the task is the root
3411 // activity, deliver this new intent to it if it
3412 // desires.
3413 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3414 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003415 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003416 if (taskTop.frontOfTask) {
3417 taskTop.task.setIntent(r.intent, r.info);
3418 }
3419 deliverNewIntentLocked(taskTop, r.intent);
3420 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3421 // In this case we are launching the root activity
3422 // of the task, but with a different intent. We
3423 // should start a new instance on top.
3424 addingToTask = true;
3425 sourceRecord = taskTop;
3426 }
3427 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3428 // In this case an activity is being launched in to an
3429 // existing task, without resetting that task. This
3430 // is typically the situation of launching an activity
3431 // from a notification or shortcut. We want to place
3432 // the new activity on top of the current task.
3433 addingToTask = true;
3434 sourceRecord = taskTop;
3435 } else if (!taskTop.task.rootWasReset) {
3436 // In this case we are launching in to an existing task
3437 // that has not yet been started from its front door.
3438 // The current task has been brought to the front.
3439 // Ideally, we'd probably like to place this new task
3440 // at the bottom of its stack, but that's a little hard
3441 // to do with the current organization of the code so
3442 // for now we'll just drop it.
3443 taskTop.task.setIntent(r.intent, r.info);
3444 }
3445 if (!addingToTask) {
3446 // We didn't do anything... but it was needed (a.k.a., client
3447 // don't use that intent!) And for paranoia, make
3448 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003449 if (doResume) {
3450 resumeTopActivityLocked(null);
3451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 return START_TASK_TO_FRONT;
3453 }
3454 }
3455 }
3456 }
3457
3458 //String uri = r.intent.toURI();
3459 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003460 //Slog.i(TAG, "Given intent: " + r.intent);
3461 //Slog.i(TAG, "URI is: " + uri);
3462 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003463
3464 if (r.packageName != null) {
3465 // If the activity being launched is the same as the one currently
3466 // at the top, then we need to check if it should only be launched
3467 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003468 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3469 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 if (top.realActivity.equals(r.realActivity)) {
3471 if (top.app != null && top.app.thread != null) {
3472 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3473 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3474 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003475 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 // For paranoia, make sure we have correctly
3477 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003478 if (doResume) {
3479 resumeTopActivityLocked(null);
3480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 if (onlyIfNeeded) {
3482 // We don't need to start a new activity, and
3483 // the client said not to do anything if that
3484 // is the case, so this is it!
3485 return START_RETURN_INTENT_TO_CALLER;
3486 }
3487 deliverNewIntentLocked(top, r.intent);
3488 return START_DELIVERED_TO_TOP;
3489 }
3490 }
3491 }
3492 }
3493
3494 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003495 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003497 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 Activity.RESULT_CANCELED, null);
3499 }
3500 return START_CLASS_NOT_FOUND;
3501 }
3502
3503 boolean newTask = false;
3504
3505 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003506 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3508 // todo: should do better management of integers.
3509 mCurTask++;
3510 if (mCurTask <= 0) {
3511 mCurTask = 1;
3512 }
3513 r.task = new TaskRecord(mCurTask, r.info, intent,
3514 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003515 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516 + " in new task " + r.task);
3517 newTask = true;
3518 addRecentTask(r.task);
3519
3520 } else if (sourceRecord != null) {
3521 if (!addingToTask &&
3522 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3523 // In this case, we are adding the activity to an existing
3524 // task, but the caller has asked to clear that task if the
3525 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003526 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003527 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003529 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003530 deliverNewIntentLocked(top, r.intent);
3531 // For paranoia, make sure we have correctly
3532 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003533 if (doResume) {
3534 resumeTopActivityLocked(null);
3535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 return START_DELIVERED_TO_TOP;
3537 }
3538 } else if (!addingToTask &&
3539 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3540 // In this case, we are launching an activity in our own task
3541 // that may already be running somewhere in the history, and
3542 // we want to shuffle it to the front of the stack if so.
3543 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3544 if (where >= 0) {
3545 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003546 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003547 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003548 if (doResume) {
3549 resumeTopActivityLocked(null);
3550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 return START_DELIVERED_TO_TOP;
3552 }
3553 }
3554 // An existing activity is starting this new activity, so we want
3555 // to keep the new one in the same task as the one that is starting
3556 // it.
3557 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003558 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 + " in existing task " + r.task);
3560
3561 } else {
3562 // This not being started from an existing activity, and not part
3563 // of a new task... just put it in the top task, though these days
3564 // this case should never happen.
3565 final int N = mHistory.size();
3566 HistoryRecord prev =
3567 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3568 r.task = prev != null
3569 ? prev.task
3570 : new TaskRecord(mCurTask, r.info, intent,
3571 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003572 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 + " in new guessed " + r.task);
3574 }
3575 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003576 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003578 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003579 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 return START_SUCCESS;
3581 }
3582
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003583 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3584 long thisTime, long totalTime) {
3585 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3586 WaitResult w = mWaitingActivityLaunched.get(i);
3587 w.timeout = timeout;
3588 if (r != null) {
3589 w.who = new ComponentName(r.info.packageName, r.info.name);
3590 }
3591 w.thisTime = thisTime;
3592 w.totalTime = totalTime;
3593 }
3594 notify();
3595 }
3596
3597 void reportActivityVisibleLocked(HistoryRecord r) {
3598 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3599 WaitResult w = mWaitingActivityVisible.get(i);
3600 w.timeout = false;
3601 if (r != null) {
3602 w.who = new ComponentName(r.info.packageName, r.info.name);
3603 }
3604 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3605 w.thisTime = w.totalTime;
3606 }
3607 notify();
3608 }
3609
3610 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3612 int grantedMode, IBinder resultTo,
3613 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003614 boolean debug, WaitResult outResult) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 // Refuse possible leaked file descriptors
3616 if (intent != null && intent.hasFileDescriptors()) {
3617 throw new IllegalArgumentException("File descriptors passed in Intent");
3618 }
3619
The Android Open Source Project4df24232009-03-05 14:34:35 -08003620 final boolean componentSpecified = intent.getComponent() != null;
3621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622 // Don't modify the client's object!
3623 intent = new Intent(intent);
3624
3625 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 ActivityInfo aInfo;
3627 try {
3628 ResolveInfo rInfo =
3629 ActivityThread.getPackageManager().resolveIntent(
3630 intent, resolvedType,
3631 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003632 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 aInfo = rInfo != null ? rInfo.activityInfo : null;
3634 } catch (RemoteException e) {
3635 aInfo = null;
3636 }
3637
3638 if (aInfo != null) {
3639 // Store the found target back into the intent, because now that
3640 // we have it we never want to do this again. For example, if the
3641 // user navigates back to this point in the history, we should
3642 // always restart the exact same activity.
3643 intent.setComponent(new ComponentName(
3644 aInfo.applicationInfo.packageName, aInfo.name));
3645
3646 // Don't debug things in the system process
3647 if (debug) {
3648 if (!aInfo.processName.equals("system")) {
3649 setDebugApp(aInfo.processName, true, false);
3650 }
3651 }
3652 }
3653
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003654 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003655 int callingPid;
3656 int callingUid;
3657 if (caller == null) {
3658 callingPid = Binder.getCallingPid();
3659 callingUid = Binder.getCallingUid();
3660 } else {
3661 callingPid = callingUid = -1;
3662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 final long origId = Binder.clearCallingIdentity();
3664 int res = startActivityLocked(caller, intent, resolvedType,
3665 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003666 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003667 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003669
3670 if (outResult != null) {
3671 outResult.result = res;
3672 if (res == IActivityManager.START_SUCCESS) {
3673 mWaitingActivityLaunched.add(outResult);
3674 do {
3675 try {
3676 wait();
3677 } catch (InterruptedException e) {
3678 }
3679 } while (!outResult.timeout && outResult.who == null);
3680 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3681 HistoryRecord r = this.topRunningActivityLocked(null);
3682 if (r.nowVisible) {
3683 outResult.timeout = false;
3684 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3685 outResult.totalTime = 0;
3686 outResult.thisTime = 0;
3687 } else {
3688 outResult.thisTime = SystemClock.uptimeMillis();
3689 mWaitingActivityVisible.add(outResult);
3690 do {
3691 try {
3692 wait();
3693 } catch (InterruptedException e) {
3694 }
3695 } while (!outResult.timeout && outResult.who == null);
3696 }
3697 }
3698 }
3699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003700 return res;
3701 }
3702 }
3703
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003704 public final int startActivity(IApplicationThread caller,
3705 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3706 int grantedMode, IBinder resultTo,
3707 String resultWho, int requestCode, boolean onlyIfNeeded,
3708 boolean debug) {
3709 return startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3710 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, null);
3711 }
3712
3713 public final WaitResult startActivityAndWait(IApplicationThread caller,
3714 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3715 int grantedMode, IBinder resultTo,
3716 String resultWho, int requestCode, boolean onlyIfNeeded,
3717 boolean debug) {
3718 WaitResult res = new WaitResult();
3719 startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3720 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, res);
3721 return res;
3722 }
3723
3724 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003725 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003726 IBinder resultTo, String resultWho, int requestCode,
3727 int flagsMask, int flagsValues) {
3728 // Refuse possible leaked file descriptors
3729 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3730 throw new IllegalArgumentException("File descriptors passed in Intent");
3731 }
3732
3733 IIntentSender sender = intent.getTarget();
3734 if (!(sender instanceof PendingIntentRecord)) {
3735 throw new IllegalArgumentException("Bad PendingIntent object");
3736 }
3737
3738 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003739
3740 synchronized (this) {
3741 // If this is coming from the currently resumed activity, it is
3742 // effectively saying that app switches are allowed at this point.
3743 if (mResumedActivity != null
3744 && mResumedActivity.info.applicationInfo.uid ==
3745 Binder.getCallingUid()) {
3746 mAppSwitchesAllowedTime = 0;
3747 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003748 }
3749
3750 return pir.sendInner(0, fillInIntent, resolvedType,
3751 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3752 }
3753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 public boolean startNextMatchingActivity(IBinder callingActivity,
3755 Intent intent) {
3756 // Refuse possible leaked file descriptors
3757 if (intent != null && intent.hasFileDescriptors() == true) {
3758 throw new IllegalArgumentException("File descriptors passed in Intent");
3759 }
3760
3761 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003762 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 if (index < 0) {
3764 return false;
3765 }
3766 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3767 if (r.app == null || r.app.thread == null) {
3768 // The caller is not running... d'oh!
3769 return false;
3770 }
3771 intent = new Intent(intent);
3772 // The caller is not allowed to change the data.
3773 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3774 // And we are resetting to find the next component...
3775 intent.setComponent(null);
3776
3777 ActivityInfo aInfo = null;
3778 try {
3779 List<ResolveInfo> resolves =
3780 ActivityThread.getPackageManager().queryIntentActivities(
3781 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003782 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783
3784 // Look for the original activity in the list...
3785 final int N = resolves != null ? resolves.size() : 0;
3786 for (int i=0; i<N; i++) {
3787 ResolveInfo rInfo = resolves.get(i);
3788 if (rInfo.activityInfo.packageName.equals(r.packageName)
3789 && rInfo.activityInfo.name.equals(r.info.name)) {
3790 // We found the current one... the next matching is
3791 // after it.
3792 i++;
3793 if (i<N) {
3794 aInfo = resolves.get(i).activityInfo;
3795 }
3796 break;
3797 }
3798 }
3799 } catch (RemoteException e) {
3800 }
3801
3802 if (aInfo == null) {
3803 // Nobody who is next!
3804 return false;
3805 }
3806
3807 intent.setComponent(new ComponentName(
3808 aInfo.applicationInfo.packageName, aInfo.name));
3809 intent.setFlags(intent.getFlags()&~(
3810 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3811 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3812 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3813 Intent.FLAG_ACTIVITY_NEW_TASK));
3814
3815 // Okay now we need to start the new activity, replacing the
3816 // currently running activity. This is a little tricky because
3817 // we want to start the new one as if the current one is finished,
3818 // but not finish the current one first so that there is no flicker.
3819 // And thus...
3820 final boolean wasFinishing = r.finishing;
3821 r.finishing = true;
3822
3823 // Propagate reply information over to the new activity.
3824 final HistoryRecord resultTo = r.resultTo;
3825 final String resultWho = r.resultWho;
3826 final int requestCode = r.requestCode;
3827 r.resultTo = null;
3828 if (resultTo != null) {
3829 resultTo.removeResultsLocked(r, resultWho, requestCode);
3830 }
3831
3832 final long origId = Binder.clearCallingIdentity();
3833 // XXX we are not dealing with propagating grantedUriPermissions...
3834 // those are not yet exposed to user code, so there is no need.
3835 int res = startActivityLocked(r.app.thread, intent,
3836 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003837 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 Binder.restoreCallingIdentity(origId);
3839
3840 r.finishing = wasFinishing;
3841 if (res != START_SUCCESS) {
3842 return false;
3843 }
3844 return true;
3845 }
3846 }
3847
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003848 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003849 Intent intent, String resolvedType, IBinder resultTo,
3850 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003851
3852 // This is so super not safe, that only the system (or okay root)
3853 // can do it.
3854 final int callingUid = Binder.getCallingUid();
3855 if (callingUid != 0 && callingUid != Process.myUid()) {
3856 throw new SecurityException(
3857 "startActivityInPackage only available to the system");
3858 }
3859
The Android Open Source Project4df24232009-03-05 14:34:35 -08003860 final boolean componentSpecified = intent.getComponent() != null;
3861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 // Don't modify the client's object!
3863 intent = new Intent(intent);
3864
3865 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 ActivityInfo aInfo;
3867 try {
3868 ResolveInfo rInfo =
3869 ActivityThread.getPackageManager().resolveIntent(
3870 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003871 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 aInfo = rInfo != null ? rInfo.activityInfo : null;
3873 } catch (RemoteException e) {
3874 aInfo = null;
3875 }
3876
3877 if (aInfo != null) {
3878 // Store the found target back into the intent, because now that
3879 // we have it we never want to do this again. For example, if the
3880 // user navigates back to this point in the history, we should
3881 // always restart the exact same activity.
3882 intent.setComponent(new ComponentName(
3883 aInfo.applicationInfo.packageName, aInfo.name));
3884 }
3885
3886 synchronized(this) {
3887 return startActivityLocked(null, intent, resolvedType,
3888 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003889 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 }
3891 }
3892
3893 private final void addRecentTask(TaskRecord task) {
3894 // Remove any existing entries that are the same kind of task.
3895 int N = mRecentTasks.size();
3896 for (int i=0; i<N; i++) {
3897 TaskRecord tr = mRecentTasks.get(i);
3898 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3899 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3900 mRecentTasks.remove(i);
3901 i--;
3902 N--;
3903 if (task.intent == null) {
3904 // If the new recent task we are adding is not fully
3905 // specified, then replace it with the existing recent task.
3906 task = tr;
3907 }
3908 }
3909 }
3910 if (N >= MAX_RECENT_TASKS) {
3911 mRecentTasks.remove(N-1);
3912 }
3913 mRecentTasks.add(0, task);
3914 }
3915
3916 public void setRequestedOrientation(IBinder token,
3917 int requestedOrientation) {
3918 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003919 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 if (index < 0) {
3921 return;
3922 }
3923 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3924 final long origId = Binder.clearCallingIdentity();
3925 mWindowManager.setAppOrientation(r, requestedOrientation);
3926 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003927 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 r.mayFreezeScreenLocked(r.app) ? r : null);
3929 if (config != null) {
3930 r.frozenBeforeDestroy = true;
3931 if (!updateConfigurationLocked(config, r)) {
3932 resumeTopActivityLocked(null);
3933 }
3934 }
3935 Binder.restoreCallingIdentity(origId);
3936 }
3937 }
3938
3939 public int getRequestedOrientation(IBinder token) {
3940 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003941 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 if (index < 0) {
3943 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3944 }
3945 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3946 return mWindowManager.getAppOrientation(r);
3947 }
3948 }
3949
3950 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003951 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3953 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3954 if (!r.finishing) {
3955 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3956 "no-history");
3957 }
3958 } else if (r.app != null && r.app.thread != null) {
3959 if (mFocusedActivity == r) {
3960 setFocusedActivityLocked(topRunningActivityLocked(null));
3961 }
3962 r.resumeKeyDispatchingLocked();
3963 try {
3964 r.stopped = false;
3965 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003966 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967 TAG, "Stopping visible=" + r.visible + " for " + r);
3968 if (!r.visible) {
3969 mWindowManager.setAppVisibility(r, false);
3970 }
3971 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3972 } catch (Exception e) {
3973 // Maybe just ignore exceptions here... if the process
3974 // has crashed, our death notification will clean things
3975 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003976 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 // Just in case, assume it to be stopped.
3978 r.stopped = true;
3979 r.state = ActivityState.STOPPED;
3980 if (r.configDestroy) {
3981 destroyActivityLocked(r, true);
3982 }
3983 }
3984 }
3985 }
3986
3987 /**
3988 * @return Returns true if the activity is being finished, false if for
3989 * some reason it is being left as-is.
3990 */
3991 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3992 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003993 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003994 TAG, "Finishing activity: token=" + token
3995 + ", result=" + resultCode + ", data=" + resultData);
3996
Dianne Hackborn75b03852009-06-12 15:43:26 -07003997 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003998 if (index < 0) {
3999 return false;
4000 }
4001 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4002
4003 // Is this the last activity left?
4004 boolean lastActivity = true;
4005 for (int i=mHistory.size()-1; i>=0; i--) {
4006 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4007 if (!p.finishing && p != r) {
4008 lastActivity = false;
4009 break;
4010 }
4011 }
4012
4013 // If this is the last activity, but it is the home activity, then
4014 // just don't finish it.
4015 if (lastActivity) {
4016 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4017 return false;
4018 }
4019 }
4020
4021 finishActivityLocked(r, index, resultCode, resultData, reason);
4022 return true;
4023 }
4024
4025 /**
4026 * @return Returns true if this activity has been removed from the history
4027 * list, or false if it is still in the list and will be removed later.
4028 */
4029 private final boolean finishActivityLocked(HistoryRecord r, int index,
4030 int resultCode, Intent resultData, String reason) {
4031 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004032 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 return false;
4034 }
4035
4036 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004037 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 System.identityHashCode(r),
4039 r.task.taskId, r.shortComponentName, reason);
4040 r.task.numActivities--;
4041 if (r.frontOfTask && index < (mHistory.size()-1)) {
4042 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4043 if (next.task == r.task) {
4044 next.frontOfTask = true;
4045 }
4046 }
4047
4048 r.pauseKeyDispatchingLocked();
4049 if (mFocusedActivity == r) {
4050 setFocusedActivityLocked(topRunningActivityLocked(null));
4051 }
4052
4053 // send the result
4054 HistoryRecord resultTo = r.resultTo;
4055 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004056 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004057 + " who=" + r.resultWho + " req=" + r.requestCode
4058 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004059 if (r.info.applicationInfo.uid > 0) {
4060 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4061 r.packageName, resultData, r);
4062 }
4063 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4064 resultData);
4065 r.resultTo = null;
4066 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004067 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004068
4069 // Make sure this HistoryRecord is not holding on to other resources,
4070 // because clients have remote IPC references to this object so we
4071 // can't assume that will go away and want to avoid circular IPC refs.
4072 r.results = null;
4073 r.pendingResults = null;
4074 r.newIntents = null;
4075 r.icicle = null;
4076
4077 if (mPendingThumbnails.size() > 0) {
4078 // There are clients waiting to receive thumbnails so, in case
4079 // this is an activity that someone is waiting for, add it
4080 // to the pending list so we can correctly update the clients.
4081 mCancelledThumbnails.add(r);
4082 }
4083
4084 if (mResumedActivity == r) {
4085 boolean endTask = index <= 0
4086 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004087 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 "Prepare close transition: finishing " + r);
4089 mWindowManager.prepareAppTransition(endTask
4090 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4091 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4092
4093 // Tell window manager to prepare for this one to be removed.
4094 mWindowManager.setAppVisibility(r, false);
4095
4096 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004097 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4098 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 startPausingLocked(false, false);
4100 }
4101
4102 } else if (r.state != ActivityState.PAUSING) {
4103 // If the activity is PAUSING, we will complete the finish once
4104 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004105 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 return finishCurrentActivityLocked(r, index,
4107 FINISH_AFTER_PAUSE) == null;
4108 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004109 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004110 }
4111
4112 return false;
4113 }
4114
4115 private static final int FINISH_IMMEDIATELY = 0;
4116 private static final int FINISH_AFTER_PAUSE = 1;
4117 private static final int FINISH_AFTER_VISIBLE = 2;
4118
4119 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4120 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004121 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004122 if (index < 0) {
4123 return null;
4124 }
4125
4126 return finishCurrentActivityLocked(r, index, mode);
4127 }
4128
4129 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4130 int index, int mode) {
4131 // First things first: if this activity is currently visible,
4132 // and the resumed activity is not yet visible, then hold off on
4133 // finishing until the resumed one becomes visible.
4134 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4135 if (!mStoppingActivities.contains(r)) {
4136 mStoppingActivities.add(r);
4137 if (mStoppingActivities.size() > 3) {
4138 // If we already have a few activities waiting to stop,
4139 // then give up on things going idle and start clearing
4140 // them out.
4141 Message msg = Message.obtain();
4142 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4143 mHandler.sendMessage(msg);
4144 }
4145 }
4146 r.state = ActivityState.STOPPING;
4147 updateOomAdjLocked();
4148 return r;
4149 }
4150
4151 // make sure the record is cleaned out of other places.
4152 mStoppingActivities.remove(r);
4153 mWaitingVisibleActivities.remove(r);
4154 if (mResumedActivity == r) {
4155 mResumedActivity = null;
4156 }
4157 final ActivityState prevState = r.state;
4158 r.state = ActivityState.FINISHING;
4159
4160 if (mode == FINISH_IMMEDIATELY
4161 || prevState == ActivityState.STOPPED
4162 || prevState == ActivityState.INITIALIZING) {
4163 // If this activity is already stopped, we can just finish
4164 // it right now.
4165 return destroyActivityLocked(r, true) ? null : r;
4166 } else {
4167 // Need to go through the full pause cycle to get this
4168 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004169 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 mFinishingActivities.add(r);
4171 resumeTopActivityLocked(null);
4172 }
4173 return r;
4174 }
4175
4176 /**
4177 * This is the internal entry point for handling Activity.finish().
4178 *
4179 * @param token The Binder token referencing the Activity we want to finish.
4180 * @param resultCode Result code, if any, from this Activity.
4181 * @param resultData Result data (Intent), if any, from this Activity.
4182 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004183 * @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 -08004184 */
4185 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4186 // Refuse possible leaked file descriptors
4187 if (resultData != null && resultData.hasFileDescriptors() == true) {
4188 throw new IllegalArgumentException("File descriptors passed in Intent");
4189 }
4190
4191 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004192 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 // Find the first activity that is not finishing.
4194 HistoryRecord next = topRunningActivityLocked(token, 0);
4195 if (next != null) {
4196 // ask watcher if this is allowed
4197 boolean resumeOK = true;
4198 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004199 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004201 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 }
4203
4204 if (!resumeOK) {
4205 return false;
4206 }
4207 }
4208 }
4209 final long origId = Binder.clearCallingIdentity();
4210 boolean res = requestFinishActivityLocked(token, resultCode,
4211 resultData, "app-request");
4212 Binder.restoreCallingIdentity(origId);
4213 return res;
4214 }
4215 }
4216
4217 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4218 String resultWho, int requestCode, int resultCode, Intent data) {
4219
4220 if (callingUid > 0) {
4221 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4222 data, r);
4223 }
4224
Joe Onorato8a9b2202010-02-26 18:56:32 -08004225 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004226 + " : who=" + resultWho + " req=" + requestCode
4227 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004228 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4229 try {
4230 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4231 list.add(new ResultInfo(resultWho, requestCode,
4232 resultCode, data));
4233 r.app.thread.scheduleSendResult(r, list);
4234 return;
4235 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004236 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 }
4238 }
4239
4240 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4241 }
4242
4243 public final void finishSubActivity(IBinder token, String resultWho,
4244 int requestCode) {
4245 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004246 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 if (index < 0) {
4248 return;
4249 }
4250 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4251
4252 final long origId = Binder.clearCallingIdentity();
4253
4254 int i;
4255 for (i=mHistory.size()-1; i>=0; i--) {
4256 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4257 if (r.resultTo == self && r.requestCode == requestCode) {
4258 if ((r.resultWho == null && resultWho == null) ||
4259 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4260 finishActivityLocked(r, i,
4261 Activity.RESULT_CANCELED, null, "request-sub");
4262 }
4263 }
4264 }
4265
4266 Binder.restoreCallingIdentity(origId);
4267 }
4268 }
4269
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004270 public void overridePendingTransition(IBinder token, String packageName,
4271 int enterAnim, int exitAnim) {
4272 synchronized(this) {
4273 int index = indexOfTokenLocked(token);
4274 if (index < 0) {
4275 return;
4276 }
4277 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4278
4279 final long origId = Binder.clearCallingIdentity();
4280
4281 if (self.state == ActivityState.RESUMED
4282 || self.state == ActivityState.PAUSING) {
4283 mWindowManager.overridePendingAppTransition(packageName,
4284 enterAnim, exitAnim);
4285 }
4286
4287 Binder.restoreCallingIdentity(origId);
4288 }
4289 }
4290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004291 /**
4292 * Perform clean-up of service connections in an activity record.
4293 */
4294 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4295 // Throw away any services that have been bound by this activity.
4296 if (r.connections != null) {
4297 Iterator<ConnectionRecord> it = r.connections.iterator();
4298 while (it.hasNext()) {
4299 ConnectionRecord c = it.next();
4300 removeConnectionLocked(c, null, r);
4301 }
4302 r.connections = null;
4303 }
4304 }
4305
4306 /**
4307 * Perform the common clean-up of an activity record. This is called both
4308 * as part of destroyActivityLocked() (when destroying the client-side
4309 * representation) and cleaning things up as a result of its hosting
4310 * processing going away, in which case there is no remaining client-side
4311 * state to destroy so only the cleanup here is needed.
4312 */
4313 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4314 if (mResumedActivity == r) {
4315 mResumedActivity = null;
4316 }
4317 if (mFocusedActivity == r) {
4318 mFocusedActivity = null;
4319 }
4320
4321 r.configDestroy = false;
4322 r.frozenBeforeDestroy = false;
4323
4324 // Make sure this record is no longer in the pending finishes list.
4325 // This could happen, for example, if we are trimming activities
4326 // down to the max limit while they are still waiting to finish.
4327 mFinishingActivities.remove(r);
4328 mWaitingVisibleActivities.remove(r);
4329
4330 // Remove any pending results.
4331 if (r.finishing && r.pendingResults != null) {
4332 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4333 PendingIntentRecord rec = apr.get();
4334 if (rec != null) {
4335 cancelIntentSenderLocked(rec, false);
4336 }
4337 }
4338 r.pendingResults = null;
4339 }
4340
4341 if (cleanServices) {
4342 cleanUpActivityServicesLocked(r);
4343 }
4344
4345 if (mPendingThumbnails.size() > 0) {
4346 // There are clients waiting to receive thumbnails so, in case
4347 // this is an activity that someone is waiting for, add it
4348 // to the pending list so we can correctly update the clients.
4349 mCancelledThumbnails.add(r);
4350 }
4351
4352 // Get rid of any pending idle timeouts.
4353 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4354 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4355 }
4356
4357 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4358 if (r.state != ActivityState.DESTROYED) {
4359 mHistory.remove(r);
4360 r.inHistory = false;
4361 r.state = ActivityState.DESTROYED;
4362 mWindowManager.removeAppToken(r);
4363 if (VALIDATE_TOKENS) {
4364 mWindowManager.validateAppTokens(mHistory);
4365 }
4366 cleanUpActivityServicesLocked(r);
4367 removeActivityUriPermissionsLocked(r);
4368 }
4369 }
4370
4371 /**
4372 * Destroy the current CLIENT SIDE instance of an activity. This may be
4373 * called both when actually finishing an activity, or when performing
4374 * a configuration switch where we destroy the current client-side object
4375 * but then create a new client-side object for this same HistoryRecord.
4376 */
4377 private final boolean destroyActivityLocked(HistoryRecord r,
4378 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004379 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 TAG, "Removing activity: token=" + r
4381 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004382 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 System.identityHashCode(r),
4384 r.task.taskId, r.shortComponentName);
4385
4386 boolean removedFromHistory = false;
4387
4388 cleanUpActivityLocked(r, false);
4389
Dianne Hackborn03abb812010-01-04 18:43:19 -08004390 final boolean hadApp = r.app != null;
4391
4392 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393 if (removeFromApp) {
4394 int idx = r.app.activities.indexOf(r);
4395 if (idx >= 0) {
4396 r.app.activities.remove(idx);
4397 }
4398 if (r.persistent) {
4399 decPersistentCountLocked(r.app);
4400 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004401 if (r.app.activities.size() == 0) {
4402 // No longer have activities, so update location in
4403 // LRU list.
4404 updateLruProcessLocked(r.app, true, false);
4405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 }
4407
4408 boolean skipDestroy = false;
4409
4410 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004411 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4413 r.configChangeFlags);
4414 } catch (Exception e) {
4415 // We can just ignore exceptions here... if the process
4416 // has crashed, our death notification will clean things
4417 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004418 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004419 if (r.finishing) {
4420 removeActivityFromHistoryLocked(r);
4421 removedFromHistory = true;
4422 skipDestroy = true;
4423 }
4424 }
4425
4426 r.app = null;
4427 r.nowVisible = false;
4428
4429 if (r.finishing && !skipDestroy) {
4430 r.state = ActivityState.DESTROYING;
4431 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4432 msg.obj = r;
4433 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4434 } else {
4435 r.state = ActivityState.DESTROYED;
4436 }
4437 } else {
4438 // remove this record from the history.
4439 if (r.finishing) {
4440 removeActivityFromHistoryLocked(r);
4441 removedFromHistory = true;
4442 } else {
4443 r.state = ActivityState.DESTROYED;
4444 }
4445 }
4446
4447 r.configChangeFlags = 0;
4448
Dianne Hackborn03abb812010-01-04 18:43:19 -08004449 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004450 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 }
4452
4453 return removedFromHistory;
4454 }
4455
Dianne Hackborn03abb812010-01-04 18:43:19 -08004456 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004458 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004459 TAG, "Removing app " + app + " from list " + list
4460 + " with " + i + " entries");
4461 while (i > 0) {
4462 i--;
4463 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004464 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4466 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004467 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 list.remove(i);
4469 }
4470 }
4471 }
4472
4473 /**
4474 * Main function for removing an existing process from the activity manager
4475 * as a result of that process going away. Clears out all connections
4476 * to the process.
4477 */
4478 private final void handleAppDiedLocked(ProcessRecord app,
4479 boolean restarting) {
4480 cleanUpApplicationRecordLocked(app, restarting, -1);
4481 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004482 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004483 }
4484
4485 // Just in case...
4486 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004487 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 mPausingActivity = null;
4489 }
4490 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4491 mLastPausedActivity = null;
4492 }
4493
4494 // Remove this application's activities from active lists.
4495 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4496 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4497 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4498 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4499
4500 boolean atTop = true;
4501 boolean hasVisibleActivities = false;
4502
4503 // Clean out the history list.
4504 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004505 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 TAG, "Removing app " + app + " from history with " + i + " entries");
4507 while (i > 0) {
4508 i--;
4509 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004510 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4512 if (r.app == app) {
4513 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004514 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515 TAG, "Removing this entry! frozen=" + r.haveState
4516 + " finishing=" + r.finishing);
4517 mHistory.remove(i);
4518
4519 r.inHistory = false;
4520 mWindowManager.removeAppToken(r);
4521 if (VALIDATE_TOKENS) {
4522 mWindowManager.validateAppTokens(mHistory);
4523 }
4524 removeActivityUriPermissionsLocked(r);
4525
4526 } else {
4527 // We have the current state for this activity, so
4528 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004529 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004530 TAG, "Keeping entry, setting app to null");
4531 if (r.visible) {
4532 hasVisibleActivities = true;
4533 }
4534 r.app = null;
4535 r.nowVisible = false;
4536 if (!r.haveState) {
4537 r.icicle = null;
4538 }
4539 }
4540
4541 cleanUpActivityLocked(r, true);
4542 r.state = ActivityState.STOPPED;
4543 }
4544 atTop = false;
4545 }
4546
4547 app.activities.clear();
4548
4549 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004550 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 + " running instrumentation " + app.instrumentationClass);
4552 Bundle info = new Bundle();
4553 info.putString("shortMsg", "Process crashed.");
4554 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4555 }
4556
4557 if (!restarting) {
4558 if (!resumeTopActivityLocked(null)) {
4559 // If there was nothing to resume, and we are not already
4560 // restarting this process, but there is a visible activity that
4561 // is hosted by the process... then make sure all visible
4562 // activities are running, taking care of restarting this
4563 // process.
4564 if (hasVisibleActivities) {
4565 ensureActivitiesVisibleLocked(null, 0);
4566 }
4567 }
4568 }
4569 }
4570
4571 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4572 IBinder threadBinder = thread.asBinder();
4573
4574 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004575 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4576 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004577 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4578 return i;
4579 }
4580 }
4581 return -1;
4582 }
4583
4584 private final ProcessRecord getRecordForAppLocked(
4585 IApplicationThread thread) {
4586 if (thread == null) {
4587 return null;
4588 }
4589
4590 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004591 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004592 }
4593
4594 private final void appDiedLocked(ProcessRecord app, int pid,
4595 IApplicationThread thread) {
4596
4597 mProcDeaths[0]++;
4598
Magnus Edlund7bb25812010-02-24 15:45:06 +01004599 // Clean up already done if the process has been re-started.
4600 if (app.pid == pid && app.thread != null &&
4601 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004602 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004604 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004605 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 TAG, "Dying app: " + app + ", pid: " + pid
4607 + ", thread: " + thread.asBinder());
4608 boolean doLowMem = app.instrumentationClass == null;
4609 handleAppDiedLocked(app, false);
4610
4611 if (doLowMem) {
4612 // If there are no longer any background processes running,
4613 // and the app that died was not running instrumentation,
4614 // then tell everyone we are now low on memory.
4615 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004616 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4617 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4619 haveBg = true;
4620 break;
4621 }
4622 }
4623
4624 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004625 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004626 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004627 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004628 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4629 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004630 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004631 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4632 // The low memory report is overriding any current
4633 // state for a GC request. Make sure to do
4634 // visible/foreground processes first.
4635 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4636 rec.lastRequestedGc = 0;
4637 } else {
4638 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004639 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004640 rec.reportLowMemory = true;
4641 rec.lastLowMemory = now;
4642 mProcessesToGc.remove(rec);
4643 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 }
4645 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004646 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647 }
4648 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004649 } else if (app.pid != pid) {
4650 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004651 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004652 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004653 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004654 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004655 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 + thread.asBinder());
4657 }
4658 }
4659
Dan Egnor42471dd2010-01-07 17:25:22 -08004660 /**
4661 * If a stack trace dump file is configured, dump process stack traces.
4662 * @param pids of dalvik VM processes to dump stack traces for
4663 * @return file containing stack traces, or null if no dump file is configured
4664 */
4665 private static File dumpStackTraces(ArrayList<Integer> pids) {
4666 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4667 if (tracesPath == null || tracesPath.length() == 0) {
4668 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004669 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004670
4671 File tracesFile = new File(tracesPath);
4672 try {
4673 File tracesDir = tracesFile.getParentFile();
4674 if (!tracesDir.exists()) tracesFile.mkdirs();
4675 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4676
4677 if (tracesFile.exists()) tracesFile.delete();
4678 tracesFile.createNewFile();
4679 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4680 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004681 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004682 return null;
4683 }
4684
4685 // Use a FileObserver to detect when traces finish writing.
4686 // The order of traces is considered important to maintain for legibility.
4687 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4688 public synchronized void onEvent(int event, String path) { notify(); }
4689 };
4690
4691 try {
4692 observer.startWatching();
4693 int num = pids.size();
4694 for (int i = 0; i < num; i++) {
4695 synchronized (observer) {
4696 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4697 observer.wait(200); // Wait for write-close, give up after 200msec
4698 }
4699 }
4700 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004701 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004702 } finally {
4703 observer.stopWatching();
4704 }
4705
4706 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 }
4708
Dan Egnor42471dd2010-01-07 17:25:22 -08004709 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4710 HistoryRecord parent, final String annotation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 if (app.notResponding || app.crashing) {
4712 return;
4713 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004716 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4717 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004718
Dan Egnor42471dd2010-01-07 17:25:22 -08004719 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4720 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4721 pids.add(app.pid);
4722
4723 int parentPid = app.pid;
4724 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4725 if (parentPid != app.pid) pids.add(parentPid);
4726
4727 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4728
4729 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4730 ProcessRecord r = mLruProcesses.get(i);
4731 if (r != null && r.thread != null) {
4732 int pid = r.pid;
4733 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 }
4735 }
4736
Dan Egnor42471dd2010-01-07 17:25:22 -08004737 File tracesFile = dumpStackTraces(pids);
4738
4739 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004740 StringBuilder info = mStringBuilder;
4741 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004742 info.append("ANR in ").append(app.processName);
4743 if (activity != null && activity.shortComponentName != null) {
4744 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004745 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004746 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004748 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004750 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004751 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004753
Dan Egnor42471dd2010-01-07 17:25:22 -08004754 String cpuInfo = null;
4755 if (MONITOR_CPU_USAGE) {
4756 updateCpuStatsNow();
4757 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4758 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759 }
4760
Joe Onorato8a9b2202010-02-26 18:56:32 -08004761 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004762 if (tracesFile == null) {
4763 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4764 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4765 }
4766
4767 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4768
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004769 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004771 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4772 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004774 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4775 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004776 }
4777 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004778 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004779 }
4780 }
4781
Dan Egnor42471dd2010-01-07 17:25:22 -08004782 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4783 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4784 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4785 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4786 Process.killProcess(app.pid);
4787 return;
4788 }
4789
4790 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 makeAppNotRespondingLocked(app,
4792 activity != null ? activity.shortComponentName : null,
4793 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004794 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004795
4796 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 Message msg = Message.obtain();
4798 HashMap map = new HashMap();
4799 msg.what = SHOW_NOT_RESPONDING_MSG;
4800 msg.obj = map;
4801 map.put("app", app);
4802 if (activity != null) {
4803 map.put("activity", activity);
4804 }
4805
4806 mHandler.sendMessage(msg);
4807 return;
4808 }
4809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004810 private final void decPersistentCountLocked(ProcessRecord app)
4811 {
4812 app.persistentActivities--;
4813 if (app.persistentActivities > 0) {
4814 // Still more of 'em...
4815 return;
4816 }
4817 if (app.persistent) {
4818 // Ah, but the application itself is persistent. Whatever!
4819 return;
4820 }
4821
4822 // App is no longer persistent... make sure it and the ones
4823 // following it in the LRU list have the correc oom_adj.
4824 updateOomAdjLocked();
4825 }
4826
4827 public void setPersistent(IBinder token, boolean isPersistent) {
4828 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4829 != PackageManager.PERMISSION_GRANTED) {
4830 String msg = "Permission Denial: setPersistent() from pid="
4831 + Binder.getCallingPid()
4832 + ", uid=" + Binder.getCallingUid()
4833 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004834 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 throw new SecurityException(msg);
4836 }
4837
4838 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004839 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 if (index < 0) {
4841 return;
4842 }
4843 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4844 ProcessRecord app = r.app;
4845
Joe Onorato8a9b2202010-02-26 18:56:32 -08004846 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 TAG, "Setting persistence " + isPersistent + ": " + r);
4848
4849 if (isPersistent) {
4850 if (r.persistent) {
4851 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004852 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 return;
4854 }
4855 r.persistent = true;
4856 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004857 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 if (app.persistentActivities > 1) {
4859 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004860 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004861 return;
4862 }
4863 if (app.persistent) {
4864 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004865 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 return;
4867 }
4868
4869 // App is now persistent... make sure it and the ones
4870 // following it now have the correct oom_adj.
4871 final long origId = Binder.clearCallingIdentity();
4872 updateOomAdjLocked();
4873 Binder.restoreCallingIdentity(origId);
4874
4875 } else {
4876 if (!r.persistent) {
4877 // Okay okay, I heard you already!
4878 return;
4879 }
4880 r.persistent = false;
4881 final long origId = Binder.clearCallingIdentity();
4882 decPersistentCountLocked(app);
4883 Binder.restoreCallingIdentity(origId);
4884
4885 }
4886 }
4887 }
4888
4889 public boolean clearApplicationUserData(final String packageName,
4890 final IPackageDataObserver observer) {
4891 int uid = Binder.getCallingUid();
4892 int pid = Binder.getCallingPid();
4893 long callingId = Binder.clearCallingIdentity();
4894 try {
4895 IPackageManager pm = ActivityThread.getPackageManager();
4896 int pkgUid = -1;
4897 synchronized(this) {
4898 try {
4899 pkgUid = pm.getPackageUid(packageName);
4900 } catch (RemoteException e) {
4901 }
4902 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004903 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004904 return false;
4905 }
4906 if (uid == pkgUid || checkComponentPermission(
4907 android.Manifest.permission.CLEAR_APP_USER_DATA,
4908 pid, uid, -1)
4909 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004910 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004911 } else {
4912 throw new SecurityException(pid+" does not have permission:"+
4913 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4914 "for process:"+packageName);
4915 }
4916 }
4917
4918 try {
4919 //clear application user data
4920 pm.clearApplicationUserData(packageName, observer);
4921 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4922 Uri.fromParts("package", packageName, null));
4923 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4924 broadcastIntentLocked(null, null, intent,
4925 null, null, 0, null, null, null,
4926 false, false, MY_PID, Process.SYSTEM_UID);
4927 } catch (RemoteException e) {
4928 }
4929 } finally {
4930 Binder.restoreCallingIdentity(callingId);
4931 }
4932 return true;
4933 }
4934
Dianne Hackborn03abb812010-01-04 18:43:19 -08004935 public void killBackgroundProcesses(final String packageName) {
4936 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4937 != PackageManager.PERMISSION_GRANTED &&
4938 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4939 != PackageManager.PERMISSION_GRANTED) {
4940 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 + Binder.getCallingPid()
4942 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004943 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004944 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 throw new SecurityException(msg);
4946 }
4947
4948 long callingId = Binder.clearCallingIdentity();
4949 try {
4950 IPackageManager pm = ActivityThread.getPackageManager();
4951 int pkgUid = -1;
4952 synchronized(this) {
4953 try {
4954 pkgUid = pm.getPackageUid(packageName);
4955 } catch (RemoteException e) {
4956 }
4957 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004958 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 return;
4960 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004961 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004962 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004963 }
4964 } finally {
4965 Binder.restoreCallingIdentity(callingId);
4966 }
4967 }
4968
4969 public void forceStopPackage(final String packageName) {
4970 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4971 != PackageManager.PERMISSION_GRANTED) {
4972 String msg = "Permission Denial: forceStopPackage() from pid="
4973 + Binder.getCallingPid()
4974 + ", uid=" + Binder.getCallingUid()
4975 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004976 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004977 throw new SecurityException(msg);
4978 }
4979
4980 long callingId = Binder.clearCallingIdentity();
4981 try {
4982 IPackageManager pm = ActivityThread.getPackageManager();
4983 int pkgUid = -1;
4984 synchronized(this) {
4985 try {
4986 pkgUid = pm.getPackageUid(packageName);
4987 } catch (RemoteException e) {
4988 }
4989 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004990 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004991 return;
4992 }
4993 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004994 }
4995 } finally {
4996 Binder.restoreCallingIdentity(callingId);
4997 }
4998 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004999
5000 /*
5001 * The pkg name and uid have to be specified.
5002 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5003 */
5004 public void killApplicationWithUid(String pkg, int uid) {
5005 if (pkg == null) {
5006 return;
5007 }
5008 // Make sure the uid is valid.
5009 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005010 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005011 return;
5012 }
5013 int callerUid = Binder.getCallingUid();
5014 // Only the system server can kill an application
5015 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005016 // Post an aysnc message to kill the application
5017 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5018 msg.arg1 = uid;
5019 msg.arg2 = 0;
5020 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005021 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005022 } else {
5023 throw new SecurityException(callerUid + " cannot kill pkg: " +
5024 pkg);
5025 }
5026 }
5027
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005028 public void closeSystemDialogs(String reason) {
5029 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5030 if (reason != null) {
5031 intent.putExtra("reason", reason);
5032 }
5033
5034 final int uid = Binder.getCallingUid();
5035 final long origId = Binder.clearCallingIdentity();
5036 synchronized (this) {
5037 int i = mWatchers.beginBroadcast();
5038 while (i > 0) {
5039 i--;
5040 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5041 if (w != null) {
5042 try {
5043 w.closingSystemDialogs(reason);
5044 } catch (RemoteException e) {
5045 }
5046 }
5047 }
5048 mWatchers.finishBroadcast();
5049
Dianne Hackbornffa42482009-09-23 22:20:11 -07005050 mWindowManager.closeSystemDialogs(reason);
5051
5052 for (i=mHistory.size()-1; i>=0; i--) {
5053 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5054 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5055 finishActivityLocked(r, i,
5056 Activity.RESULT_CANCELED, null, "close-sys");
5057 }
5058 }
5059
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005060 broadcastIntentLocked(null, null, intent, null,
5061 null, 0, null, null, null, false, false, -1, uid);
5062 }
5063 Binder.restoreCallingIdentity(origId);
5064 }
5065
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005066 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005067 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005068 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5069 for (int i=pids.length-1; i>=0; i--) {
5070 infos[i] = new Debug.MemoryInfo();
5071 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005072 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005073 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005074 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005075
5076 public void killApplicationProcess(String processName, int uid) {
5077 if (processName == null) {
5078 return;
5079 }
5080
5081 int callerUid = Binder.getCallingUid();
5082 // Only the system server can kill an application
5083 if (callerUid == Process.SYSTEM_UID) {
5084 synchronized (this) {
5085 ProcessRecord app = getProcessRecordLocked(processName, uid);
5086 if (app != null) {
5087 try {
5088 app.thread.scheduleSuicide();
5089 } catch (RemoteException e) {
5090 // If the other end already died, then our work here is done.
5091 }
5092 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005093 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005094 + processName + " / " + uid);
5095 }
5096 }
5097 } else {
5098 throw new SecurityException(callerUid + " cannot kill app process: " +
5099 processName);
5100 }
5101 }
5102
Dianne Hackborn03abb812010-01-04 18:43:19 -08005103 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005104 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5106 Uri.fromParts("package", packageName, null));
5107 intent.putExtra(Intent.EXTRA_UID, uid);
5108 broadcastIntentLocked(null, null, intent,
5109 null, null, 0, null, null, null,
5110 false, false, MY_PID, Process.SYSTEM_UID);
5111 }
5112
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005113 private final boolean killPackageProcessesLocked(String packageName, int uid,
5114 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005115 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116
Dianne Hackborn03abb812010-01-04 18:43:19 -08005117 // Remove all processes this package may have touched: all with the
5118 // same UID (except for the system or root user), and all whose name
5119 // matches the package name.
5120 final String procNamePrefix = packageName + ":";
5121 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5122 final int NA = apps.size();
5123 for (int ia=0; ia<NA; ia++) {
5124 ProcessRecord app = apps.valueAt(ia);
5125 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005126 if (doit) {
5127 procs.add(app);
5128 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005129 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5130 || app.processName.equals(packageName)
5131 || app.processName.startsWith(procNamePrefix)) {
5132 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005133 if (!doit) {
5134 return true;
5135 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005136 app.removed = true;
5137 procs.add(app);
5138 }
5139 }
5140 }
5141 }
5142
5143 int N = procs.size();
5144 for (int i=0; i<N; i++) {
5145 removeProcessLocked(procs.get(i), callerWillRestart);
5146 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005147 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005148 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005149
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005150 private final boolean forceStopPackageLocked(String name, int uid,
5151 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 int i, N;
5153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 if (uid < 0) {
5155 try {
5156 uid = ActivityThread.getPackageManager().getPackageUid(name);
5157 } catch (RemoteException e) {
5158 }
5159 }
5160
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005161 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005162 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005163
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005164 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5165 while (badApps.hasNext()) {
5166 SparseArray<Long> ba = badApps.next();
5167 if (ba.get(uid) != null) {
5168 badApps.remove();
5169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005170 }
5171 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005172
5173 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5174 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175
5176 for (i=mHistory.size()-1; i>=0; i--) {
5177 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5178 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005179 if (!doit) {
5180 return true;
5181 }
5182 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005183 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184 if (r.app != null) {
5185 r.app.removed = true;
5186 }
5187 r.app = null;
5188 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5189 }
5190 }
5191
5192 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5193 for (ServiceRecord service : mServices.values()) {
5194 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005195 if (!doit) {
5196 return true;
5197 }
5198 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005199 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 if (service.app != null) {
5201 service.app.removed = true;
5202 }
5203 service.app = null;
5204 services.add(service);
5205 }
5206 }
5207
5208 N = services.size();
5209 for (i=0; i<N; i++) {
5210 bringDownServiceLocked(services.get(i), true);
5211 }
5212
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005213 if (doit) {
5214 if (purgeCache) {
5215 AttributeCache ac = AttributeCache.instance();
5216 if (ac != null) {
5217 ac.removePackage(name);
5218 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005219 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005220 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005221 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005222
5223 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 }
5225
5226 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5227 final String name = app.processName;
5228 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005229 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005230 TAG, "Force removing process " + app + " (" + name
5231 + "/" + uid + ")");
5232
5233 mProcessNames.remove(name, uid);
5234 boolean needRestart = false;
5235 if (app.pid > 0 && app.pid != MY_PID) {
5236 int pid = app.pid;
5237 synchronized (mPidsSelfLocked) {
5238 mPidsSelfLocked.remove(pid);
5239 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5240 }
5241 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005242 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 Process.killProcess(pid);
5244
5245 if (app.persistent) {
5246 if (!callerWillRestart) {
5247 addAppLocked(app.info);
5248 } else {
5249 needRestart = true;
5250 }
5251 }
5252 } else {
5253 mRemovedProcesses.add(app);
5254 }
5255
5256 return needRestart;
5257 }
5258
5259 private final void processStartTimedOutLocked(ProcessRecord app) {
5260 final int pid = app.pid;
5261 boolean gone = false;
5262 synchronized (mPidsSelfLocked) {
5263 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5264 if (knownApp != null && knownApp.thread == null) {
5265 mPidsSelfLocked.remove(pid);
5266 gone = true;
5267 }
5268 }
5269
5270 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005271 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005272 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005273 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005275 // Take care of any launching providers waiting for this process.
5276 checkAppInLaunchingProvidersLocked(app, true);
5277 // Take care of any services that are waiting for the process.
5278 for (int i=0; i<mPendingServices.size(); i++) {
5279 ServiceRecord sr = mPendingServices.get(i);
5280 if (app.info.uid == sr.appInfo.uid
5281 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005282 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005283 mPendingServices.remove(i);
5284 i--;
5285 bringDownServiceLocked(sr, true);
5286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005288 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005289 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005290 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005291 try {
5292 IBackupManager bm = IBackupManager.Stub.asInterface(
5293 ServiceManager.getService(Context.BACKUP_SERVICE));
5294 bm.agentDisconnected(app.info.packageName);
5295 } catch (RemoteException e) {
5296 // Can't happen; the backup manager is local
5297 }
5298 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005299 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005300 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005301 mPendingBroadcast = null;
5302 scheduleBroadcastsLocked();
5303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005305 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005306 }
5307 }
5308
5309 private final boolean attachApplicationLocked(IApplicationThread thread,
5310 int pid) {
5311
5312 // Find the application record that is being attached... either via
5313 // the pid if we are running in multiple processes, or just pull the
5314 // next app record if we are emulating process with anonymous threads.
5315 ProcessRecord app;
5316 if (pid != MY_PID && pid >= 0) {
5317 synchronized (mPidsSelfLocked) {
5318 app = mPidsSelfLocked.get(pid);
5319 }
5320 } else if (mStartingProcesses.size() > 0) {
5321 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005322 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 } else {
5324 app = null;
5325 }
5326
5327 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005328 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005330 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 if (pid > 0 && pid != MY_PID) {
5332 Process.killProcess(pid);
5333 } else {
5334 try {
5335 thread.scheduleExit();
5336 } catch (Exception e) {
5337 // Ignore exceptions.
5338 }
5339 }
5340 return false;
5341 }
5342
5343 // If this application record is still attached to a previous
5344 // process, clean it up now.
5345 if (app.thread != null) {
5346 handleAppDiedLocked(app, true);
5347 }
5348
5349 // Tell the process all about itself.
5350
Joe Onorato8a9b2202010-02-26 18:56:32 -08005351 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 TAG, "Binding process pid " + pid + " to record " + app);
5353
5354 String processName = app.processName;
5355 try {
5356 thread.asBinder().linkToDeath(new AppDeathRecipient(
5357 app, pid, thread), 0);
5358 } catch (RemoteException e) {
5359 app.resetPackageList();
5360 startProcessLocked(app, "link fail", processName);
5361 return false;
5362 }
5363
Doug Zongker2bec3d42009-12-04 12:52:44 -08005364 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365
5366 app.thread = thread;
5367 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005368 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5369 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005370 app.forcingToForeground = null;
5371 app.foregroundServices = false;
5372 app.debugging = false;
5373
5374 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5375
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005376 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5377 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005378
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005379 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005380 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005381 }
5382
Joe Onorato8a9b2202010-02-26 18:56:32 -08005383 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005384 TAG, "New app record " + app
5385 + " thread=" + thread.asBinder() + " pid=" + pid);
5386 try {
5387 int testMode = IApplicationThread.DEBUG_OFF;
5388 if (mDebugApp != null && mDebugApp.equals(processName)) {
5389 testMode = mWaitForDebugger
5390 ? IApplicationThread.DEBUG_WAIT
5391 : IApplicationThread.DEBUG_ON;
5392 app.debugging = true;
5393 if (mDebugTransient) {
5394 mDebugApp = mOrigDebugApp;
5395 mWaitForDebugger = mOrigWaitForDebugger;
5396 }
5397 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005398
Christopher Tate181fafa2009-05-14 11:12:14 -07005399 // If the app is being launched for restore or full backup, set it up specially
5400 boolean isRestrictedBackupMode = false;
5401 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5402 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5403 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5404 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005405
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005406 ensurePackageDexOpt(app.instrumentationInfo != null
5407 ? app.instrumentationInfo.packageName
5408 : app.info.packageName);
5409 if (app.instrumentationClass != null) {
5410 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005411 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005412 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005413 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005414 thread.bindApplication(processName, app.instrumentationInfo != null
5415 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005416 app.instrumentationClass, app.instrumentationProfileFile,
5417 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005418 isRestrictedBackupMode || !normalMode,
5419 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005420 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005421 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005422 } catch (Exception e) {
5423 // todo: Yikes! What should we do? For now we will try to
5424 // start another process, but that could easily get us in
5425 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005426 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427
5428 app.resetPackageList();
5429 startProcessLocked(app, "bind fail", processName);
5430 return false;
5431 }
5432
5433 // Remove this record from the list of starting applications.
5434 mPersistentStartingProcesses.remove(app);
5435 mProcessesOnHold.remove(app);
5436
5437 boolean badApp = false;
5438 boolean didSomething = false;
5439
5440 // See if the top visible activity is waiting to run in this process...
5441 HistoryRecord hr = topRunningActivityLocked(null);
5442 if (hr != null) {
5443 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5444 && processName.equals(hr.processName)) {
5445 try {
5446 if (realStartActivityLocked(hr, app, true, true)) {
5447 didSomething = true;
5448 }
5449 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005450 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 + hr.intent.getComponent().flattenToShortString(), e);
5452 badApp = true;
5453 }
5454 } else {
5455 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5456 }
5457 }
5458
5459 // Find any services that should be running in this process...
5460 if (!badApp && mPendingServices.size() > 0) {
5461 ServiceRecord sr = null;
5462 try {
5463 for (int i=0; i<mPendingServices.size(); i++) {
5464 sr = mPendingServices.get(i);
5465 if (app.info.uid != sr.appInfo.uid
5466 || !processName.equals(sr.processName)) {
5467 continue;
5468 }
5469
5470 mPendingServices.remove(i);
5471 i--;
5472 realStartServiceLocked(sr, app);
5473 didSomething = true;
5474 }
5475 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005476 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005477 + sr.shortName, e);
5478 badApp = true;
5479 }
5480 }
5481
5482 // Check if the next broadcast receiver is in this process...
5483 BroadcastRecord br = mPendingBroadcast;
5484 if (!badApp && br != null && br.curApp == app) {
5485 try {
5486 mPendingBroadcast = null;
5487 processCurBroadcastLocked(br, app);
5488 didSomething = true;
5489 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005490 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005491 + br.curComponent.flattenToShortString(), e);
5492 badApp = true;
5493 logBroadcastReceiverDiscard(br);
5494 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5495 br.resultExtras, br.resultAbort, true);
5496 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005497 // We need to reset the state if we fails to start the receiver.
5498 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 }
5500 }
5501
Christopher Tate181fafa2009-05-14 11:12:14 -07005502 // Check whether the next backup agent is in this process...
5503 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005504 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005505 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005506 try {
5507 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5508 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005509 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005510 e.printStackTrace();
5511 }
5512 }
5513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 if (badApp) {
5515 // todo: Also need to kill application to deal with all
5516 // kinds of exceptions.
5517 handleAppDiedLocked(app, false);
5518 return false;
5519 }
5520
5521 if (!didSomething) {
5522 updateOomAdjLocked();
5523 }
5524
5525 return true;
5526 }
5527
5528 public final void attachApplication(IApplicationThread thread) {
5529 synchronized (this) {
5530 int callingPid = Binder.getCallingPid();
5531 final long origId = Binder.clearCallingIdentity();
5532 attachApplicationLocked(thread, callingPid);
5533 Binder.restoreCallingIdentity(origId);
5534 }
5535 }
5536
Dianne Hackborne88846e2009-09-30 21:34:25 -07005537 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005538 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005539 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005540 Binder.restoreCallingIdentity(origId);
5541 }
5542
5543 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5544 boolean remove) {
5545 int N = mStoppingActivities.size();
5546 if (N <= 0) return null;
5547
5548 ArrayList<HistoryRecord> stops = null;
5549
5550 final boolean nowVisible = mResumedActivity != null
5551 && mResumedActivity.nowVisible
5552 && !mResumedActivity.waitingVisible;
5553 for (int i=0; i<N; i++) {
5554 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005555 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005556 + nowVisible + " waitingVisible=" + s.waitingVisible
5557 + " finishing=" + s.finishing);
5558 if (s.waitingVisible && nowVisible) {
5559 mWaitingVisibleActivities.remove(s);
5560 s.waitingVisible = false;
5561 if (s.finishing) {
5562 // If this activity is finishing, it is sitting on top of
5563 // everyone else but we now know it is no longer needed...
5564 // so get rid of it. Otherwise, we need to go through the
5565 // normal flow and hide it once we determine that it is
5566 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005567 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005568 mWindowManager.setAppVisibility(s, false);
5569 }
5570 }
5571 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005572 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 if (stops == null) {
5574 stops = new ArrayList<HistoryRecord>();
5575 }
5576 stops.add(s);
5577 mStoppingActivities.remove(i);
5578 N--;
5579 i--;
5580 }
5581 }
5582
5583 return stops;
5584 }
5585
5586 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005587 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005588 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005589 mWindowManager.enableScreenAfterBoot();
5590 }
5591
Dianne Hackborne88846e2009-09-30 21:34:25 -07005592 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5593 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005594 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005595
5596 ArrayList<HistoryRecord> stops = null;
5597 ArrayList<HistoryRecord> finishes = null;
5598 ArrayList<HistoryRecord> thumbnails = null;
5599 int NS = 0;
5600 int NF = 0;
5601 int NT = 0;
5602 IApplicationThread sendThumbnail = null;
5603 boolean booting = false;
5604 boolean enableScreen = false;
5605
5606 synchronized (this) {
5607 if (token != null) {
5608 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5609 }
5610
5611 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005612 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 if (index >= 0) {
5614 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5615
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005616 if (fromTimeout) {
5617 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5618 }
5619
Dianne Hackborne88846e2009-09-30 21:34:25 -07005620 // This is a hack to semi-deal with a race condition
5621 // in the client where it can be constructed with a
5622 // newer configuration from when we asked it to launch.
5623 // We'll update with whatever configuration it now says
5624 // it used to launch.
5625 if (config != null) {
5626 r.configuration = config;
5627 }
5628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629 // No longer need to keep the device awake.
5630 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5631 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5632 mLaunchingActivity.release();
5633 }
5634
5635 // We are now idle. If someone is waiting for a thumbnail from
5636 // us, we can now deliver.
5637 r.idle = true;
5638 scheduleAppGcsLocked();
5639 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5640 sendThumbnail = r.app.thread;
5641 r.thumbnailNeeded = false;
5642 }
5643
5644 // If this activity is fullscreen, set up to hide those under it.
5645
Joe Onorato8a9b2202010-02-26 18:56:32 -08005646 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 ensureActivitiesVisibleLocked(null, 0);
5648
Joe Onorato8a9b2202010-02-26 18:56:32 -08005649 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005650 if (!mBooted && !fromTimeout) {
5651 mBooted = true;
5652 enableScreen = true;
5653 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005654
5655 } else if (fromTimeout) {
5656 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005657 }
5658
5659 // Atomically retrieve all of the other things to do.
5660 stops = processStoppingActivitiesLocked(true);
5661 NS = stops != null ? stops.size() : 0;
5662 if ((NF=mFinishingActivities.size()) > 0) {
5663 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5664 mFinishingActivities.clear();
5665 }
5666 if ((NT=mCancelledThumbnails.size()) > 0) {
5667 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5668 mCancelledThumbnails.clear();
5669 }
5670
5671 booting = mBooting;
5672 mBooting = false;
5673 }
5674
5675 int i;
5676
5677 // Send thumbnail if requested.
5678 if (sendThumbnail != null) {
5679 try {
5680 sendThumbnail.requestThumbnail(token);
5681 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005682 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005683 sendPendingThumbnail(null, token, null, null, true);
5684 }
5685 }
5686
5687 // Stop any activities that are scheduled to do so but have been
5688 // waiting for the next one to start.
5689 for (i=0; i<NS; i++) {
5690 HistoryRecord r = (HistoryRecord)stops.get(i);
5691 synchronized (this) {
5692 if (r.finishing) {
5693 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5694 } else {
5695 stopActivityLocked(r);
5696 }
5697 }
5698 }
5699
5700 // Finish any activities that are scheduled to do so but have been
5701 // waiting for the next one to start.
5702 for (i=0; i<NF; i++) {
5703 HistoryRecord r = (HistoryRecord)finishes.get(i);
5704 synchronized (this) {
5705 destroyActivityLocked(r, true);
5706 }
5707 }
5708
5709 // Report back to any thumbnail receivers.
5710 for (i=0; i<NT; i++) {
5711 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5712 sendPendingThumbnail(r, null, null, null, true);
5713 }
5714
5715 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005716 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 }
5718
5719 trimApplications();
5720 //dump();
5721 //mWindowManager.dump();
5722
5723 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 enableScreenAfterBoot();
5725 }
5726 }
5727
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005728 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005729 IntentFilter pkgFilter = new IntentFilter();
5730 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5731 pkgFilter.addDataScheme("package");
5732 mContext.registerReceiver(new BroadcastReceiver() {
5733 @Override
5734 public void onReceive(Context context, Intent intent) {
5735 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5736 if (pkgs != null) {
5737 for (String pkg : pkgs) {
5738 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5739 setResultCode(Activity.RESULT_OK);
5740 return;
5741 }
5742 }
5743 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005744 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005745 }, pkgFilter);
5746
5747 synchronized (this) {
5748 // Ensure that any processes we had put on hold are now started
5749 // up.
5750 final int NP = mProcessesOnHold.size();
5751 if (NP > 0) {
5752 ArrayList<ProcessRecord> procs =
5753 new ArrayList<ProcessRecord>(mProcessesOnHold);
5754 for (int ip=0; ip<NP; ip++) {
5755 this.startProcessLocked(procs.get(ip), "on-hold", null);
5756 }
5757 }
5758
5759 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5760 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005761 broadcastIntentLocked(null, null,
5762 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5763 null, null, 0, null, null,
5764 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5765 false, false, MY_PID, Process.SYSTEM_UID);
5766 }
5767 }
5768 }
5769
5770 final void ensureBootCompleted() {
5771 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005772 boolean enableScreen;
5773 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005774 booting = mBooting;
5775 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005776 enableScreen = !mBooted;
5777 mBooted = true;
5778 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005779
5780 if (booting) {
5781 finishBooting();
5782 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005783
5784 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005785 enableScreenAfterBoot();
5786 }
5787 }
5788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005789 public final void activityPaused(IBinder token, Bundle icicle) {
5790 // Refuse possible leaked file descriptors
5791 if (icicle != null && icicle.hasFileDescriptors()) {
5792 throw new IllegalArgumentException("File descriptors passed in Bundle");
5793 }
5794
5795 final long origId = Binder.clearCallingIdentity();
5796 activityPaused(token, icicle, false);
5797 Binder.restoreCallingIdentity(origId);
5798 }
5799
5800 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005801 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005802 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5803 + ", timeout=" + timeout);
5804
5805 HistoryRecord r = null;
5806
5807 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005808 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005809 if (index >= 0) {
5810 r = (HistoryRecord)mHistory.get(index);
5811 if (!timeout) {
5812 r.icicle = icicle;
5813 r.haveState = true;
5814 }
5815 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5816 if (mPausingActivity == r) {
5817 r.state = ActivityState.PAUSED;
5818 completePauseLocked();
5819 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005820 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005821 System.identityHashCode(r), r.shortComponentName,
5822 mPausingActivity != null
5823 ? mPausingActivity.shortComponentName : "(none)");
5824 }
5825 }
5826 }
5827 }
5828
5829 public final void activityStopped(IBinder token, Bitmap thumbnail,
5830 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005831 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 TAG, "Activity stopped: token=" + token);
5833
5834 HistoryRecord r = null;
5835
5836 final long origId = Binder.clearCallingIdentity();
5837
5838 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005839 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 if (index >= 0) {
5841 r = (HistoryRecord)mHistory.get(index);
5842 r.thumbnail = thumbnail;
5843 r.description = description;
5844 r.stopped = true;
5845 r.state = ActivityState.STOPPED;
5846 if (!r.finishing) {
5847 if (r.configDestroy) {
5848 destroyActivityLocked(r, true);
5849 resumeTopActivityLocked(null);
5850 }
5851 }
5852 }
5853 }
5854
5855 if (r != null) {
5856 sendPendingThumbnail(r, null, null, null, false);
5857 }
5858
5859 trimApplications();
5860
5861 Binder.restoreCallingIdentity(origId);
5862 }
5863
5864 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005865 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 synchronized (this) {
5867 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5868
Dianne Hackborn75b03852009-06-12 15:43:26 -07005869 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005870 if (index >= 0) {
5871 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5872 if (r.state == ActivityState.DESTROYING) {
5873 final long origId = Binder.clearCallingIdentity();
5874 removeActivityFromHistoryLocked(r);
5875 Binder.restoreCallingIdentity(origId);
5876 }
5877 }
5878 }
5879 }
5880
5881 public String getCallingPackage(IBinder token) {
5882 synchronized (this) {
5883 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005884 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005885 }
5886 }
5887
5888 public ComponentName getCallingActivity(IBinder token) {
5889 synchronized (this) {
5890 HistoryRecord r = getCallingRecordLocked(token);
5891 return r != null ? r.intent.getComponent() : null;
5892 }
5893 }
5894
5895 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005896 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 if (index >= 0) {
5898 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5899 if (r != null) {
5900 return r.resultTo;
5901 }
5902 }
5903 return null;
5904 }
5905
5906 public ComponentName getActivityClassForToken(IBinder token) {
5907 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005908 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005909 if (index >= 0) {
5910 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5911 return r.intent.getComponent();
5912 }
5913 return null;
5914 }
5915 }
5916
5917 public String getPackageForToken(IBinder token) {
5918 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005919 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005920 if (index >= 0) {
5921 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5922 return r.packageName;
5923 }
5924 return null;
5925 }
5926 }
5927
5928 public IIntentSender getIntentSender(int type,
5929 String packageName, IBinder token, String resultWho,
5930 int requestCode, Intent intent, String resolvedType, int flags) {
5931 // Refuse possible leaked file descriptors
5932 if (intent != null && intent.hasFileDescriptors() == true) {
5933 throw new IllegalArgumentException("File descriptors passed in Intent");
5934 }
5935
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005936 if (type == INTENT_SENDER_BROADCAST) {
5937 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5938 throw new IllegalArgumentException(
5939 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5940 }
5941 }
5942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943 synchronized(this) {
5944 int callingUid = Binder.getCallingUid();
5945 try {
5946 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5947 Process.supportsProcesses()) {
5948 int uid = ActivityThread.getPackageManager()
5949 .getPackageUid(packageName);
5950 if (uid != Binder.getCallingUid()) {
5951 String msg = "Permission Denial: getIntentSender() from pid="
5952 + Binder.getCallingPid()
5953 + ", uid=" + Binder.getCallingUid()
5954 + ", (need uid=" + uid + ")"
5955 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005956 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 throw new SecurityException(msg);
5958 }
5959 }
5960 } catch (RemoteException e) {
5961 throw new SecurityException(e);
5962 }
5963 HistoryRecord activity = null;
5964 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005965 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005966 if (index < 0) {
5967 return null;
5968 }
5969 activity = (HistoryRecord)mHistory.get(index);
5970 if (activity.finishing) {
5971 return null;
5972 }
5973 }
5974
5975 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5976 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5977 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5978 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5979 |PendingIntent.FLAG_UPDATE_CURRENT);
5980
5981 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5982 type, packageName, activity, resultWho,
5983 requestCode, intent, resolvedType, flags);
5984 WeakReference<PendingIntentRecord> ref;
5985 ref = mIntentSenderRecords.get(key);
5986 PendingIntentRecord rec = ref != null ? ref.get() : null;
5987 if (rec != null) {
5988 if (!cancelCurrent) {
5989 if (updateCurrent) {
5990 rec.key.requestIntent.replaceExtras(intent);
5991 }
5992 return rec;
5993 }
5994 rec.canceled = true;
5995 mIntentSenderRecords.remove(key);
5996 }
5997 if (noCreate) {
5998 return rec;
5999 }
6000 rec = new PendingIntentRecord(this, key, callingUid);
6001 mIntentSenderRecords.put(key, rec.ref);
6002 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6003 if (activity.pendingResults == null) {
6004 activity.pendingResults
6005 = new HashSet<WeakReference<PendingIntentRecord>>();
6006 }
6007 activity.pendingResults.add(rec.ref);
6008 }
6009 return rec;
6010 }
6011 }
6012
6013 public void cancelIntentSender(IIntentSender sender) {
6014 if (!(sender instanceof PendingIntentRecord)) {
6015 return;
6016 }
6017 synchronized(this) {
6018 PendingIntentRecord rec = (PendingIntentRecord)sender;
6019 try {
6020 int uid = ActivityThread.getPackageManager()
6021 .getPackageUid(rec.key.packageName);
6022 if (uid != Binder.getCallingUid()) {
6023 String msg = "Permission Denial: cancelIntentSender() from pid="
6024 + Binder.getCallingPid()
6025 + ", uid=" + Binder.getCallingUid()
6026 + " is not allowed to cancel packges "
6027 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006028 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006029 throw new SecurityException(msg);
6030 }
6031 } catch (RemoteException e) {
6032 throw new SecurityException(e);
6033 }
6034 cancelIntentSenderLocked(rec, true);
6035 }
6036 }
6037
6038 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6039 rec.canceled = true;
6040 mIntentSenderRecords.remove(rec.key);
6041 if (cleanActivity && rec.key.activity != null) {
6042 rec.key.activity.pendingResults.remove(rec.ref);
6043 }
6044 }
6045
6046 public String getPackageForIntentSender(IIntentSender pendingResult) {
6047 if (!(pendingResult instanceof PendingIntentRecord)) {
6048 return null;
6049 }
6050 synchronized(this) {
6051 try {
6052 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6053 return res.key.packageName;
6054 } catch (ClassCastException e) {
6055 }
6056 }
6057 return null;
6058 }
6059
6060 public void setProcessLimit(int max) {
6061 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6062 "setProcessLimit()");
6063 mProcessLimit = max;
6064 }
6065
6066 public int getProcessLimit() {
6067 return mProcessLimit;
6068 }
6069
6070 void foregroundTokenDied(ForegroundToken token) {
6071 synchronized (ActivityManagerService.this) {
6072 synchronized (mPidsSelfLocked) {
6073 ForegroundToken cur
6074 = mForegroundProcesses.get(token.pid);
6075 if (cur != token) {
6076 return;
6077 }
6078 mForegroundProcesses.remove(token.pid);
6079 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6080 if (pr == null) {
6081 return;
6082 }
6083 pr.forcingToForeground = null;
6084 pr.foregroundServices = false;
6085 }
6086 updateOomAdjLocked();
6087 }
6088 }
6089
6090 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6091 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6092 "setProcessForeground()");
6093 synchronized(this) {
6094 boolean changed = false;
6095
6096 synchronized (mPidsSelfLocked) {
6097 ProcessRecord pr = mPidsSelfLocked.get(pid);
6098 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006099 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 return;
6101 }
6102 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6103 if (oldToken != null) {
6104 oldToken.token.unlinkToDeath(oldToken, 0);
6105 mForegroundProcesses.remove(pid);
6106 pr.forcingToForeground = null;
6107 changed = true;
6108 }
6109 if (isForeground && token != null) {
6110 ForegroundToken newToken = new ForegroundToken() {
6111 public void binderDied() {
6112 foregroundTokenDied(this);
6113 }
6114 };
6115 newToken.pid = pid;
6116 newToken.token = token;
6117 try {
6118 token.linkToDeath(newToken, 0);
6119 mForegroundProcesses.put(pid, newToken);
6120 pr.forcingToForeground = token;
6121 changed = true;
6122 } catch (RemoteException e) {
6123 // If the process died while doing this, we will later
6124 // do the cleanup with the process death link.
6125 }
6126 }
6127 }
6128
6129 if (changed) {
6130 updateOomAdjLocked();
6131 }
6132 }
6133 }
6134
6135 // =========================================================
6136 // PERMISSIONS
6137 // =========================================================
6138
6139 static class PermissionController extends IPermissionController.Stub {
6140 ActivityManagerService mActivityManagerService;
6141 PermissionController(ActivityManagerService activityManagerService) {
6142 mActivityManagerService = activityManagerService;
6143 }
6144
6145 public boolean checkPermission(String permission, int pid, int uid) {
6146 return mActivityManagerService.checkPermission(permission, pid,
6147 uid) == PackageManager.PERMISSION_GRANTED;
6148 }
6149 }
6150
6151 /**
6152 * This can be called with or without the global lock held.
6153 */
6154 int checkComponentPermission(String permission, int pid, int uid,
6155 int reqUid) {
6156 // We might be performing an operation on behalf of an indirect binder
6157 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6158 // client identity accordingly before proceeding.
6159 Identity tlsIdentity = sCallerIdentity.get();
6160 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006161 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006162 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6163 uid = tlsIdentity.uid;
6164 pid = tlsIdentity.pid;
6165 }
6166
6167 // Root, system server and our own process get to do everything.
6168 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6169 !Process.supportsProcesses()) {
6170 return PackageManager.PERMISSION_GRANTED;
6171 }
6172 // If the target requires a specific UID, always fail for others.
6173 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006174 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006175 return PackageManager.PERMISSION_DENIED;
6176 }
6177 if (permission == null) {
6178 return PackageManager.PERMISSION_GRANTED;
6179 }
6180 try {
6181 return ActivityThread.getPackageManager()
6182 .checkUidPermission(permission, uid);
6183 } catch (RemoteException e) {
6184 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006185 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006186 }
6187 return PackageManager.PERMISSION_DENIED;
6188 }
6189
6190 /**
6191 * As the only public entry point for permissions checking, this method
6192 * can enforce the semantic that requesting a check on a null global
6193 * permission is automatically denied. (Internally a null permission
6194 * string is used when calling {@link #checkComponentPermission} in cases
6195 * when only uid-based security is needed.)
6196 *
6197 * This can be called with or without the global lock held.
6198 */
6199 public int checkPermission(String permission, int pid, int uid) {
6200 if (permission == null) {
6201 return PackageManager.PERMISSION_DENIED;
6202 }
6203 return checkComponentPermission(permission, pid, uid, -1);
6204 }
6205
6206 /**
6207 * Binder IPC calls go through the public entry point.
6208 * This can be called with or without the global lock held.
6209 */
6210 int checkCallingPermission(String permission) {
6211 return checkPermission(permission,
6212 Binder.getCallingPid(),
6213 Binder.getCallingUid());
6214 }
6215
6216 /**
6217 * This can be called with or without the global lock held.
6218 */
6219 void enforceCallingPermission(String permission, String func) {
6220 if (checkCallingPermission(permission)
6221 == PackageManager.PERMISSION_GRANTED) {
6222 return;
6223 }
6224
6225 String msg = "Permission Denial: " + func + " from pid="
6226 + Binder.getCallingPid()
6227 + ", uid=" + Binder.getCallingUid()
6228 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006229 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230 throw new SecurityException(msg);
6231 }
6232
6233 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6234 ProviderInfo pi, int uid, int modeFlags) {
6235 try {
6236 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6237 if ((pi.readPermission != null) &&
6238 (pm.checkUidPermission(pi.readPermission, uid)
6239 != PackageManager.PERMISSION_GRANTED)) {
6240 return false;
6241 }
6242 }
6243 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6244 if ((pi.writePermission != null) &&
6245 (pm.checkUidPermission(pi.writePermission, uid)
6246 != PackageManager.PERMISSION_GRANTED)) {
6247 return false;
6248 }
6249 }
6250 return true;
6251 } catch (RemoteException e) {
6252 return false;
6253 }
6254 }
6255
6256 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6257 int modeFlags) {
6258 // Root gets to do everything.
6259 if (uid == 0 || !Process.supportsProcesses()) {
6260 return true;
6261 }
6262 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6263 if (perms == null) return false;
6264 UriPermission perm = perms.get(uri);
6265 if (perm == null) return false;
6266 return (modeFlags&perm.modeFlags) == modeFlags;
6267 }
6268
6269 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6270 // Another redirected-binder-call permissions check as in
6271 // {@link checkComponentPermission}.
6272 Identity tlsIdentity = sCallerIdentity.get();
6273 if (tlsIdentity != null) {
6274 uid = tlsIdentity.uid;
6275 pid = tlsIdentity.pid;
6276 }
6277
6278 // Our own process gets to do everything.
6279 if (pid == MY_PID) {
6280 return PackageManager.PERMISSION_GRANTED;
6281 }
6282 synchronized(this) {
6283 return checkUriPermissionLocked(uri, uid, modeFlags)
6284 ? PackageManager.PERMISSION_GRANTED
6285 : PackageManager.PERMISSION_DENIED;
6286 }
6287 }
6288
6289 private void grantUriPermissionLocked(int callingUid,
6290 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6291 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6292 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6293 if (modeFlags == 0) {
6294 return;
6295 }
6296
Joe Onorato8a9b2202010-02-26 18:56:32 -08006297 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006298 "Requested grant " + targetPkg + " permission to " + uri);
6299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006300 final IPackageManager pm = ActivityThread.getPackageManager();
6301
6302 // If this is not a content: uri, we can't do anything with it.
6303 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006304 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006305 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006306 return;
6307 }
6308
6309 String name = uri.getAuthority();
6310 ProviderInfo pi = null;
6311 ContentProviderRecord cpr
6312 = (ContentProviderRecord)mProvidersByName.get(name);
6313 if (cpr != null) {
6314 pi = cpr.info;
6315 } else {
6316 try {
6317 pi = pm.resolveContentProvider(name,
6318 PackageManager.GET_URI_PERMISSION_PATTERNS);
6319 } catch (RemoteException ex) {
6320 }
6321 }
6322 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006323 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006324 return;
6325 }
6326
6327 int targetUid;
6328 try {
6329 targetUid = pm.getPackageUid(targetPkg);
6330 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006331 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006332 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006333 return;
6334 }
6335 } catch (RemoteException ex) {
6336 return;
6337 }
6338
6339 // First... does the target actually need this permission?
6340 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6341 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006342 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006343 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006344 return;
6345 }
6346
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006347 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006348 if (!pi.grantUriPermissions) {
6349 throw new SecurityException("Provider " + pi.packageName
6350 + "/" + pi.name
6351 + " does not allow granting of Uri permissions (uri "
6352 + uri + ")");
6353 }
6354 if (pi.uriPermissionPatterns != null) {
6355 final int N = pi.uriPermissionPatterns.length;
6356 boolean allowed = false;
6357 for (int i=0; i<N; i++) {
6358 if (pi.uriPermissionPatterns[i] != null
6359 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6360 allowed = true;
6361 break;
6362 }
6363 }
6364 if (!allowed) {
6365 throw new SecurityException("Provider " + pi.packageName
6366 + "/" + pi.name
6367 + " does not allow granting of permission to path of Uri "
6368 + uri);
6369 }
6370 }
6371
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006372 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006373 // this uri?
6374 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6375 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6376 throw new SecurityException("Uid " + callingUid
6377 + " does not have permission to uri " + uri);
6378 }
6379 }
6380
6381 // Okay! So here we are: the caller has the assumed permission
6382 // to the uri, and the target doesn't. Let's now give this to
6383 // the target.
6384
Joe Onorato8a9b2202010-02-26 18:56:32 -08006385 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006386 "Granting " + targetPkg + " permission to " + uri);
6387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006388 HashMap<Uri, UriPermission> targetUris
6389 = mGrantedUriPermissions.get(targetUid);
6390 if (targetUris == null) {
6391 targetUris = new HashMap<Uri, UriPermission>();
6392 mGrantedUriPermissions.put(targetUid, targetUris);
6393 }
6394
6395 UriPermission perm = targetUris.get(uri);
6396 if (perm == null) {
6397 perm = new UriPermission(targetUid, uri);
6398 targetUris.put(uri, perm);
6399
6400 }
6401 perm.modeFlags |= modeFlags;
6402 if (activity == null) {
6403 perm.globalModeFlags |= modeFlags;
6404 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6405 perm.readActivities.add(activity);
6406 if (activity.readUriPermissions == null) {
6407 activity.readUriPermissions = new HashSet<UriPermission>();
6408 }
6409 activity.readUriPermissions.add(perm);
6410 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6411 perm.writeActivities.add(activity);
6412 if (activity.writeUriPermissions == null) {
6413 activity.writeUriPermissions = new HashSet<UriPermission>();
6414 }
6415 activity.writeUriPermissions.add(perm);
6416 }
6417 }
6418
6419 private void grantUriPermissionFromIntentLocked(int callingUid,
6420 String targetPkg, Intent intent, HistoryRecord activity) {
6421 if (intent == null) {
6422 return;
6423 }
6424 Uri data = intent.getData();
6425 if (data == null) {
6426 return;
6427 }
6428 grantUriPermissionLocked(callingUid, targetPkg, data,
6429 intent.getFlags(), activity);
6430 }
6431
6432 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6433 Uri uri, int modeFlags) {
6434 synchronized(this) {
6435 final ProcessRecord r = getRecordForAppLocked(caller);
6436 if (r == null) {
6437 throw new SecurityException("Unable to find app for caller "
6438 + caller
6439 + " when granting permission to uri " + uri);
6440 }
6441 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006442 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006443 return;
6444 }
6445 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006446 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006447 return;
6448 }
6449
6450 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6451 null);
6452 }
6453 }
6454
6455 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6456 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6457 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6458 HashMap<Uri, UriPermission> perms
6459 = mGrantedUriPermissions.get(perm.uid);
6460 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006461 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006462 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006463 perms.remove(perm.uri);
6464 if (perms.size() == 0) {
6465 mGrantedUriPermissions.remove(perm.uid);
6466 }
6467 }
6468 }
6469 }
6470
6471 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6472 if (activity.readUriPermissions != null) {
6473 for (UriPermission perm : activity.readUriPermissions) {
6474 perm.readActivities.remove(activity);
6475 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6476 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6477 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6478 removeUriPermissionIfNeededLocked(perm);
6479 }
6480 }
6481 }
6482 if (activity.writeUriPermissions != null) {
6483 for (UriPermission perm : activity.writeUriPermissions) {
6484 perm.writeActivities.remove(activity);
6485 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6486 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6487 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6488 removeUriPermissionIfNeededLocked(perm);
6489 }
6490 }
6491 }
6492 }
6493
6494 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6495 int modeFlags) {
6496 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6497 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6498 if (modeFlags == 0) {
6499 return;
6500 }
6501
Joe Onorato8a9b2202010-02-26 18:56:32 -08006502 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006503 "Revoking all granted permissions to " + uri);
6504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006505 final IPackageManager pm = ActivityThread.getPackageManager();
6506
6507 final String authority = uri.getAuthority();
6508 ProviderInfo pi = null;
6509 ContentProviderRecord cpr
6510 = (ContentProviderRecord)mProvidersByName.get(authority);
6511 if (cpr != null) {
6512 pi = cpr.info;
6513 } else {
6514 try {
6515 pi = pm.resolveContentProvider(authority,
6516 PackageManager.GET_URI_PERMISSION_PATTERNS);
6517 } catch (RemoteException ex) {
6518 }
6519 }
6520 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006521 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006522 return;
6523 }
6524
6525 // Does the caller have this permission on the URI?
6526 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6527 // Right now, if you are not the original owner of the permission,
6528 // you are not allowed to revoke it.
6529 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6530 throw new SecurityException("Uid " + callingUid
6531 + " does not have permission to uri " + uri);
6532 //}
6533 }
6534
6535 // Go through all of the permissions and remove any that match.
6536 final List<String> SEGMENTS = uri.getPathSegments();
6537 if (SEGMENTS != null) {
6538 final int NS = SEGMENTS.size();
6539 int N = mGrantedUriPermissions.size();
6540 for (int i=0; i<N; i++) {
6541 HashMap<Uri, UriPermission> perms
6542 = mGrantedUriPermissions.valueAt(i);
6543 Iterator<UriPermission> it = perms.values().iterator();
6544 toploop:
6545 while (it.hasNext()) {
6546 UriPermission perm = it.next();
6547 Uri targetUri = perm.uri;
6548 if (!authority.equals(targetUri.getAuthority())) {
6549 continue;
6550 }
6551 List<String> targetSegments = targetUri.getPathSegments();
6552 if (targetSegments == null) {
6553 continue;
6554 }
6555 if (targetSegments.size() < NS) {
6556 continue;
6557 }
6558 for (int j=0; j<NS; j++) {
6559 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6560 continue toploop;
6561 }
6562 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006563 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006564 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006565 perm.clearModes(modeFlags);
6566 if (perm.modeFlags == 0) {
6567 it.remove();
6568 }
6569 }
6570 if (perms.size() == 0) {
6571 mGrantedUriPermissions.remove(
6572 mGrantedUriPermissions.keyAt(i));
6573 N--;
6574 i--;
6575 }
6576 }
6577 }
6578 }
6579
6580 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6581 int modeFlags) {
6582 synchronized(this) {
6583 final ProcessRecord r = getRecordForAppLocked(caller);
6584 if (r == null) {
6585 throw new SecurityException("Unable to find app for caller "
6586 + caller
6587 + " when revoking permission to uri " + uri);
6588 }
6589 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006590 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006591 return;
6592 }
6593
6594 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6595 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6596 if (modeFlags == 0) {
6597 return;
6598 }
6599
6600 final IPackageManager pm = ActivityThread.getPackageManager();
6601
6602 final String authority = uri.getAuthority();
6603 ProviderInfo pi = null;
6604 ContentProviderRecord cpr
6605 = (ContentProviderRecord)mProvidersByName.get(authority);
6606 if (cpr != null) {
6607 pi = cpr.info;
6608 } else {
6609 try {
6610 pi = pm.resolveContentProvider(authority,
6611 PackageManager.GET_URI_PERMISSION_PATTERNS);
6612 } catch (RemoteException ex) {
6613 }
6614 }
6615 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006616 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006617 return;
6618 }
6619
6620 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6621 }
6622 }
6623
6624 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6625 synchronized (this) {
6626 ProcessRecord app =
6627 who != null ? getRecordForAppLocked(who) : null;
6628 if (app == null) return;
6629
6630 Message msg = Message.obtain();
6631 msg.what = WAIT_FOR_DEBUGGER_MSG;
6632 msg.obj = app;
6633 msg.arg1 = waiting ? 1 : 0;
6634 mHandler.sendMessage(msg);
6635 }
6636 }
6637
6638 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6639 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006640 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006641 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006642 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006643 }
6644
6645 // =========================================================
6646 // TASK MANAGEMENT
6647 // =========================================================
6648
6649 public List getTasks(int maxNum, int flags,
6650 IThumbnailReceiver receiver) {
6651 ArrayList list = new ArrayList();
6652
6653 PendingThumbnailsRecord pending = null;
6654 IApplicationThread topThumbnail = null;
6655 HistoryRecord topRecord = null;
6656
6657 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006658 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006659 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6660 + ", receiver=" + receiver);
6661
6662 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6663 != PackageManager.PERMISSION_GRANTED) {
6664 if (receiver != null) {
6665 // If the caller wants to wait for pending thumbnails,
6666 // it ain't gonna get them.
6667 try {
6668 receiver.finished();
6669 } catch (RemoteException ex) {
6670 }
6671 }
6672 String msg = "Permission Denial: getTasks() from pid="
6673 + Binder.getCallingPid()
6674 + ", uid=" + Binder.getCallingUid()
6675 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006676 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006677 throw new SecurityException(msg);
6678 }
6679
6680 int pos = mHistory.size()-1;
6681 HistoryRecord next =
6682 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6683 HistoryRecord top = null;
6684 CharSequence topDescription = null;
6685 TaskRecord curTask = null;
6686 int numActivities = 0;
6687 int numRunning = 0;
6688 while (pos >= 0 && maxNum > 0) {
6689 final HistoryRecord r = next;
6690 pos--;
6691 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6692
6693 // Initialize state for next task if needed.
6694 if (top == null ||
6695 (top.state == ActivityState.INITIALIZING
6696 && top.task == r.task)) {
6697 top = r;
6698 topDescription = r.description;
6699 curTask = r.task;
6700 numActivities = numRunning = 0;
6701 }
6702
6703 // Add 'r' into the current task.
6704 numActivities++;
6705 if (r.app != null && r.app.thread != null) {
6706 numRunning++;
6707 }
6708 if (topDescription == null) {
6709 topDescription = r.description;
6710 }
6711
Joe Onorato8a9b2202010-02-26 18:56:32 -08006712 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006713 TAG, r.intent.getComponent().flattenToShortString()
6714 + ": task=" + r.task);
6715
6716 // If the next one is a different task, generate a new
6717 // TaskInfo entry for what we have.
6718 if (next == null || next.task != curTask) {
6719 ActivityManager.RunningTaskInfo ci
6720 = new ActivityManager.RunningTaskInfo();
6721 ci.id = curTask.taskId;
6722 ci.baseActivity = r.intent.getComponent();
6723 ci.topActivity = top.intent.getComponent();
6724 ci.thumbnail = top.thumbnail;
6725 ci.description = topDescription;
6726 ci.numActivities = numActivities;
6727 ci.numRunning = numRunning;
6728 //System.out.println(
6729 // "#" + maxNum + ": " + " descr=" + ci.description);
6730 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006731 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 TAG, "State=" + top.state + "Idle=" + top.idle
6733 + " app=" + top.app
6734 + " thr=" + (top.app != null ? top.app.thread : null));
6735 if (top.state == ActivityState.RESUMED
6736 || top.state == ActivityState.PAUSING) {
6737 if (top.idle && top.app != null
6738 && top.app.thread != null) {
6739 topRecord = top;
6740 topThumbnail = top.app.thread;
6741 } else {
6742 top.thumbnailNeeded = true;
6743 }
6744 }
6745 if (pending == null) {
6746 pending = new PendingThumbnailsRecord(receiver);
6747 }
6748 pending.pendingRecords.add(top);
6749 }
6750 list.add(ci);
6751 maxNum--;
6752 top = null;
6753 }
6754 }
6755
6756 if (pending != null) {
6757 mPendingThumbnails.add(pending);
6758 }
6759 }
6760
Joe Onorato8a9b2202010-02-26 18:56:32 -08006761 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006762
6763 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006764 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006765 try {
6766 topThumbnail.requestThumbnail(topRecord);
6767 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006768 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769 sendPendingThumbnail(null, topRecord, null, null, true);
6770 }
6771 }
6772
6773 if (pending == null && receiver != null) {
6774 // In this case all thumbnails were available and the client
6775 // is being asked to be told when the remaining ones come in...
6776 // which is unusually, since the top-most currently running
6777 // activity should never have a canned thumbnail! Oh well.
6778 try {
6779 receiver.finished();
6780 } catch (RemoteException ex) {
6781 }
6782 }
6783
6784 return list;
6785 }
6786
6787 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6788 int flags) {
6789 synchronized (this) {
6790 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6791 "getRecentTasks()");
6792
6793 final int N = mRecentTasks.size();
6794 ArrayList<ActivityManager.RecentTaskInfo> res
6795 = new ArrayList<ActivityManager.RecentTaskInfo>(
6796 maxNum < N ? maxNum : N);
6797 for (int i=0; i<N && maxNum > 0; i++) {
6798 TaskRecord tr = mRecentTasks.get(i);
6799 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6800 || (tr.intent == null)
6801 || ((tr.intent.getFlags()
6802 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6803 ActivityManager.RecentTaskInfo rti
6804 = new ActivityManager.RecentTaskInfo();
6805 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6806 rti.baseIntent = new Intent(
6807 tr.intent != null ? tr.intent : tr.affinityIntent);
6808 rti.origActivity = tr.origActivity;
6809 res.add(rti);
6810 maxNum--;
6811 }
6812 }
6813 return res;
6814 }
6815 }
6816
6817 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6818 int j;
6819 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6820 TaskRecord jt = startTask;
6821
6822 // First look backwards
6823 for (j=startIndex-1; j>=0; j--) {
6824 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6825 if (r.task != jt) {
6826 jt = r.task;
6827 if (affinity.equals(jt.affinity)) {
6828 return j;
6829 }
6830 }
6831 }
6832
6833 // Now look forwards
6834 final int N = mHistory.size();
6835 jt = startTask;
6836 for (j=startIndex+1; j<N; j++) {
6837 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6838 if (r.task != jt) {
6839 if (affinity.equals(jt.affinity)) {
6840 return j;
6841 }
6842 jt = r.task;
6843 }
6844 }
6845
6846 // Might it be at the top?
6847 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6848 return N-1;
6849 }
6850
6851 return -1;
6852 }
6853
6854 /**
6855 * Perform a reset of the given task, if needed as part of launching it.
6856 * Returns the new HistoryRecord at the top of the task.
6857 */
6858 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6859 HistoryRecord newActivity) {
6860 boolean forceReset = (newActivity.info.flags
6861 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6862 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6863 if ((newActivity.info.flags
6864 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6865 forceReset = true;
6866 }
6867 }
6868
6869 final TaskRecord task = taskTop.task;
6870
6871 // We are going to move through the history list so that we can look
6872 // at each activity 'target' with 'below' either the interesting
6873 // activity immediately below it in the stack or null.
6874 HistoryRecord target = null;
6875 int targetI = 0;
6876 int taskTopI = -1;
6877 int replyChainEnd = -1;
6878 int lastReparentPos = -1;
6879 for (int i=mHistory.size()-1; i>=-1; i--) {
6880 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6881
6882 if (below != null && below.finishing) {
6883 continue;
6884 }
6885 if (target == null) {
6886 target = below;
6887 targetI = i;
6888 // If we were in the middle of a reply chain before this
6889 // task, it doesn't appear like the root of the chain wants
6890 // anything interesting, so drop it.
6891 replyChainEnd = -1;
6892 continue;
6893 }
6894
6895 final int flags = target.info.flags;
6896
6897 final boolean finishOnTaskLaunch =
6898 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6899 final boolean allowTaskReparenting =
6900 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6901
6902 if (target.task == task) {
6903 // We are inside of the task being reset... we'll either
6904 // finish this activity, push it out for another task,
6905 // or leave it as-is. We only do this
6906 // for activities that are not the root of the task (since
6907 // if we finish the root, we may no longer have the task!).
6908 if (taskTopI < 0) {
6909 taskTopI = targetI;
6910 }
6911 if (below != null && below.task == task) {
6912 final boolean clearWhenTaskReset =
6913 (target.intent.getFlags()
6914 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006915 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006916 // If this activity is sending a reply to a previous
6917 // activity, we can't do anything with it now until
6918 // we reach the start of the reply chain.
6919 // XXX note that we are assuming the result is always
6920 // to the previous activity, which is almost always
6921 // the case but we really shouldn't count on.
6922 if (replyChainEnd < 0) {
6923 replyChainEnd = targetI;
6924 }
Ed Heyl73798232009-03-24 21:32:21 -07006925 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006926 && target.taskAffinity != null
6927 && !target.taskAffinity.equals(task.affinity)) {
6928 // If this activity has an affinity for another
6929 // task, then we need to move it out of here. We will
6930 // move it as far out of the way as possible, to the
6931 // bottom of the activity stack. This also keeps it
6932 // correctly ordered with any activities we previously
6933 // moved.
6934 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6935 if (target.taskAffinity != null
6936 && target.taskAffinity.equals(p.task.affinity)) {
6937 // If the activity currently at the bottom has the
6938 // same task affinity as the one we are moving,
6939 // then merge it into the same task.
6940 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006941 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006942 + " out to bottom task " + p.task);
6943 } else {
6944 mCurTask++;
6945 if (mCurTask <= 0) {
6946 mCurTask = 1;
6947 }
6948 target.task = new TaskRecord(mCurTask, target.info, null,
6949 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6950 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006951 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006952 + " out to new task " + target.task);
6953 }
6954 mWindowManager.setAppGroupId(target, task.taskId);
6955 if (replyChainEnd < 0) {
6956 replyChainEnd = targetI;
6957 }
6958 int dstPos = 0;
6959 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6960 p = (HistoryRecord)mHistory.get(srcPos);
6961 if (p.finishing) {
6962 continue;
6963 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006964 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 + " out to target's task " + target.task);
6966 task.numActivities--;
6967 p.task = target.task;
6968 target.task.numActivities++;
6969 mHistory.remove(srcPos);
6970 mHistory.add(dstPos, p);
6971 mWindowManager.moveAppToken(dstPos, p);
6972 mWindowManager.setAppGroupId(p, p.task.taskId);
6973 dstPos++;
6974 if (VALIDATE_TOKENS) {
6975 mWindowManager.validateAppTokens(mHistory);
6976 }
6977 i++;
6978 }
6979 if (taskTop == p) {
6980 taskTop = below;
6981 }
6982 if (taskTopI == replyChainEnd) {
6983 taskTopI = -1;
6984 }
6985 replyChainEnd = -1;
6986 addRecentTask(target.task);
6987 } else if (forceReset || finishOnTaskLaunch
6988 || clearWhenTaskReset) {
6989 // If the activity should just be removed -- either
6990 // because it asks for it, or the task should be
6991 // cleared -- then finish it and anything that is
6992 // part of its reply chain.
6993 if (clearWhenTaskReset) {
6994 // In this case, we want to finish this activity
6995 // and everything above it, so be sneaky and pretend
6996 // like these are all in the reply chain.
6997 replyChainEnd = targetI+1;
6998 while (replyChainEnd < mHistory.size() &&
6999 ((HistoryRecord)mHistory.get(
7000 replyChainEnd)).task == task) {
7001 replyChainEnd++;
7002 }
7003 replyChainEnd--;
7004 } else if (replyChainEnd < 0) {
7005 replyChainEnd = targetI;
7006 }
7007 HistoryRecord p = null;
7008 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7009 p = (HistoryRecord)mHistory.get(srcPos);
7010 if (p.finishing) {
7011 continue;
7012 }
7013 if (finishActivityLocked(p, srcPos,
7014 Activity.RESULT_CANCELED, null, "reset")) {
7015 replyChainEnd--;
7016 srcPos--;
7017 }
7018 }
7019 if (taskTop == p) {
7020 taskTop = below;
7021 }
7022 if (taskTopI == replyChainEnd) {
7023 taskTopI = -1;
7024 }
7025 replyChainEnd = -1;
7026 } else {
7027 // If we were in the middle of a chain, well the
7028 // activity that started it all doesn't want anything
7029 // special, so leave it all as-is.
7030 replyChainEnd = -1;
7031 }
7032 } else {
7033 // Reached the bottom of the task -- any reply chain
7034 // should be left as-is.
7035 replyChainEnd = -1;
7036 }
7037
7038 } else if (target.resultTo != null) {
7039 // If this activity is sending a reply to a previous
7040 // activity, we can't do anything with it now until
7041 // we reach the start of the reply chain.
7042 // XXX note that we are assuming the result is always
7043 // to the previous activity, which is almost always
7044 // the case but we really shouldn't count on.
7045 if (replyChainEnd < 0) {
7046 replyChainEnd = targetI;
7047 }
7048
7049 } else if (taskTopI >= 0 && allowTaskReparenting
7050 && task.affinity != null
7051 && task.affinity.equals(target.taskAffinity)) {
7052 // We are inside of another task... if this activity has
7053 // an affinity for our task, then either remove it if we are
7054 // clearing or move it over to our task. Note that
7055 // we currently punt on the case where we are resetting a
7056 // task that is not at the top but who has activities above
7057 // with an affinity to it... this is really not a normal
7058 // case, and we will need to later pull that task to the front
7059 // and usually at that point we will do the reset and pick
7060 // up those remaining activities. (This only happens if
7061 // someone starts an activity in a new task from an activity
7062 // in a task that is not currently on top.)
7063 if (forceReset || finishOnTaskLaunch) {
7064 if (replyChainEnd < 0) {
7065 replyChainEnd = targetI;
7066 }
7067 HistoryRecord p = null;
7068 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7069 p = (HistoryRecord)mHistory.get(srcPos);
7070 if (p.finishing) {
7071 continue;
7072 }
7073 if (finishActivityLocked(p, srcPos,
7074 Activity.RESULT_CANCELED, null, "reset")) {
7075 taskTopI--;
7076 lastReparentPos--;
7077 replyChainEnd--;
7078 srcPos--;
7079 }
7080 }
7081 replyChainEnd = -1;
7082 } else {
7083 if (replyChainEnd < 0) {
7084 replyChainEnd = targetI;
7085 }
7086 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7087 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7088 if (p.finishing) {
7089 continue;
7090 }
7091 if (lastReparentPos < 0) {
7092 lastReparentPos = taskTopI;
7093 taskTop = p;
7094 } else {
7095 lastReparentPos--;
7096 }
7097 mHistory.remove(srcPos);
7098 p.task.numActivities--;
7099 p.task = task;
7100 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007101 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007102 + " in to resetting task " + task);
7103 task.numActivities++;
7104 mWindowManager.moveAppToken(lastReparentPos, p);
7105 mWindowManager.setAppGroupId(p, p.task.taskId);
7106 if (VALIDATE_TOKENS) {
7107 mWindowManager.validateAppTokens(mHistory);
7108 }
7109 }
7110 replyChainEnd = -1;
7111
7112 // Now we've moved it in to place... but what if this is
7113 // a singleTop activity and we have put it on top of another
7114 // instance of the same activity? Then we drop the instance
7115 // below so it remains singleTop.
7116 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7117 for (int j=lastReparentPos-1; j>=0; j--) {
7118 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7119 if (p.finishing) {
7120 continue;
7121 }
7122 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7123 if (finishActivityLocked(p, j,
7124 Activity.RESULT_CANCELED, null, "replace")) {
7125 taskTopI--;
7126 lastReparentPos--;
7127 }
7128 }
7129 }
7130 }
7131 }
7132 }
7133
7134 target = below;
7135 targetI = i;
7136 }
7137
7138 return taskTop;
7139 }
7140
7141 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007142 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007143 */
7144 public void moveTaskToFront(int task) {
7145 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7146 "moveTaskToFront()");
7147
7148 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007149 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7150 Binder.getCallingUid(), "Task to front")) {
7151 return;
7152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007153 final long origId = Binder.clearCallingIdentity();
7154 try {
7155 int N = mRecentTasks.size();
7156 for (int i=0; i<N; i++) {
7157 TaskRecord tr = mRecentTasks.get(i);
7158 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007159 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007160 return;
7161 }
7162 }
7163 for (int i=mHistory.size()-1; i>=0; i--) {
7164 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7165 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007166 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007167 return;
7168 }
7169 }
7170 } finally {
7171 Binder.restoreCallingIdentity(origId);
7172 }
7173 }
7174 }
7175
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007176 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007177 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007178
7179 final int task = tr.taskId;
7180 int top = mHistory.size()-1;
7181
7182 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7183 // nothing to do!
7184 return;
7185 }
7186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007187 ArrayList moved = new ArrayList();
7188
7189 // Applying the affinities may have removed entries from the history,
7190 // so get the size again.
7191 top = mHistory.size()-1;
7192 int pos = top;
7193
7194 // Shift all activities with this task up to the top
7195 // of the stack, keeping them in the same internal order.
7196 while (pos >= 0) {
7197 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007198 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007199 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7200 boolean first = true;
7201 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007202 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007203 mHistory.remove(pos);
7204 mHistory.add(top, r);
7205 moved.add(0, r);
7206 top--;
7207 if (first) {
7208 addRecentTask(r.task);
7209 first = false;
7210 }
7211 }
7212 pos--;
7213 }
7214
Joe Onorato8a9b2202010-02-26 18:56:32 -08007215 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007216 "Prepare to front transition: task=" + tr);
7217 if (reason != null &&
7218 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7219 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7220 HistoryRecord r = topRunningActivityLocked(null);
7221 if (r != null) {
7222 mNoAnimActivities.add(r);
7223 }
7224 } else {
7225 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7226 }
7227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 mWindowManager.moveAppTokensToTop(moved);
7229 if (VALIDATE_TOKENS) {
7230 mWindowManager.validateAppTokens(mHistory);
7231 }
7232
7233 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007234 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007235 }
7236
7237 private final void finishTaskMove(int task) {
7238 resumeTopActivityLocked(null);
7239 }
7240
7241 public void moveTaskToBack(int task) {
7242 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7243 "moveTaskToBack()");
7244
7245 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007246 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7247 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7248 Binder.getCallingUid(), "Task to back")) {
7249 return;
7250 }
7251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007253 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007254 Binder.restoreCallingIdentity(origId);
7255 }
7256 }
7257
7258 /**
7259 * Moves an activity, and all of the other activities within the same task, to the bottom
7260 * of the history stack. The activity's order within the task is unchanged.
7261 *
7262 * @param token A reference to the activity we wish to move
7263 * @param nonRoot If false then this only works if the activity is the root
7264 * of a task; if true it will work for any activity in a task.
7265 * @return Returns true if the move completed, false if not.
7266 */
7267 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7268 synchronized(this) {
7269 final long origId = Binder.clearCallingIdentity();
7270 int taskId = getTaskForActivityLocked(token, !nonRoot);
7271 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007272 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273 }
7274 Binder.restoreCallingIdentity(origId);
7275 }
7276 return false;
7277 }
7278
7279 /**
7280 * Worker method for rearranging history stack. Implements the function of moving all
7281 * activities for a specific task (gathering them if disjoint) into a single group at the
7282 * bottom of the stack.
7283 *
7284 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7285 * to premeptively cancel the move.
7286 *
7287 * @param task The taskId to collect and move to the bottom.
7288 * @return Returns true if the move completed, false if not.
7289 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007290 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007291 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007292
7293 // If we have a watcher, preflight the move before committing to it. First check
7294 // for *other* available tasks, but if none are available, then try again allowing the
7295 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007296 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007297 HistoryRecord next = topRunningActivityLocked(null, task);
7298 if (next == null) {
7299 next = topRunningActivityLocked(null, 0);
7300 }
7301 if (next != null) {
7302 // ask watcher if this is allowed
7303 boolean moveOK = true;
7304 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007305 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007307 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 }
7309 if (!moveOK) {
7310 return false;
7311 }
7312 }
7313 }
7314
7315 ArrayList moved = new ArrayList();
7316
Joe Onorato8a9b2202010-02-26 18:56:32 -08007317 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007318 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007319
7320 final int N = mHistory.size();
7321 int bottom = 0;
7322 int pos = 0;
7323
7324 // Shift all activities with this task down to the bottom
7325 // of the stack, keeping them in the same internal order.
7326 while (pos < N) {
7327 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007328 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7330 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007331 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007332 mHistory.remove(pos);
7333 mHistory.add(bottom, r);
7334 moved.add(r);
7335 bottom++;
7336 }
7337 pos++;
7338 }
7339
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007340 if (reason != null &&
7341 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7342 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7343 HistoryRecord r = topRunningActivityLocked(null);
7344 if (r != null) {
7345 mNoAnimActivities.add(r);
7346 }
7347 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007348 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 mWindowManager.moveAppTokensToBottom(moved);
7351 if (VALIDATE_TOKENS) {
7352 mWindowManager.validateAppTokens(mHistory);
7353 }
7354
7355 finishTaskMove(task);
7356 return true;
7357 }
7358
7359 public void moveTaskBackwards(int task) {
7360 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7361 "moveTaskBackwards()");
7362
7363 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007364 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7365 Binder.getCallingUid(), "Task backwards")) {
7366 return;
7367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 final long origId = Binder.clearCallingIdentity();
7369 moveTaskBackwardsLocked(task);
7370 Binder.restoreCallingIdentity(origId);
7371 }
7372 }
7373
7374 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007375 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 }
7377
7378 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7379 synchronized(this) {
7380 return getTaskForActivityLocked(token, onlyRoot);
7381 }
7382 }
7383
7384 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7385 final int N = mHistory.size();
7386 TaskRecord lastTask = null;
7387 for (int i=0; i<N; i++) {
7388 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7389 if (r == token) {
7390 if (!onlyRoot || lastTask != r.task) {
7391 return r.task.taskId;
7392 }
7393 return -1;
7394 }
7395 lastTask = r.task;
7396 }
7397
7398 return -1;
7399 }
7400
7401 /**
7402 * Returns the top activity in any existing task matching the given
7403 * Intent. Returns null if no such task is found.
7404 */
7405 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7406 ComponentName cls = intent.getComponent();
7407 if (info.targetActivity != null) {
7408 cls = new ComponentName(info.packageName, info.targetActivity);
7409 }
7410
7411 TaskRecord cp = null;
7412
7413 final int N = mHistory.size();
7414 for (int i=(N-1); i>=0; i--) {
7415 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7416 if (!r.finishing && r.task != cp
7417 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7418 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007419 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007420 // + "/aff=" + r.task.affinity + " to new cls="
7421 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7422 if (r.task.affinity != null) {
7423 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007424 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007425 return r;
7426 }
7427 } else if (r.task.intent != null
7428 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007429 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007431 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432 return r;
7433 } else if (r.task.affinityIntent != null
7434 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007435 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007437 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 return r;
7439 }
7440 }
7441 }
7442
7443 return null;
7444 }
7445
7446 /**
7447 * Returns the first activity (starting from the top of the stack) that
7448 * is the same as the given activity. Returns null if no such activity
7449 * is found.
7450 */
7451 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7452 ComponentName cls = intent.getComponent();
7453 if (info.targetActivity != null) {
7454 cls = new ComponentName(info.packageName, info.targetActivity);
7455 }
7456
7457 final int N = mHistory.size();
7458 for (int i=(N-1); i>=0; i--) {
7459 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7460 if (!r.finishing) {
7461 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007462 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007463 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007464 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 return r;
7466 }
7467 }
7468 }
7469
7470 return null;
7471 }
7472
7473 public void finishOtherInstances(IBinder token, ComponentName className) {
7474 synchronized(this) {
7475 final long origId = Binder.clearCallingIdentity();
7476
7477 int N = mHistory.size();
7478 TaskRecord lastTask = null;
7479 for (int i=0; i<N; i++) {
7480 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7481 if (r.realActivity.equals(className)
7482 && r != token && lastTask != r.task) {
7483 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7484 null, "others")) {
7485 i--;
7486 N--;
7487 }
7488 }
7489 lastTask = r.task;
7490 }
7491
7492 Binder.restoreCallingIdentity(origId);
7493 }
7494 }
7495
7496 // =========================================================
7497 // THUMBNAILS
7498 // =========================================================
7499
7500 public void reportThumbnail(IBinder token,
7501 Bitmap thumbnail, CharSequence description) {
7502 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7503 final long origId = Binder.clearCallingIdentity();
7504 sendPendingThumbnail(null, token, thumbnail, description, true);
7505 Binder.restoreCallingIdentity(origId);
7506 }
7507
7508 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7509 Bitmap thumbnail, CharSequence description, boolean always) {
7510 TaskRecord task = null;
7511 ArrayList receivers = null;
7512
7513 //System.out.println("Send pending thumbnail: " + r);
7514
7515 synchronized(this) {
7516 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007517 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007518 if (index < 0) {
7519 return;
7520 }
7521 r = (HistoryRecord)mHistory.get(index);
7522 }
7523 if (thumbnail == null) {
7524 thumbnail = r.thumbnail;
7525 description = r.description;
7526 }
7527 if (thumbnail == null && !always) {
7528 // If there is no thumbnail, and this entry is not actually
7529 // going away, then abort for now and pick up the next
7530 // thumbnail we get.
7531 return;
7532 }
7533 task = r.task;
7534
7535 int N = mPendingThumbnails.size();
7536 int i=0;
7537 while (i<N) {
7538 PendingThumbnailsRecord pr =
7539 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7540 //System.out.println("Looking in " + pr.pendingRecords);
7541 if (pr.pendingRecords.remove(r)) {
7542 if (receivers == null) {
7543 receivers = new ArrayList();
7544 }
7545 receivers.add(pr);
7546 if (pr.pendingRecords.size() == 0) {
7547 pr.finished = true;
7548 mPendingThumbnails.remove(i);
7549 N--;
7550 continue;
7551 }
7552 }
7553 i++;
7554 }
7555 }
7556
7557 if (receivers != null) {
7558 final int N = receivers.size();
7559 for (int i=0; i<N; i++) {
7560 try {
7561 PendingThumbnailsRecord pr =
7562 (PendingThumbnailsRecord)receivers.get(i);
7563 pr.receiver.newThumbnail(
7564 task != null ? task.taskId : -1, thumbnail, description);
7565 if (pr.finished) {
7566 pr.receiver.finished();
7567 }
7568 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007569 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 }
7571 }
7572 }
7573 }
7574
7575 // =========================================================
7576 // CONTENT PROVIDERS
7577 // =========================================================
7578
7579 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7580 List providers = null;
7581 try {
7582 providers = ActivityThread.getPackageManager().
7583 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007584 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007585 } catch (RemoteException ex) {
7586 }
7587 if (providers != null) {
7588 final int N = providers.size();
7589 for (int i=0; i<N; i++) {
7590 ProviderInfo cpi =
7591 (ProviderInfo)providers.get(i);
7592 ContentProviderRecord cpr =
7593 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7594 if (cpr == null) {
7595 cpr = new ContentProviderRecord(cpi, app.info);
7596 mProvidersByClass.put(cpi.name, cpr);
7597 }
7598 app.pubProviders.put(cpi.name, cpr);
7599 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007600 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007601 }
7602 }
7603 return providers;
7604 }
7605
7606 private final String checkContentProviderPermissionLocked(
7607 ProviderInfo cpi, ProcessRecord r, int mode) {
7608 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7609 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7610 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7611 cpi.exported ? -1 : cpi.applicationInfo.uid)
7612 == PackageManager.PERMISSION_GRANTED
7613 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7614 return null;
7615 }
7616 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7617 cpi.exported ? -1 : cpi.applicationInfo.uid)
7618 == PackageManager.PERMISSION_GRANTED) {
7619 return null;
7620 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007621
7622 PathPermission[] pps = cpi.pathPermissions;
7623 if (pps != null) {
7624 int i = pps.length;
7625 while (i > 0) {
7626 i--;
7627 PathPermission pp = pps[i];
7628 if (checkComponentPermission(pp.getReadPermission(), 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(pp.getWritePermission(), callingPid, callingUid,
7635 cpi.exported ? -1 : cpi.applicationInfo.uid)
7636 == PackageManager.PERMISSION_GRANTED) {
7637 return null;
7638 }
7639 }
7640 }
7641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007642 String msg = "Permission Denial: opening provider " + cpi.name
7643 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7644 + ", uid=" + callingUid + ") requires "
7645 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007646 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007647 return msg;
7648 }
7649
7650 private final ContentProviderHolder getContentProviderImpl(
7651 IApplicationThread caller, String name) {
7652 ContentProviderRecord cpr;
7653 ProviderInfo cpi = null;
7654
7655 synchronized(this) {
7656 ProcessRecord r = null;
7657 if (caller != null) {
7658 r = getRecordForAppLocked(caller);
7659 if (r == null) {
7660 throw new SecurityException(
7661 "Unable to find app for caller " + caller
7662 + " (pid=" + Binder.getCallingPid()
7663 + ") when getting content provider " + name);
7664 }
7665 }
7666
7667 // First check if this content provider has been published...
7668 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7669 if (cpr != null) {
7670 cpi = cpr.info;
7671 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7672 return new ContentProviderHolder(cpi,
7673 cpi.readPermission != null
7674 ? cpi.readPermission : cpi.writePermission);
7675 }
7676
7677 if (r != null && cpr.canRunHere(r)) {
7678 // This provider has been published or is in the process
7679 // of being published... but it is also allowed to run
7680 // in the caller's process, so don't make a connection
7681 // and just let the caller instantiate its own instance.
7682 if (cpr.provider != null) {
7683 // don't give caller the provider object, it needs
7684 // to make its own.
7685 cpr = new ContentProviderRecord(cpr);
7686 }
7687 return cpr;
7688 }
7689
7690 final long origId = Binder.clearCallingIdentity();
7691
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007692 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007693 // return it right away.
7694 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007695 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007696 "Adding provider requested by "
7697 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007698 + cpr.info.processName);
7699 Integer cnt = r.conProviders.get(cpr);
7700 if (cnt == null) {
7701 r.conProviders.put(cpr, new Integer(1));
7702 } else {
7703 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705 cpr.clients.add(r);
7706 } else {
7707 cpr.externals++;
7708 }
7709
7710 if (cpr.app != null) {
7711 updateOomAdjLocked(cpr.app);
7712 }
7713
7714 Binder.restoreCallingIdentity(origId);
7715
7716 } else {
7717 try {
7718 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007719 resolveContentProvider(name,
7720 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007721 } catch (RemoteException ex) {
7722 }
7723 if (cpi == null) {
7724 return null;
7725 }
7726
7727 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7728 return new ContentProviderHolder(cpi,
7729 cpi.readPermission != null
7730 ? cpi.readPermission : cpi.writePermission);
7731 }
7732
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007733 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7734 && !cpi.processName.equals("system")) {
7735 // If this content provider does not run in the system
7736 // process, and the system is not yet ready to run other
7737 // processes, then fail fast instead of hanging.
7738 throw new IllegalArgumentException(
7739 "Attempt to launch content provider before system ready");
7740 }
7741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7743 final boolean firstClass = cpr == null;
7744 if (firstClass) {
7745 try {
7746 ApplicationInfo ai =
7747 ActivityThread.getPackageManager().
7748 getApplicationInfo(
7749 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007750 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007752 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007753 + cpi.name);
7754 return null;
7755 }
7756 cpr = new ContentProviderRecord(cpi, ai);
7757 } catch (RemoteException ex) {
7758 // pm is in same process, this will never happen.
7759 }
7760 }
7761
7762 if (r != null && cpr.canRunHere(r)) {
7763 // If this is a multiprocess provider, then just return its
7764 // info and allow the caller to instantiate it. Only do
7765 // this if the provider is the same user as the caller's
7766 // process, or can run as root (so can be in any process).
7767 return cpr;
7768 }
7769
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007770 if (DEBUG_PROVIDER) {
7771 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007772 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007773 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774 }
7775
7776 // This is single process, and our app is now connecting to it.
7777 // See if we are already in the process of launching this
7778 // provider.
7779 final int N = mLaunchingProviders.size();
7780 int i;
7781 for (i=0; i<N; i++) {
7782 if (mLaunchingProviders.get(i) == cpr) {
7783 break;
7784 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 }
7786
7787 // If the provider is not already being launched, then get it
7788 // started.
7789 if (i >= N) {
7790 final long origId = Binder.clearCallingIdentity();
7791 ProcessRecord proc = startProcessLocked(cpi.processName,
7792 cpr.appInfo, false, 0, "content provider",
7793 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007794 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007795 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007796 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 + cpi.applicationInfo.packageName + "/"
7798 + cpi.applicationInfo.uid + " for provider "
7799 + name + ": process is bad");
7800 return null;
7801 }
7802 cpr.launchingApp = proc;
7803 mLaunchingProviders.add(cpr);
7804 Binder.restoreCallingIdentity(origId);
7805 }
7806
7807 // Make sure the provider is published (the same provider class
7808 // may be published under multiple names).
7809 if (firstClass) {
7810 mProvidersByClass.put(cpi.name, cpr);
7811 }
7812 mProvidersByName.put(name, cpr);
7813
7814 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007815 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007816 "Adding provider requested by "
7817 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007818 + cpr.info.processName);
7819 Integer cnt = r.conProviders.get(cpr);
7820 if (cnt == null) {
7821 r.conProviders.put(cpr, new Integer(1));
7822 } else {
7823 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 cpr.clients.add(r);
7826 } else {
7827 cpr.externals++;
7828 }
7829 }
7830 }
7831
7832 // Wait for the provider to be published...
7833 synchronized (cpr) {
7834 while (cpr.provider == null) {
7835 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007836 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007837 + cpi.applicationInfo.packageName + "/"
7838 + cpi.applicationInfo.uid + " for provider "
7839 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007840 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 cpi.applicationInfo.packageName,
7842 cpi.applicationInfo.uid, name);
7843 return null;
7844 }
7845 try {
7846 cpr.wait();
7847 } catch (InterruptedException ex) {
7848 }
7849 }
7850 }
7851 return cpr;
7852 }
7853
7854 public final ContentProviderHolder getContentProvider(
7855 IApplicationThread caller, String name) {
7856 if (caller == null) {
7857 String msg = "null IApplicationThread when getting content provider "
7858 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007859 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007860 throw new SecurityException(msg);
7861 }
7862
7863 return getContentProviderImpl(caller, name);
7864 }
7865
7866 private ContentProviderHolder getContentProviderExternal(String name) {
7867 return getContentProviderImpl(null, name);
7868 }
7869
7870 /**
7871 * Drop a content provider from a ProcessRecord's bookkeeping
7872 * @param cpr
7873 */
7874 public void removeContentProvider(IApplicationThread caller, String name) {
7875 synchronized (this) {
7876 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7877 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007878 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007879 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007880 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 return;
7882 }
7883 final ProcessRecord r = getRecordForAppLocked(caller);
7884 if (r == null) {
7885 throw new SecurityException(
7886 "Unable to find app for caller " + caller +
7887 " when removing content provider " + name);
7888 }
7889 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007890 ContentProviderRecord localCpr = (ContentProviderRecord)
7891 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007892 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007893 + r.info.processName + " from process "
7894 + localCpr.appInfo.processName);
7895 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007896 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007897 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007898 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007899 return;
7900 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007901 Integer cnt = r.conProviders.get(localCpr);
7902 if (cnt == null || cnt.intValue() <= 1) {
7903 localCpr.clients.remove(r);
7904 r.conProviders.remove(localCpr);
7905 } else {
7906 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 }
7909 updateOomAdjLocked();
7910 }
7911 }
7912
7913 private void removeContentProviderExternal(String name) {
7914 synchronized (this) {
7915 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7916 if(cpr == null) {
7917 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007918 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007919 return;
7920 }
7921
7922 //update content provider record entry info
7923 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7924 localCpr.externals--;
7925 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007926 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927 }
7928 updateOomAdjLocked();
7929 }
7930 }
7931
7932 public final void publishContentProviders(IApplicationThread caller,
7933 List<ContentProviderHolder> providers) {
7934 if (providers == null) {
7935 return;
7936 }
7937
7938 synchronized(this) {
7939 final ProcessRecord r = getRecordForAppLocked(caller);
7940 if (r == null) {
7941 throw new SecurityException(
7942 "Unable to find app for caller " + caller
7943 + " (pid=" + Binder.getCallingPid()
7944 + ") when publishing content providers");
7945 }
7946
7947 final long origId = Binder.clearCallingIdentity();
7948
7949 final int N = providers.size();
7950 for (int i=0; i<N; i++) {
7951 ContentProviderHolder src = providers.get(i);
7952 if (src == null || src.info == null || src.provider == null) {
7953 continue;
7954 }
7955 ContentProviderRecord dst =
7956 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7957 if (dst != null) {
7958 mProvidersByClass.put(dst.info.name, dst);
7959 String names[] = dst.info.authority.split(";");
7960 for (int j = 0; j < names.length; j++) {
7961 mProvidersByName.put(names[j], dst);
7962 }
7963
7964 int NL = mLaunchingProviders.size();
7965 int j;
7966 for (j=0; j<NL; j++) {
7967 if (mLaunchingProviders.get(j) == dst) {
7968 mLaunchingProviders.remove(j);
7969 j--;
7970 NL--;
7971 }
7972 }
7973 synchronized (dst) {
7974 dst.provider = src.provider;
7975 dst.app = r;
7976 dst.notifyAll();
7977 }
7978 updateOomAdjLocked(r);
7979 }
7980 }
7981
7982 Binder.restoreCallingIdentity(origId);
7983 }
7984 }
7985
7986 public static final void installSystemProviders() {
7987 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7988 List providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007989 if (providers != null) {
7990 for (int i=providers.size()-1; i>=0; i--) {
7991 ProviderInfo pi = (ProviderInfo)providers.get(i);
7992 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007993 Slog.w(TAG, "Not installing system proc provider " + pi.name
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007994 + ": not system .apk");
7995 providers.remove(i);
7996 }
7997 }
7998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007999 mSystemThread.installSystemProviders(providers);
8000 }
8001
8002 // =========================================================
8003 // GLOBAL MANAGEMENT
8004 // =========================================================
8005
8006 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8007 ApplicationInfo info, String customProcess) {
8008 String proc = customProcess != null ? customProcess : info.processName;
8009 BatteryStatsImpl.Uid.Proc ps = null;
8010 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8011 synchronized (stats) {
8012 ps = stats.getProcessStatsLocked(info.uid, proc);
8013 }
8014 return new ProcessRecord(ps, thread, info, proc);
8015 }
8016
8017 final ProcessRecord addAppLocked(ApplicationInfo info) {
8018 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8019
8020 if (app == null) {
8021 app = newProcessRecordLocked(null, info, null);
8022 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008023 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 }
8025
8026 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8027 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8028 app.persistent = true;
8029 app.maxAdj = CORE_SERVER_ADJ;
8030 }
8031 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8032 mPersistentStartingProcesses.add(app);
8033 startProcessLocked(app, "added application", app.processName);
8034 }
8035
8036 return app;
8037 }
8038
8039 public void unhandledBack() {
8040 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8041 "unhandledBack()");
8042
8043 synchronized(this) {
8044 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008045 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008046 TAG, "Performing unhandledBack(): stack size = " + count);
8047 if (count > 1) {
8048 final long origId = Binder.clearCallingIdentity();
8049 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8050 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8051 Binder.restoreCallingIdentity(origId);
8052 }
8053 }
8054 }
8055
8056 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8057 String name = uri.getAuthority();
8058 ContentProviderHolder cph = getContentProviderExternal(name);
8059 ParcelFileDescriptor pfd = null;
8060 if (cph != null) {
8061 // We record the binder invoker's uid in thread-local storage before
8062 // going to the content provider to open the file. Later, in the code
8063 // that handles all permissions checks, we look for this uid and use
8064 // that rather than the Activity Manager's own uid. The effect is that
8065 // we do the check against the caller's permissions even though it looks
8066 // to the content provider like the Activity Manager itself is making
8067 // the request.
8068 sCallerIdentity.set(new Identity(
8069 Binder.getCallingPid(), Binder.getCallingUid()));
8070 try {
8071 pfd = cph.provider.openFile(uri, "r");
8072 } catch (FileNotFoundException e) {
8073 // do nothing; pfd will be returned null
8074 } finally {
8075 // Ensure that whatever happens, we clean up the identity state
8076 sCallerIdentity.remove();
8077 }
8078
8079 // We've got the fd now, so we're done with the provider.
8080 removeContentProviderExternal(name);
8081 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008082 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008083 }
8084 return pfd;
8085 }
8086
8087 public void goingToSleep() {
8088 synchronized(this) {
8089 mSleeping = true;
8090 mWindowManager.setEventDispatching(false);
8091
8092 if (mResumedActivity != null) {
8093 pauseIfSleepingLocked();
8094 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008095 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008096 }
8097 }
8098 }
8099
Dianne Hackborn55280a92009-05-07 15:53:46 -07008100 public boolean shutdown(int timeout) {
8101 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8102 != PackageManager.PERMISSION_GRANTED) {
8103 throw new SecurityException("Requires permission "
8104 + android.Manifest.permission.SHUTDOWN);
8105 }
8106
8107 boolean timedout = false;
8108
8109 synchronized(this) {
8110 mShuttingDown = true;
8111 mWindowManager.setEventDispatching(false);
8112
8113 if (mResumedActivity != null) {
8114 pauseIfSleepingLocked();
8115 final long endTime = System.currentTimeMillis() + timeout;
8116 while (mResumedActivity != null || mPausingActivity != null) {
8117 long delay = endTime - System.currentTimeMillis();
8118 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008119 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008120 timedout = true;
8121 break;
8122 }
8123 try {
8124 this.wait();
8125 } catch (InterruptedException e) {
8126 }
8127 }
8128 }
8129 }
8130
8131 mUsageStatsService.shutdown();
8132 mBatteryStatsService.shutdown();
8133
8134 return timedout;
8135 }
8136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008138 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 if (!mGoingToSleep.isHeld()) {
8140 mGoingToSleep.acquire();
8141 if (mLaunchingActivity.isHeld()) {
8142 mLaunchingActivity.release();
8143 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8144 }
8145 }
8146
8147 // If we are not currently pausing an activity, get the current
8148 // one to pause. If we are pausing one, we will just let that stuff
8149 // run and release the wake lock when all done.
8150 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008151 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8152 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008153 startPausingLocked(false, true);
8154 }
8155 }
8156 }
8157
8158 public void wakingUp() {
8159 synchronized(this) {
8160 if (mGoingToSleep.isHeld()) {
8161 mGoingToSleep.release();
8162 }
8163 mWindowManager.setEventDispatching(true);
8164 mSleeping = false;
8165 resumeTopActivityLocked(null);
8166 }
8167 }
8168
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008169 public void stopAppSwitches() {
8170 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8171 != PackageManager.PERMISSION_GRANTED) {
8172 throw new SecurityException("Requires permission "
8173 + android.Manifest.permission.STOP_APP_SWITCHES);
8174 }
8175
8176 synchronized(this) {
8177 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8178 + APP_SWITCH_DELAY_TIME;
8179 mDidAppSwitch = false;
8180 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8181 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8182 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8183 }
8184 }
8185
8186 public void resumeAppSwitches() {
8187 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8188 != PackageManager.PERMISSION_GRANTED) {
8189 throw new SecurityException("Requires permission "
8190 + android.Manifest.permission.STOP_APP_SWITCHES);
8191 }
8192
8193 synchronized(this) {
8194 // Note that we don't execute any pending app switches... we will
8195 // let those wait until either the timeout, or the next start
8196 // activity request.
8197 mAppSwitchesAllowedTime = 0;
8198 }
8199 }
8200
8201 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8202 String name) {
8203 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8204 return true;
8205 }
8206
8207 final int perm = checkComponentPermission(
8208 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8209 callingUid, -1);
8210 if (perm == PackageManager.PERMISSION_GRANTED) {
8211 return true;
8212 }
8213
Joe Onorato8a9b2202010-02-26 18:56:32 -08008214 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008215 return false;
8216 }
8217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008218 public void setDebugApp(String packageName, boolean waitForDebugger,
8219 boolean persistent) {
8220 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8221 "setDebugApp()");
8222
8223 // Note that this is not really thread safe if there are multiple
8224 // callers into it at the same time, but that's not a situation we
8225 // care about.
8226 if (persistent) {
8227 final ContentResolver resolver = mContext.getContentResolver();
8228 Settings.System.putString(
8229 resolver, Settings.System.DEBUG_APP,
8230 packageName);
8231 Settings.System.putInt(
8232 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8233 waitForDebugger ? 1 : 0);
8234 }
8235
8236 synchronized (this) {
8237 if (!persistent) {
8238 mOrigDebugApp = mDebugApp;
8239 mOrigWaitForDebugger = mWaitForDebugger;
8240 }
8241 mDebugApp = packageName;
8242 mWaitForDebugger = waitForDebugger;
8243 mDebugTransient = !persistent;
8244 if (packageName != null) {
8245 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008246 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 Binder.restoreCallingIdentity(origId);
8248 }
8249 }
8250 }
8251
8252 public void setAlwaysFinish(boolean enabled) {
8253 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8254 "setAlwaysFinish()");
8255
8256 Settings.System.putInt(
8257 mContext.getContentResolver(),
8258 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8259
8260 synchronized (this) {
8261 mAlwaysFinishActivities = enabled;
8262 }
8263 }
8264
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008265 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008267 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008269 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270 }
8271 }
8272
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008273 public boolean isUserAMonkey() {
8274 // For now the fact that there is a controller implies
8275 // we have a monkey.
8276 synchronized (this) {
8277 return mController != null;
8278 }
8279 }
8280
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008281 public void registerActivityWatcher(IActivityWatcher watcher) {
8282 mWatchers.register(watcher);
8283 }
8284
8285 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8286 mWatchers.unregister(watcher);
8287 }
8288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008289 public final void enterSafeMode() {
8290 synchronized(this) {
8291 // It only makes sense to do this before the system is ready
8292 // and started launching other packages.
8293 if (!mSystemReady) {
8294 try {
8295 ActivityThread.getPackageManager().enterSafeMode();
8296 } catch (RemoteException e) {
8297 }
8298
8299 View v = LayoutInflater.from(mContext).inflate(
8300 com.android.internal.R.layout.safe_mode, null);
8301 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8302 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8303 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8304 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8305 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8306 lp.format = v.getBackground().getOpacity();
8307 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8308 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8309 ((WindowManager)mContext.getSystemService(
8310 Context.WINDOW_SERVICE)).addView(v, lp);
8311 }
8312 }
8313 }
8314
8315 public void noteWakeupAlarm(IIntentSender sender) {
8316 if (!(sender instanceof PendingIntentRecord)) {
8317 return;
8318 }
8319 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8320 synchronized (stats) {
8321 if (mBatteryStatsService.isOnBattery()) {
8322 mBatteryStatsService.enforceCallingPermission();
8323 PendingIntentRecord rec = (PendingIntentRecord)sender;
8324 int MY_UID = Binder.getCallingUid();
8325 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8326 BatteryStatsImpl.Uid.Pkg pkg =
8327 stats.getPackageStatsLocked(uid, rec.key.packageName);
8328 pkg.incWakeupsLocked();
8329 }
8330 }
8331 }
8332
8333 public boolean killPidsForMemory(int[] pids) {
8334 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8335 throw new SecurityException("killPidsForMemory only available to the system");
8336 }
8337
8338 // XXX Note: don't acquire main activity lock here, because the window
8339 // manager calls in with its locks held.
8340
8341 boolean killed = false;
8342 synchronized (mPidsSelfLocked) {
8343 int[] types = new int[pids.length];
8344 int worstType = 0;
8345 for (int i=0; i<pids.length; i++) {
8346 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8347 if (proc != null) {
8348 int type = proc.setAdj;
8349 types[i] = type;
8350 if (type > worstType) {
8351 worstType = type;
8352 }
8353 }
8354 }
8355
8356 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8357 // then constrain it so we will kill all hidden procs.
8358 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8359 worstType = HIDDEN_APP_MIN_ADJ;
8360 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008361 Slog.w(TAG, "Killing processes for memory at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008362 for (int i=0; i<pids.length; i++) {
8363 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8364 if (proc == null) {
8365 continue;
8366 }
8367 int adj = proc.setAdj;
8368 if (adj >= worstType) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008369 Slog.w(TAG, "Killing for memory: " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008370 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008371 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008372 proc.processName, adj);
8373 killed = true;
8374 Process.killProcess(pids[i]);
8375 }
8376 }
8377 }
8378 return killed;
8379 }
8380
8381 public void reportPss(IApplicationThread caller, int pss) {
8382 Watchdog.PssRequestor req;
8383 String name;
8384 ProcessRecord callerApp;
8385 synchronized (this) {
8386 if (caller == null) {
8387 return;
8388 }
8389 callerApp = getRecordForAppLocked(caller);
8390 if (callerApp == null) {
8391 return;
8392 }
8393 callerApp.lastPss = pss;
8394 req = callerApp;
8395 name = callerApp.processName;
8396 }
8397 Watchdog.getInstance().reportPss(req, name, pss);
8398 if (!callerApp.persistent) {
8399 removeRequestedPss(callerApp);
8400 }
8401 }
8402
8403 public void requestPss(Runnable completeCallback) {
8404 ArrayList<ProcessRecord> procs;
8405 synchronized (this) {
8406 mRequestPssCallback = completeCallback;
8407 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008408 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8409 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008410 if (!proc.persistent) {
8411 mRequestPssList.add(proc);
8412 }
8413 }
8414 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8415 }
8416
8417 int oldPri = Process.getThreadPriority(Process.myTid());
8418 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8419 for (int i=procs.size()-1; i>=0; i--) {
8420 ProcessRecord proc = procs.get(i);
8421 proc.lastPss = 0;
8422 proc.requestPss();
8423 }
8424 Process.setThreadPriority(oldPri);
8425 }
8426
8427 void removeRequestedPss(ProcessRecord proc) {
8428 Runnable callback = null;
8429 synchronized (this) {
8430 if (mRequestPssList.remove(proc)) {
8431 if (mRequestPssList.size() == 0) {
8432 callback = mRequestPssCallback;
8433 mRequestPssCallback = null;
8434 }
8435 }
8436 }
8437
8438 if (callback != null) {
8439 callback.run();
8440 }
8441 }
8442
8443 public void collectPss(Watchdog.PssStats stats) {
8444 stats.mEmptyPss = 0;
8445 stats.mEmptyCount = 0;
8446 stats.mBackgroundPss = 0;
8447 stats.mBackgroundCount = 0;
8448 stats.mServicePss = 0;
8449 stats.mServiceCount = 0;
8450 stats.mVisiblePss = 0;
8451 stats.mVisibleCount = 0;
8452 stats.mForegroundPss = 0;
8453 stats.mForegroundCount = 0;
8454 stats.mNoPssCount = 0;
8455 synchronized (this) {
8456 int i;
8457 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8458 ? mProcDeaths.length : stats.mProcDeaths.length;
8459 int aggr = 0;
8460 for (i=0; i<NPD; i++) {
8461 aggr += mProcDeaths[i];
8462 stats.mProcDeaths[i] = aggr;
8463 }
8464 while (i<stats.mProcDeaths.length) {
8465 stats.mProcDeaths[i] = 0;
8466 i++;
8467 }
8468
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008469 for (i=mLruProcesses.size()-1; i>=0; i--) {
8470 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 if (proc.persistent) {
8472 continue;
8473 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008474 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475 if (proc.lastPss == 0) {
8476 stats.mNoPssCount++;
8477 continue;
8478 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008479 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8480 if (proc.empty) {
8481 stats.mEmptyPss += proc.lastPss;
8482 stats.mEmptyCount++;
8483 } else {
8484 stats.mBackgroundPss += proc.lastPss;
8485 stats.mBackgroundCount++;
8486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008487 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8488 stats.mVisiblePss += proc.lastPss;
8489 stats.mVisibleCount++;
8490 } else {
8491 stats.mForegroundPss += proc.lastPss;
8492 stats.mForegroundCount++;
8493 }
8494 }
8495 }
8496 }
8497
8498 public final void startRunning(String pkg, String cls, String action,
8499 String data) {
8500 synchronized(this) {
8501 if (mStartRunning) {
8502 return;
8503 }
8504 mStartRunning = true;
8505 mTopComponent = pkg != null && cls != null
8506 ? new ComponentName(pkg, cls) : null;
8507 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8508 mTopData = data;
8509 if (!mSystemReady) {
8510 return;
8511 }
8512 }
8513
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008514 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 }
8516
8517 private void retrieveSettings() {
8518 final ContentResolver resolver = mContext.getContentResolver();
8519 String debugApp = Settings.System.getString(
8520 resolver, Settings.System.DEBUG_APP);
8521 boolean waitForDebugger = Settings.System.getInt(
8522 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8523 boolean alwaysFinishActivities = Settings.System.getInt(
8524 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8525
8526 Configuration configuration = new Configuration();
8527 Settings.System.getConfiguration(resolver, configuration);
8528
8529 synchronized (this) {
8530 mDebugApp = mOrigDebugApp = debugApp;
8531 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8532 mAlwaysFinishActivities = alwaysFinishActivities;
8533 // This happens before any activities are started, so we can
8534 // change mConfiguration in-place.
8535 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008536 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008537 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008538 }
8539 }
8540
8541 public boolean testIsSystemReady() {
8542 // no need to synchronize(this) just to read & return the value
8543 return mSystemReady;
8544 }
8545
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008546 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008547 // In the simulator, startRunning will never have been called, which
8548 // normally sets a few crucial variables. Do it here instead.
8549 if (!Process.supportsProcesses()) {
8550 mStartRunning = true;
8551 mTopAction = Intent.ACTION_MAIN;
8552 }
8553
8554 synchronized(this) {
8555 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008556 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008557 return;
8558 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008559
8560 // Check to see if there are any update receivers to run.
8561 if (!mDidUpdate) {
8562 if (mWaitingUpdate) {
8563 return;
8564 }
8565 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8566 List<ResolveInfo> ris = null;
8567 try {
8568 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8569 intent, null, 0);
8570 } catch (RemoteException e) {
8571 }
8572 if (ris != null) {
8573 for (int i=ris.size()-1; i>=0; i--) {
8574 if ((ris.get(i).activityInfo.applicationInfo.flags
8575 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8576 ris.remove(i);
8577 }
8578 }
8579 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8580 for (int i=0; i<ris.size(); i++) {
8581 ActivityInfo ai = ris.get(i).activityInfo;
8582 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8583 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008584 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008585 finisher = new IIntentReceiver.Stub() {
8586 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008587 String data, Bundle extras, boolean ordered,
8588 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008589 throws RemoteException {
8590 synchronized (ActivityManagerService.this) {
8591 mDidUpdate = true;
8592 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008593 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008594 }
8595 };
8596 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008597 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008598 broadcastIntentLocked(null, null, intent, null, finisher,
8599 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008600 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008601 mWaitingUpdate = true;
8602 }
8603 }
8604 }
8605 if (mWaitingUpdate) {
8606 return;
8607 }
8608 mDidUpdate = true;
8609 }
8610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008611 mSystemReady = true;
8612 if (!mStartRunning) {
8613 return;
8614 }
8615 }
8616
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008617 ArrayList<ProcessRecord> procsToKill = null;
8618 synchronized(mPidsSelfLocked) {
8619 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8620 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8621 if (!isAllowedWhileBooting(proc.info)){
8622 if (procsToKill == null) {
8623 procsToKill = new ArrayList<ProcessRecord>();
8624 }
8625 procsToKill.add(proc);
8626 }
8627 }
8628 }
8629
8630 if (procsToKill != null) {
8631 synchronized(this) {
8632 for (int i=procsToKill.size()-1; i>=0; i--) {
8633 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008634 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008635 removeProcessLocked(proc, true);
8636 }
8637 }
8638 }
8639
Joe Onorato8a9b2202010-02-26 18:56:32 -08008640 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008641 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642 SystemClock.uptimeMillis());
8643
8644 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008645 // Make sure we have no pre-ready processes sitting around.
8646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008647 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8648 ResolveInfo ri = mContext.getPackageManager()
8649 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008650 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008651 CharSequence errorMsg = null;
8652 if (ri != null) {
8653 ActivityInfo ai = ri.activityInfo;
8654 ApplicationInfo app = ai.applicationInfo;
8655 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8656 mTopAction = Intent.ACTION_FACTORY_TEST;
8657 mTopData = null;
8658 mTopComponent = new ComponentName(app.packageName,
8659 ai.name);
8660 } else {
8661 errorMsg = mContext.getResources().getText(
8662 com.android.internal.R.string.factorytest_not_system);
8663 }
8664 } else {
8665 errorMsg = mContext.getResources().getText(
8666 com.android.internal.R.string.factorytest_no_action);
8667 }
8668 if (errorMsg != null) {
8669 mTopAction = null;
8670 mTopData = null;
8671 mTopComponent = null;
8672 Message msg = Message.obtain();
8673 msg.what = SHOW_FACTORY_ERROR_MSG;
8674 msg.getData().putCharSequence("msg", errorMsg);
8675 mHandler.sendMessage(msg);
8676 }
8677 }
8678 }
8679
8680 retrieveSettings();
8681
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008682 if (goingCallback != null) goingCallback.run();
8683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008684 synchronized (this) {
8685 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8686 try {
8687 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008688 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 if (apps != null) {
8690 int N = apps.size();
8691 int i;
8692 for (i=0; i<N; i++) {
8693 ApplicationInfo info
8694 = (ApplicationInfo)apps.get(i);
8695 if (info != null &&
8696 !info.packageName.equals("android")) {
8697 addAppLocked(info);
8698 }
8699 }
8700 }
8701 } catch (RemoteException ex) {
8702 // pm is in same process, this will never happen.
8703 }
8704 }
8705
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008706 // Start up initial activity.
8707 mBooting = true;
8708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008709 try {
8710 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8711 Message msg = Message.obtain();
8712 msg.what = SHOW_UID_ERROR_MSG;
8713 mHandler.sendMessage(msg);
8714 }
8715 } catch (RemoteException e) {
8716 }
8717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 resumeTopActivityLocked(null);
8719 }
8720 }
8721
Dan Egnorb7f03672009-12-09 16:22:32 -08008722 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008723 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008724 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008725 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008726 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008727 startAppProblemLocked(app);
8728 app.stopFreezingAllLocked();
8729 return handleAppCrashLocked(app);
8730 }
8731
Dan Egnorb7f03672009-12-09 16:22:32 -08008732 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008733 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008734 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008735 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008736 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8737 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 startAppProblemLocked(app);
8739 app.stopFreezingAllLocked();
8740 }
8741
8742 /**
8743 * Generate a process error record, suitable for attachment to a ProcessRecord.
8744 *
8745 * @param app The ProcessRecord in which the error occurred.
8746 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8747 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008748 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749 * @param shortMsg Short message describing the crash.
8750 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008751 * @param stackTrace Full crash stack trace, may be null.
8752 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008753 * @return Returns a fully-formed AppErrorStateInfo record.
8754 */
8755 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008756 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 report.condition = condition;
8760 report.processName = app.processName;
8761 report.pid = app.pid;
8762 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008763 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008764 report.shortMsg = shortMsg;
8765 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008766 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008767
8768 return report;
8769 }
8770
Dan Egnor42471dd2010-01-07 17:25:22 -08008771 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008772 synchronized (this) {
8773 app.crashing = false;
8774 app.crashingReport = null;
8775 app.notResponding = false;
8776 app.notRespondingReport = null;
8777 if (app.anrDialog == fromDialog) {
8778 app.anrDialog = null;
8779 }
8780 if (app.waitDialog == fromDialog) {
8781 app.waitDialog = null;
8782 }
8783 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008784 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008785 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008786 + app.processName
8787 + " (pid=" + app.pid + ") at user's request");
8788 Process.killProcess(app.pid);
8789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008790 }
8791 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008792
Dan Egnorb7f03672009-12-09 16:22:32 -08008793 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 long now = SystemClock.uptimeMillis();
8795
8796 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8797 app.info.uid);
8798 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8799 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008800 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008802 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008803 app.info.processName, app.info.uid);
8804 killServicesLocked(app, false);
8805 for (int i=mHistory.size()-1; i>=0; i--) {
8806 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8807 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008808 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008809 + r.intent.getComponent().flattenToShortString());
8810 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8811 }
8812 }
8813 if (!app.persistent) {
8814 // We don't want to start this process again until the user
8815 // explicitly does so... but for persistent process, we really
8816 // need to keep it running. If a persistent process is actually
8817 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008818 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 app.info.processName);
8820 mBadProcesses.put(app.info.processName, app.info.uid, now);
8821 app.bad = true;
8822 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8823 app.removed = true;
8824 removeProcessLocked(app, false);
8825 return false;
8826 }
8827 }
8828
8829 // Bump up the crash count of any services currently running in the proc.
8830 if (app.services.size() != 0) {
8831 // Any services running in the application need to be placed
8832 // back in the pending list.
8833 Iterator it = app.services.iterator();
8834 while (it.hasNext()) {
8835 ServiceRecord sr = (ServiceRecord)it.next();
8836 sr.crashCount++;
8837 }
8838 }
8839
8840 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8841 return true;
8842 }
8843
8844 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008845 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8846 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008847 skipCurrentReceiverLocked(app);
8848 }
8849
8850 void skipCurrentReceiverLocked(ProcessRecord app) {
8851 boolean reschedule = false;
8852 BroadcastRecord r = app.curReceiver;
8853 if (r != null) {
8854 // The current broadcast is waiting for this app's receiver
8855 // to be finished. Looks like that's not going to happen, so
8856 // let the broadcast continue.
8857 logBroadcastReceiverDiscard(r);
8858 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8859 r.resultExtras, r.resultAbort, true);
8860 reschedule = true;
8861 }
8862 r = mPendingBroadcast;
8863 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008864 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008865 "skip & discard pending app " + r);
8866 logBroadcastReceiverDiscard(r);
8867 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8868 r.resultExtras, r.resultAbort, true);
8869 reschedule = true;
8870 }
8871 if (reschedule) {
8872 scheduleBroadcastsLocked();
8873 }
8874 }
8875
Dan Egnor60d87622009-12-16 16:32:58 -08008876 /**
8877 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8878 * The application process will exit immediately after this call returns.
8879 * @param app object of the crashing app, null for the system server
8880 * @param crashInfo describing the exception
8881 */
8882 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8883 ProcessRecord r = findAppProcess(app);
8884
8885 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8886 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008887 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008888 crashInfo.exceptionClassName,
8889 crashInfo.exceptionMessage,
8890 crashInfo.throwFileName,
8891 crashInfo.throwLineNumber);
8892
Dan Egnor42471dd2010-01-07 17:25:22 -08008893 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008894
8895 crashApplication(r, crashInfo);
8896 }
8897
8898 /**
8899 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8900 * @param app object of the crashing app, null for the system server
8901 * @param tag reported by the caller
8902 * @param crashInfo describing the context of the error
8903 * @return true if the process should exit immediately (WTF is fatal)
8904 */
8905 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008906 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008907 ProcessRecord r = findAppProcess(app);
8908
8909 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8910 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008911 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008912 tag, crashInfo.exceptionMessage);
8913
Dan Egnor42471dd2010-01-07 17:25:22 -08008914 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008915
Doug Zongker43866e02010-01-07 12:09:54 -08008916 if (Settings.Secure.getInt(mContext.getContentResolver(),
8917 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008918 crashApplication(r, crashInfo);
8919 return true;
8920 } else {
8921 return false;
8922 }
8923 }
8924
8925 /**
8926 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8927 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8928 */
8929 private ProcessRecord findAppProcess(IBinder app) {
8930 if (app == null) {
8931 return null;
8932 }
8933
8934 synchronized (this) {
8935 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8936 final int NA = apps.size();
8937 for (int ia=0; ia<NA; ia++) {
8938 ProcessRecord p = apps.valueAt(ia);
8939 if (p.thread != null && p.thread.asBinder() == app) {
8940 return p;
8941 }
8942 }
8943 }
8944
Joe Onorato8a9b2202010-02-26 18:56:32 -08008945 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008946 return null;
8947 }
8948 }
8949
8950 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008951 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008952 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008953 * @param process which caused the error, null means the system server
8954 * @param activity which triggered the error, null if unknown
8955 * @param parent activity related to the error, null if unknown
8956 * @param subject line related to the error, null if absent
8957 * @param report in long form describing the error, null if absent
8958 * @param logFile to include in the report, null if none
8959 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008960 */
Dan Egnor42471dd2010-01-07 17:25:22 -08008961 private void addErrorToDropBox(String eventType,
8962 ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
8963 String subject, String report, File logFile,
Dan Egnor60d87622009-12-16 16:32:58 -08008964 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008965 String dropboxTag;
8966 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008967 dropboxTag = "system_server_" + eventType;
Dan Egnor42471dd2010-01-07 17:25:22 -08008968 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008969 dropboxTag = "system_app_" + eventType;
8970 } else {
8971 dropboxTag = "data_app_" + eventType;
8972 }
8973
8974 DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
8975 if (dbox != null && dbox.isTagEnabled(dropboxTag)) {
8976 StringBuilder sb = new StringBuilder(1024);
Dan Egnor42471dd2010-01-07 17:25:22 -08008977 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008978 sb.append("Process: system_server\n");
8979 } else {
Dan Egnor42471dd2010-01-07 17:25:22 -08008980 sb.append("Process: ").append(process.processName).append("\n");
Dan Egnor66c40e72010-01-26 16:23:11 -08008981 }
8982 if (process != null) {
8983 int flags = process.info.flags;
8984 IPackageManager pm = ActivityThread.getPackageManager();
8985 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8986 for (String pkg : process.pkgList) {
8987 sb.append("Package: ").append(pkg);
8988 try {
8989 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8990 if (pi != null) {
8991 sb.append(" v").append(pi.versionCode);
8992 if (pi.versionName != null) {
8993 sb.append(" (").append(pi.versionName).append(")");
8994 }
8995 }
8996 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008997 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor66c40e72010-01-26 16:23:11 -08008998 }
8999 sb.append("\n");
9000 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009001 }
9002 if (activity != null) {
9003 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9004 }
9005 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9006 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9007 }
9008 if (parent != null && parent != activity) {
9009 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9010 }
9011 if (subject != null) {
9012 sb.append("Subject: ").append(subject).append("\n");
9013 }
9014 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9015 sb.append("\n");
9016 if (report != null) {
9017 sb.append(report);
9018 }
9019 if (logFile != null) {
9020 try {
9021 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9022 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009023 Slog.e(TAG, "Error reading " + logFile, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009024 }
9025 }
Dan Egnor60d87622009-12-16 16:32:58 -08009026 if (crashInfo != null && crashInfo.stackTrace != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009027 sb.append(crashInfo.stackTrace);
Dan Egnor60d87622009-12-16 16:32:58 -08009028 }
9029 dbox.addText(dropboxTag, sb.toString());
9030 }
9031 }
9032
9033 /**
9034 * Bring up the "unexpected error" dialog box for a crashing app.
9035 * Deal with edge cases (intercepts from instrumented applications,
9036 * ActivityController, error intent receivers, that sort of thing).
9037 * @param r the application crashing
9038 * @param crashInfo describing the failure
9039 */
9040 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009041 long timeMillis = System.currentTimeMillis();
9042 String shortMsg = crashInfo.exceptionClassName;
9043 String longMsg = crashInfo.exceptionMessage;
9044 String stackTrace = crashInfo.stackTrace;
9045 if (shortMsg != null && longMsg != null) {
9046 longMsg = shortMsg + ": " + longMsg;
9047 } else if (shortMsg != null) {
9048 longMsg = shortMsg;
9049 }
9050
Dan Egnor60d87622009-12-16 16:32:58 -08009051 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009052 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009053 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009054 try {
9055 String name = r != null ? r.processName : null;
9056 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009057 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009058 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009059 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009060 + " at watcher's request");
9061 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009062 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009063 }
9064 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009065 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009066 }
9067 }
9068
9069 final long origId = Binder.clearCallingIdentity();
9070
9071 // If this process is running instrumentation, finish it.
9072 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009073 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009074 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009075 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9076 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 Bundle info = new Bundle();
9078 info.putString("shortMsg", shortMsg);
9079 info.putString("longMsg", longMsg);
9080 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9081 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009082 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009083 }
9084
Dan Egnor60d87622009-12-16 16:32:58 -08009085 // If we can't identify the process or it's already exceeded its crash quota,
9086 // quit right away without showing a crash dialog.
9087 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009089 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009090 }
9091
9092 Message msg = Message.obtain();
9093 msg.what = SHOW_ERROR_MSG;
9094 HashMap data = new HashMap();
9095 data.put("result", result);
9096 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009097 msg.obj = data;
9098 mHandler.sendMessage(msg);
9099
9100 Binder.restoreCallingIdentity(origId);
9101 }
9102
9103 int res = result.get();
9104
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009105 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009106 synchronized (this) {
9107 if (r != null) {
9108 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9109 SystemClock.uptimeMillis());
9110 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009111 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009112 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009113 }
9114 }
9115
9116 if (appErrorIntent != null) {
9117 try {
9118 mContext.startActivity(appErrorIntent);
9119 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009120 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009123 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009124
9125 Intent createAppErrorIntentLocked(ProcessRecord r,
9126 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9127 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009128 if (report == null) {
9129 return null;
9130 }
9131 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9132 result.setComponent(r.errorReportReceiver);
9133 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9134 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9135 return result;
9136 }
9137
Dan Egnorb7f03672009-12-09 16:22:32 -08009138 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9139 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009140 if (r.errorReportReceiver == null) {
9141 return null;
9142 }
9143
9144 if (!r.crashing && !r.notResponding) {
9145 return null;
9146 }
9147
Dan Egnorb7f03672009-12-09 16:22:32 -08009148 ApplicationErrorReport report = new ApplicationErrorReport();
9149 report.packageName = r.info.packageName;
9150 report.installerPackageName = r.errorReportReceiver.getPackageName();
9151 report.processName = r.processName;
9152 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009153 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009154
Dan Egnorb7f03672009-12-09 16:22:32 -08009155 if (r.crashing) {
9156 report.type = ApplicationErrorReport.TYPE_CRASH;
9157 report.crashInfo = crashInfo;
9158 } else if (r.notResponding) {
9159 report.type = ApplicationErrorReport.TYPE_ANR;
9160 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009161
Dan Egnorb7f03672009-12-09 16:22:32 -08009162 report.anrInfo.activity = r.notRespondingReport.tag;
9163 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9164 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009165 }
9166
Dan Egnorb7f03672009-12-09 16:22:32 -08009167 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009168 }
9169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9171 // assume our apps are happy - lazy create the list
9172 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9173
9174 synchronized (this) {
9175
9176 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009177 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9178 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9180 // This one's in trouble, so we'll generate a report for it
9181 // crashes are higher priority (in case there's a crash *and* an anr)
9182 ActivityManager.ProcessErrorStateInfo report = null;
9183 if (app.crashing) {
9184 report = app.crashingReport;
9185 } else if (app.notResponding) {
9186 report = app.notRespondingReport;
9187 }
9188
9189 if (report != null) {
9190 if (errList == null) {
9191 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9192 }
9193 errList.add(report);
9194 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009195 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009196 " crashing = " + app.crashing +
9197 " notResponding = " + app.notResponding);
9198 }
9199 }
9200 }
9201 }
9202
9203 return errList;
9204 }
9205
9206 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9207 // Lazy instantiation of list
9208 List<ActivityManager.RunningAppProcessInfo> runList = null;
9209 synchronized (this) {
9210 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009211 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9212 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009213 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9214 // Generate process state info for running application
9215 ActivityManager.RunningAppProcessInfo currApp =
9216 new ActivityManager.RunningAppProcessInfo(app.processName,
9217 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009218 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009219 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009220 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9222 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9223 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009224 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9225 } else if (adj >= HOME_APP_ADJ) {
9226 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9227 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009228 } else if (adj >= SECONDARY_SERVER_ADJ) {
9229 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9230 } else if (adj >= VISIBLE_APP_ADJ) {
9231 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9232 } else {
9233 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9234 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009235 currApp.importanceReasonCode = app.adjTypeCode;
9236 if (app.adjSource instanceof ProcessRecord) {
9237 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9238 } else if (app.adjSource instanceof HistoryRecord) {
9239 HistoryRecord r = (HistoryRecord)app.adjSource;
9240 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9241 }
9242 if (app.adjTarget instanceof ComponentName) {
9243 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9244 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009245 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009246 // + " lru=" + currApp.lru);
9247 if (runList == null) {
9248 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9249 }
9250 runList.add(currApp);
9251 }
9252 }
9253 }
9254 return runList;
9255 }
9256
9257 @Override
9258 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009259 if (checkCallingPermission(android.Manifest.permission.DUMP)
9260 != PackageManager.PERMISSION_GRANTED) {
9261 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9262 + Binder.getCallingPid()
9263 + ", uid=" + Binder.getCallingUid()
9264 + " without permission "
9265 + android.Manifest.permission.DUMP);
9266 return;
9267 }
9268
9269 boolean dumpAll = false;
9270
9271 int opti = 0;
9272 while (opti < args.length) {
9273 String opt = args[opti];
9274 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9275 break;
9276 }
9277 opti++;
9278 if ("-a".equals(opt)) {
9279 dumpAll = true;
9280 } else if ("-h".equals(opt)) {
9281 pw.println("Activity manager dump options:");
9282 pw.println(" [-a] [h- [cmd] ...");
9283 pw.println(" cmd may be one of:");
9284 pw.println(" activities: activity stack state");
9285 pw.println(" broadcasts: broadcast state");
9286 pw.println(" intents: pending intent state");
9287 pw.println(" processes: process state");
9288 pw.println(" providers: content provider state");
9289 pw.println(" services: service state");
9290 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009292 } else {
9293 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009294 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009295 }
9296
9297 // Is the caller requesting to dump a particular piece of data?
9298 if (opti < args.length) {
9299 String cmd = args[opti];
9300 opti++;
9301 if ("activities".equals(cmd) || "a".equals(cmd)) {
9302 synchronized (this) {
9303 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009304 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009305 return;
9306 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9307 synchronized (this) {
9308 dumpBroadcastsLocked(fd, pw, args, opti, true);
9309 }
9310 return;
9311 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9312 synchronized (this) {
9313 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9314 }
9315 return;
9316 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9317 synchronized (this) {
9318 dumpProcessesLocked(fd, pw, args, opti, true);
9319 }
9320 return;
9321 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9322 synchronized (this) {
9323 dumpProvidersLocked(fd, pw, args, opti, true);
9324 }
9325 return;
9326 } else if ("service".equals(cmd)) {
9327 dumpService(fd, pw, args, opti, true);
9328 return;
9329 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9330 synchronized (this) {
9331 dumpServicesLocked(fd, pw, args, opti, true);
9332 }
9333 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009334 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009335 }
9336
9337 // No piece of data specified, dump everything.
9338 synchronized (this) {
9339 boolean needSep;
9340 if (dumpAll) {
9341 pw.println("Providers in Current Activity Manager State:");
9342 }
9343 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9344 if (needSep) {
9345 pw.println(" ");
9346 }
9347 if (dumpAll) {
9348 pw.println("-------------------------------------------------------------------------------");
9349 pw.println("Broadcasts in Current Activity Manager State:");
9350 }
9351 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9352 if (needSep) {
9353 pw.println(" ");
9354 }
9355 if (dumpAll) {
9356 pw.println("-------------------------------------------------------------------------------");
9357 pw.println("Services in Current Activity Manager State:");
9358 }
9359 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9360 if (needSep) {
9361 pw.println(" ");
9362 }
9363 if (dumpAll) {
9364 pw.println("-------------------------------------------------------------------------------");
9365 pw.println("PendingIntents in Current Activity Manager State:");
9366 }
9367 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9368 if (needSep) {
9369 pw.println(" ");
9370 }
9371 if (dumpAll) {
9372 pw.println("-------------------------------------------------------------------------------");
9373 pw.println("Activities in Current Activity Manager State:");
9374 }
9375 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9376 if (needSep) {
9377 pw.println(" ");
9378 }
9379 if (dumpAll) {
9380 pw.println("-------------------------------------------------------------------------------");
9381 pw.println("Processes in Current Activity Manager State:");
9382 }
9383 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9384 }
9385 }
9386
9387 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9388 int opti, boolean dumpAll, boolean needHeader) {
9389 if (needHeader) {
9390 pw.println(" Activity stack:");
9391 }
9392 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9393 pw.println(" ");
9394 pw.println(" Running activities (most recent first):");
9395 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9396 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009397 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009398 pw.println(" Activities waiting for another to become visible:");
9399 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9400 }
9401 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009402 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009403 pw.println(" Activities waiting to stop:");
9404 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9405 }
9406 if (mFinishingActivities.size() > 0) {
9407 pw.println(" ");
9408 pw.println(" Activities waiting to finish:");
9409 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009411
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009412 pw.println(" ");
9413 pw.println(" mPausingActivity: " + mPausingActivity);
9414 pw.println(" mResumedActivity: " + mResumedActivity);
9415 pw.println(" mFocusedActivity: " + mFocusedActivity);
9416 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009417
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009418 if (dumpAll && mRecentTasks.size() > 0) {
9419 pw.println(" ");
9420 pw.println("Recent tasks in Current Activity Manager State:");
9421
9422 final int N = mRecentTasks.size();
9423 for (int i=0; i<N; i++) {
9424 TaskRecord tr = mRecentTasks.get(i);
9425 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9426 pw.println(tr);
9427 mRecentTasks.get(i).dump(pw, " ");
9428 }
9429 }
9430
9431 pw.println(" ");
9432 pw.println(" mCurTask: " + mCurTask);
9433
9434 return true;
9435 }
9436
9437 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9438 int opti, boolean dumpAll) {
9439 boolean needSep = false;
9440 int numPers = 0;
9441
9442 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009443 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9444 final int NA = procs.size();
9445 for (int ia=0; ia<NA; ia++) {
9446 if (!needSep) {
9447 pw.println(" All known processes:");
9448 needSep = true;
9449 }
9450 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009451 pw.print(r.persistent ? " *PERS*" : " *APP*");
9452 pw.print(" UID "); pw.print(procs.keyAt(ia));
9453 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454 r.dump(pw, " ");
9455 if (r.persistent) {
9456 numPers++;
9457 }
9458 }
9459 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009460 }
9461
9462 if (mLruProcesses.size() > 0) {
9463 if (needSep) pw.println(" ");
9464 needSep = true;
9465 pw.println(" Running processes (most recent first):");
9466 dumpProcessList(pw, this, mLruProcesses, " ",
9467 "App ", "PERS", true);
9468 needSep = true;
9469 }
9470
9471 synchronized (mPidsSelfLocked) {
9472 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009473 if (needSep) pw.println(" ");
9474 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009475 pw.println(" PID mappings:");
9476 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9477 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9478 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 }
9480 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009481 }
9482
9483 if (mForegroundProcesses.size() > 0) {
9484 if (needSep) pw.println(" ");
9485 needSep = true;
9486 pw.println(" Foreground Processes:");
9487 for (int i=0; i<mForegroundProcesses.size(); i++) {
9488 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9489 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009490 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009491 }
9492
9493 if (mPersistentStartingProcesses.size() > 0) {
9494 if (needSep) pw.println(" ");
9495 needSep = true;
9496 pw.println(" Persisent processes that are starting:");
9497 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9498 "Starting Norm", "Restarting PERS", false);
9499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009500
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009501 if (mStartingProcesses.size() > 0) {
9502 if (needSep) pw.println(" ");
9503 needSep = true;
9504 pw.println(" Processes that are starting:");
9505 dumpProcessList(pw, this, mStartingProcesses, " ",
9506 "Starting Norm", "Starting PERS", false);
9507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009508
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009509 if (mRemovedProcesses.size() > 0) {
9510 if (needSep) pw.println(" ");
9511 needSep = true;
9512 pw.println(" Processes that are being removed:");
9513 dumpProcessList(pw, this, mRemovedProcesses, " ",
9514 "Removed Norm", "Removed PERS", false);
9515 }
9516
9517 if (mProcessesOnHold.size() > 0) {
9518 if (needSep) pw.println(" ");
9519 needSep = true;
9520 pw.println(" Processes that are on old until the system is ready:");
9521 dumpProcessList(pw, this, mProcessesOnHold, " ",
9522 "OnHold Norm", "OnHold PERS", false);
9523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009524
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009525 if (mProcessesToGc.size() > 0) {
9526 if (needSep) pw.println(" ");
9527 needSep = true;
9528 pw.println(" Processes that are waiting to GC:");
9529 long now = SystemClock.uptimeMillis();
9530 for (int i=0; i<mProcessesToGc.size(); i++) {
9531 ProcessRecord proc = mProcessesToGc.get(i);
9532 pw.print(" Process "); pw.println(proc);
9533 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9534 pw.print(", last gced=");
9535 pw.print(now-proc.lastRequestedGc);
9536 pw.print(" ms ago, last lowMem=");
9537 pw.print(now-proc.lastLowMemory);
9538 pw.println(" ms ago");
9539
9540 }
9541 }
9542
9543 if (mProcessCrashTimes.getMap().size() > 0) {
9544 if (needSep) pw.println(" ");
9545 needSep = true;
9546 pw.println(" Time since processes crashed:");
9547 long now = SystemClock.uptimeMillis();
9548 for (Map.Entry<String, SparseArray<Long>> procs
9549 : mProcessCrashTimes.getMap().entrySet()) {
9550 SparseArray<Long> uids = procs.getValue();
9551 final int N = uids.size();
9552 for (int i=0; i<N; i++) {
9553 pw.print(" Process "); pw.print(procs.getKey());
9554 pw.print(" uid "); pw.print(uids.keyAt(i));
9555 pw.print(": last crashed ");
9556 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009557 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009558 }
9559 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009561
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009562 if (mBadProcesses.getMap().size() > 0) {
9563 if (needSep) pw.println(" ");
9564 needSep = true;
9565 pw.println(" Bad processes:");
9566 for (Map.Entry<String, SparseArray<Long>> procs
9567 : mBadProcesses.getMap().entrySet()) {
9568 SparseArray<Long> uids = procs.getValue();
9569 final int N = uids.size();
9570 for (int i=0; i<N; i++) {
9571 pw.print(" Bad process "); pw.print(procs.getKey());
9572 pw.print(" uid "); pw.print(uids.keyAt(i));
9573 pw.print(": crashed at time ");
9574 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009575 }
9576 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009579 pw.println(" ");
9580 pw.println(" mHomeProcess: " + mHomeProcess);
9581 pw.println(" mConfiguration: " + mConfiguration);
9582 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9583 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9584 || mOrigWaitForDebugger) {
9585 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9586 + " mDebugTransient=" + mDebugTransient
9587 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9588 }
9589 if (mAlwaysFinishActivities || mController != null) {
9590 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9591 + " mController=" + mController);
9592 }
9593 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009594 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009595 pw.println(" mStartRunning=" + mStartRunning
9596 + " mSystemReady=" + mSystemReady
9597 + " mBooting=" + mBooting
9598 + " mBooted=" + mBooted
9599 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009600 pw.println(" mGoingToSleep=" + mGoingToSleep);
9601 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009602 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009603
9604 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009605 }
9606
9607 /**
9608 * There are three ways to call this:
9609 * - no service specified: dump all the services
9610 * - a flattened component name that matched an existing service was specified as the
9611 * first arg: dump that one service
9612 * - the first arg isn't the flattened component name of an existing service:
9613 * dump all services whose component contains the first arg as a substring
9614 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009615 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9616 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009617 String[] newArgs;
9618 String componentNameString;
9619 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009620 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621 componentNameString = null;
9622 newArgs = EMPTY_STRING_ARRAY;
9623 r = null;
9624 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009625 componentNameString = args[opti];
9626 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009627 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9628 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009629 newArgs = new String[args.length - opti];
9630 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009631 }
9632
9633 if (r != null) {
9634 dumpService(fd, pw, r, newArgs);
9635 } else {
9636 for (ServiceRecord r1 : mServices.values()) {
9637 if (componentNameString == null
9638 || r1.name.flattenToString().contains(componentNameString)) {
9639 dumpService(fd, pw, r1, newArgs);
9640 }
9641 }
9642 }
9643 }
9644
9645 /**
9646 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9647 * there is a thread associated with the service.
9648 */
9649 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9650 pw.println(" Service " + r.name.flattenToString());
9651 if (r.app != null && r.app.thread != null) {
9652 try {
9653 // flush anything that is already in the PrintWriter since the thread is going
9654 // to write to the file descriptor directly
9655 pw.flush();
9656 r.app.thread.dumpService(fd, r, args);
9657 pw.print("\n");
9658 } catch (RemoteException e) {
9659 pw.println("got a RemoteException while dumping the service");
9660 }
9661 }
9662 }
9663
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009664 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9665 int opti, boolean dumpAll) {
9666 boolean needSep = false;
9667
9668 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009669 if (mRegisteredReceivers.size() > 0) {
9670 pw.println(" ");
9671 pw.println(" Registered Receivers:");
9672 Iterator it = mRegisteredReceivers.values().iterator();
9673 while (it.hasNext()) {
9674 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009675 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676 r.dump(pw, " ");
9677 }
9678 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009680 pw.println(" ");
9681 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009682 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009683 needSep = true;
9684 }
9685
9686 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9687 || mPendingBroadcast != null) {
9688 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009690 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009691 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009692 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9693 pw.println(" Broadcast #" + i + ":");
9694 mParallelBroadcasts.get(i).dump(pw, " ");
9695 }
9696 if (mOrderedBroadcasts.size() > 0) {
9697 pw.println(" ");
9698 pw.println(" Active serialized broadcasts:");
9699 }
9700 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9701 pw.println(" Serialized Broadcast #" + i + ":");
9702 mOrderedBroadcasts.get(i).dump(pw, " ");
9703 }
9704 pw.println(" ");
9705 pw.println(" Pending broadcast:");
9706 if (mPendingBroadcast != null) {
9707 mPendingBroadcast.dump(pw, " ");
9708 } else {
9709 pw.println(" (null)");
9710 }
9711 needSep = true;
9712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009713
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009714 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009715 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009716 pw.println(" Historical broadcasts:");
9717 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9718 BroadcastRecord r = mBroadcastHistory[i];
9719 if (r == null) {
9720 break;
9721 }
9722 pw.println(" Historical Broadcast #" + i + ":");
9723 r.dump(pw, " ");
9724 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009725 needSep = true;
9726 }
9727
9728 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009729 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009730 pw.println(" Sticky broadcasts:");
9731 StringBuilder sb = new StringBuilder(128);
9732 for (Map.Entry<String, ArrayList<Intent>> ent
9733 : mStickyBroadcasts.entrySet()) {
9734 pw.print(" * Sticky action "); pw.print(ent.getKey());
9735 pw.println(":");
9736 ArrayList<Intent> intents = ent.getValue();
9737 final int N = intents.size();
9738 for (int i=0; i<N; i++) {
9739 sb.setLength(0);
9740 sb.append(" Intent: ");
9741 intents.get(i).toShortString(sb, true, false);
9742 pw.println(sb.toString());
9743 Bundle bundle = intents.get(i).getExtras();
9744 if (bundle != null) {
9745 pw.print(" ");
9746 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009747 }
9748 }
9749 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009750 needSep = true;
9751 }
9752
9753 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009754 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009755 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009756 pw.println(" mHandler:");
9757 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009758 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009760
9761 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 }
9763
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009764 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9765 int opti, boolean dumpAll) {
9766 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009767
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009768 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009769 if (mServices.size() > 0) {
9770 pw.println(" Active services:");
9771 Iterator<ServiceRecord> it = mServices.values().iterator();
9772 while (it.hasNext()) {
9773 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009774 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775 r.dump(pw, " ");
9776 }
9777 needSep = true;
9778 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009781 if (mPendingServices.size() > 0) {
9782 if (needSep) pw.println(" ");
9783 pw.println(" Pending services:");
9784 for (int i=0; i<mPendingServices.size(); i++) {
9785 ServiceRecord r = mPendingServices.get(i);
9786 pw.print(" * Pending "); pw.println(r);
9787 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009789 needSep = true;
9790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009792 if (mRestartingServices.size() > 0) {
9793 if (needSep) pw.println(" ");
9794 pw.println(" Restarting services:");
9795 for (int i=0; i<mRestartingServices.size(); i++) {
9796 ServiceRecord r = mRestartingServices.get(i);
9797 pw.print(" * Restarting "); pw.println(r);
9798 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009799 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009800 needSep = true;
9801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009802
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009803 if (mStoppingServices.size() > 0) {
9804 if (needSep) pw.println(" ");
9805 pw.println(" Stopping services:");
9806 for (int i=0; i<mStoppingServices.size(); i++) {
9807 ServiceRecord r = mStoppingServices.get(i);
9808 pw.print(" * Stopping "); pw.println(r);
9809 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009810 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009811 needSep = true;
9812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009814 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009815 if (mServiceConnections.size() > 0) {
9816 if (needSep) pw.println(" ");
9817 pw.println(" Connection bindings to services:");
9818 Iterator<ConnectionRecord> it
9819 = mServiceConnections.values().iterator();
9820 while (it.hasNext()) {
9821 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009822 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009823 r.dump(pw, " ");
9824 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009825 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009826 }
9827 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009828
9829 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 }
9831
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009832 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9833 int opti, boolean dumpAll) {
9834 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009836 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009837 if (mProvidersByClass.size() > 0) {
9838 if (needSep) pw.println(" ");
9839 pw.println(" Published content providers (by class):");
9840 Iterator it = mProvidersByClass.entrySet().iterator();
9841 while (it.hasNext()) {
9842 Map.Entry e = (Map.Entry)it.next();
9843 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009844 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009845 r.dump(pw, " ");
9846 }
9847 needSep = true;
9848 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009849
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009850 if (mProvidersByName.size() > 0) {
9851 pw.println(" ");
9852 pw.println(" Authority to provider mappings:");
9853 Iterator it = mProvidersByName.entrySet().iterator();
9854 while (it.hasNext()) {
9855 Map.Entry e = (Map.Entry)it.next();
9856 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9857 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9858 pw.println(r);
9859 }
9860 needSep = true;
9861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009862 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009863
9864 if (mLaunchingProviders.size() > 0) {
9865 if (needSep) pw.println(" ");
9866 pw.println(" Launching content providers:");
9867 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9868 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9869 pw.println(mLaunchingProviders.get(i));
9870 }
9871 needSep = true;
9872 }
9873
9874 if (mGrantedUriPermissions.size() > 0) {
9875 pw.println();
9876 pw.println("Granted Uri Permissions:");
9877 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9878 int uid = mGrantedUriPermissions.keyAt(i);
9879 HashMap<Uri, UriPermission> perms
9880 = mGrantedUriPermissions.valueAt(i);
9881 pw.print(" * UID "); pw.print(uid);
9882 pw.println(" holds:");
9883 for (UriPermission perm : perms.values()) {
9884 pw.print(" "); pw.println(perm);
9885 perm.dump(pw, " ");
9886 }
9887 }
9888 needSep = true;
9889 }
9890
9891 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 }
9893
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009894 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9895 int opti, boolean dumpAll) {
9896 boolean needSep = false;
9897
9898 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009899 if (this.mIntentSenderRecords.size() > 0) {
9900 Iterator<WeakReference<PendingIntentRecord>> it
9901 = mIntentSenderRecords.values().iterator();
9902 while (it.hasNext()) {
9903 WeakReference<PendingIntentRecord> ref = it.next();
9904 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009905 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009906 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009907 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009908 rec.dump(pw, " ");
9909 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009910 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009911 }
9912 }
9913 }
9914 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009915
9916 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009917 }
9918
9919 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009920 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009921 TaskRecord lastTask = null;
9922 for (int i=list.size()-1; i>=0; i--) {
9923 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009924 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009925 if (lastTask != r.task) {
9926 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009927 pw.print(prefix);
9928 pw.print(full ? "* " : " ");
9929 pw.println(lastTask);
9930 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009931 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009933 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009934 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9935 pw.print(" #"); pw.print(i); pw.print(": ");
9936 pw.println(r);
9937 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009938 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009940 }
9941 }
9942
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009943 private static String buildOomTag(String prefix, String space, int val, int base) {
9944 if (val == base) {
9945 if (space == null) return prefix;
9946 return prefix + " ";
9947 }
9948 return prefix + "+" + Integer.toString(val-base);
9949 }
9950
9951 private static final int dumpProcessList(PrintWriter pw,
9952 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009953 String prefix, String normalLabel, String persistentLabel,
9954 boolean inclOomAdj) {
9955 int numPers = 0;
9956 for (int i=list.size()-1; i>=0; i--) {
9957 ProcessRecord r = (ProcessRecord)list.get(i);
9958 if (false) {
9959 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
9960 + " #" + i + ":");
9961 r.dump(pw, prefix + " ");
9962 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009963 String oomAdj;
9964 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009965 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009966 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009967 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
9968 } else if (r.setAdj >= HOME_APP_ADJ) {
9969 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
9970 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
9971 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
9972 } else if (r.setAdj >= BACKUP_APP_ADJ) {
9973 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
9974 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
9975 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
9976 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
9977 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009978 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009979 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009980 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009981 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009982 } else {
9983 oomAdj = Integer.toString(r.setAdj);
9984 }
9985 String schedGroup;
9986 switch (r.setSchedGroup) {
9987 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9988 schedGroup = "B";
9989 break;
9990 case Process.THREAD_GROUP_DEFAULT:
9991 schedGroup = "F";
9992 break;
9993 default:
9994 schedGroup = Integer.toString(r.setSchedGroup);
9995 break;
9996 }
9997 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009998 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009999 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010000 if (r.adjSource != null || r.adjTarget != null) {
10001 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010002 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010004 } else {
10005 pw.println(String.format("%s%s #%2d: %s",
10006 prefix, (r.persistent ? persistentLabel : normalLabel),
10007 i, r.toString()));
10008 }
10009 if (r.persistent) {
10010 numPers++;
10011 }
10012 }
10013 return numPers;
10014 }
10015
10016 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
10017 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010018 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010019 long uptime = SystemClock.uptimeMillis();
10020 long realtime = SystemClock.elapsedRealtime();
10021
10022 if (isCheckinRequest) {
10023 // short checkin version
10024 pw.println(uptime + "," + realtime);
10025 pw.flush();
10026 } else {
10027 pw.println("Applications Memory Usage (kB):");
10028 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10029 }
10030 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10031 ProcessRecord r = (ProcessRecord)list.get(i);
10032 if (r.thread != null) {
10033 if (!isCheckinRequest) {
10034 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10035 pw.flush();
10036 }
10037 try {
10038 r.thread.asBinder().dump(fd, args);
10039 } catch (RemoteException e) {
10040 if (!isCheckinRequest) {
10041 pw.println("Got RemoteException!");
10042 pw.flush();
10043 }
10044 }
10045 }
10046 }
10047 }
10048
10049 /**
10050 * Searches array of arguments for the specified string
10051 * @param args array of argument strings
10052 * @param value value to search for
10053 * @return true if the value is contained in the array
10054 */
10055 private static boolean scanArgs(String[] args, String value) {
10056 if (args != null) {
10057 for (String arg : args) {
10058 if (value.equals(arg)) {
10059 return true;
10060 }
10061 }
10062 }
10063 return false;
10064 }
10065
Dianne Hackborn75b03852009-06-12 15:43:26 -070010066 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010067 int count = mHistory.size();
10068
10069 // convert the token to an entry in the history.
10070 HistoryRecord r = null;
10071 int index = -1;
10072 for (int i=count-1; i>=0; i--) {
10073 Object o = mHistory.get(i);
10074 if (o == token) {
10075 r = (HistoryRecord)o;
10076 index = i;
10077 break;
10078 }
10079 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010080
10081 return index;
10082 }
10083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010084 private final void killServicesLocked(ProcessRecord app,
10085 boolean allowRestart) {
10086 // Report disconnected services.
10087 if (false) {
10088 // XXX we are letting the client link to the service for
10089 // death notifications.
10090 if (app.services.size() > 0) {
10091 Iterator it = app.services.iterator();
10092 while (it.hasNext()) {
10093 ServiceRecord r = (ServiceRecord)it.next();
10094 if (r.connections.size() > 0) {
10095 Iterator<ConnectionRecord> jt
10096 = r.connections.values().iterator();
10097 while (jt.hasNext()) {
10098 ConnectionRecord c = jt.next();
10099 if (c.binding.client != app) {
10100 try {
10101 //c.conn.connected(r.className, null);
10102 } catch (Exception e) {
10103 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010104 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010105 + r.shortName
10106 + " from app " + app.processName, e);
10107 }
10108 }
10109 }
10110 }
10111 }
10112 }
10113 }
10114
10115 // Clean up any connections this application has to other services.
10116 if (app.connections.size() > 0) {
10117 Iterator<ConnectionRecord> it = app.connections.iterator();
10118 while (it.hasNext()) {
10119 ConnectionRecord r = it.next();
10120 removeConnectionLocked(r, app, null);
10121 }
10122 }
10123 app.connections.clear();
10124
10125 if (app.services.size() != 0) {
10126 // Any services running in the application need to be placed
10127 // back in the pending list.
10128 Iterator it = app.services.iterator();
10129 while (it.hasNext()) {
10130 ServiceRecord sr = (ServiceRecord)it.next();
10131 synchronized (sr.stats.getBatteryStats()) {
10132 sr.stats.stopLaunchedLocked();
10133 }
10134 sr.app = null;
10135 sr.executeNesting = 0;
10136 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010137
10138 boolean hasClients = sr.bindings.size() > 0;
10139 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 Iterator<IntentBindRecord> bindings
10141 = sr.bindings.values().iterator();
10142 while (bindings.hasNext()) {
10143 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010144 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010145 + ": shouldUnbind=" + b.hasBound);
10146 b.binder = null;
10147 b.requested = b.received = b.hasBound = false;
10148 }
10149 }
10150
10151 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010152 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010153 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010154 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155 sr.crashCount, sr.shortName, app.pid);
10156 bringDownServiceLocked(sr, true);
10157 } else if (!allowRestart) {
10158 bringDownServiceLocked(sr, true);
10159 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010160 boolean canceled = scheduleServiceRestartLocked(sr, true);
10161
10162 // Should the service remain running? Note that in the
10163 // extreme case of so many attempts to deliver a command
10164 // that it failed, that we also will stop it here.
10165 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10166 if (sr.pendingStarts.size() == 0) {
10167 sr.startRequested = false;
10168 if (!hasClients) {
10169 // Whoops, no reason to restart!
10170 bringDownServiceLocked(sr, true);
10171 }
10172 }
10173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010174 }
10175 }
10176
10177 if (!allowRestart) {
10178 app.services.clear();
10179 }
10180 }
10181
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010182 // Make sure we have no more records on the stopping list.
10183 int i = mStoppingServices.size();
10184 while (i > 0) {
10185 i--;
10186 ServiceRecord sr = mStoppingServices.get(i);
10187 if (sr.app == app) {
10188 mStoppingServices.remove(i);
10189 }
10190 }
10191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010192 app.executingServices.clear();
10193 }
10194
10195 private final void removeDyingProviderLocked(ProcessRecord proc,
10196 ContentProviderRecord cpr) {
10197 synchronized (cpr) {
10198 cpr.launchingApp = null;
10199 cpr.notifyAll();
10200 }
10201
10202 mProvidersByClass.remove(cpr.info.name);
10203 String names[] = cpr.info.authority.split(";");
10204 for (int j = 0; j < names.length; j++) {
10205 mProvidersByName.remove(names[j]);
10206 }
10207
10208 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10209 while (cit.hasNext()) {
10210 ProcessRecord capp = cit.next();
10211 if (!capp.persistent && capp.thread != null
10212 && capp.pid != 0
10213 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010214 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010215 + " (pid " + capp.pid
10216 + ") because provider " + cpr.info.name
10217 + " is in dying process " + proc.processName);
10218 Process.killProcess(capp.pid);
10219 }
10220 }
10221
10222 mLaunchingProviders.remove(cpr);
10223 }
10224
10225 /**
10226 * Main code for cleaning up a process when it has gone away. This is
10227 * called both as a result of the process dying, or directly when stopping
10228 * a process when running in single process mode.
10229 */
10230 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10231 boolean restarting, int index) {
10232 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010233 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 }
10235
Dianne Hackborn36124872009-10-08 16:22:03 -070010236 mProcessesToGc.remove(app);
10237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 // Dismiss any open dialogs.
10239 if (app.crashDialog != null) {
10240 app.crashDialog.dismiss();
10241 app.crashDialog = null;
10242 }
10243 if (app.anrDialog != null) {
10244 app.anrDialog.dismiss();
10245 app.anrDialog = null;
10246 }
10247 if (app.waitDialog != null) {
10248 app.waitDialog.dismiss();
10249 app.waitDialog = null;
10250 }
10251
10252 app.crashing = false;
10253 app.notResponding = false;
10254
10255 app.resetPackageList();
10256 app.thread = null;
10257 app.forcingToForeground = null;
10258 app.foregroundServices = false;
10259
10260 killServicesLocked(app, true);
10261
10262 boolean restart = false;
10263
10264 int NL = mLaunchingProviders.size();
10265
10266 // Remove published content providers.
10267 if (!app.pubProviders.isEmpty()) {
10268 Iterator it = app.pubProviders.values().iterator();
10269 while (it.hasNext()) {
10270 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10271 cpr.provider = null;
10272 cpr.app = null;
10273
10274 // See if someone is waiting for this provider... in which
10275 // case we don't remove it, but just let it restart.
10276 int i = 0;
10277 if (!app.bad) {
10278 for (; i<NL; i++) {
10279 if (mLaunchingProviders.get(i) == cpr) {
10280 restart = true;
10281 break;
10282 }
10283 }
10284 } else {
10285 i = NL;
10286 }
10287
10288 if (i >= NL) {
10289 removeDyingProviderLocked(app, cpr);
10290 NL = mLaunchingProviders.size();
10291 }
10292 }
10293 app.pubProviders.clear();
10294 }
10295
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010296 // Take care of any launching providers waiting for this process.
10297 if (checkAppInLaunchingProvidersLocked(app, false)) {
10298 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 // Unregister from connected content providers.
10302 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010303 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010304 while (it.hasNext()) {
10305 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10306 cpr.clients.remove(app);
10307 }
10308 app.conProviders.clear();
10309 }
10310
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010311 // At this point there may be remaining entries in mLaunchingProviders
10312 // where we were the only one waiting, so they are no longer of use.
10313 // Look for these and clean up if found.
10314 // XXX Commented out for now. Trying to figure out a way to reproduce
10315 // the actual situation to identify what is actually going on.
10316 if (false) {
10317 for (int i=0; i<NL; i++) {
10318 ContentProviderRecord cpr = (ContentProviderRecord)
10319 mLaunchingProviders.get(i);
10320 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10321 synchronized (cpr) {
10322 cpr.launchingApp = null;
10323 cpr.notifyAll();
10324 }
10325 }
10326 }
10327 }
10328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 skipCurrentReceiverLocked(app);
10330
10331 // Unregister any receivers.
10332 if (app.receivers.size() > 0) {
10333 Iterator<ReceiverList> it = app.receivers.iterator();
10334 while (it.hasNext()) {
10335 removeReceiverLocked(it.next());
10336 }
10337 app.receivers.clear();
10338 }
10339
Christopher Tate181fafa2009-05-14 11:12:14 -070010340 // If the app is undergoing backup, tell the backup manager about it
10341 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010342 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010343 try {
10344 IBackupManager bm = IBackupManager.Stub.asInterface(
10345 ServiceManager.getService(Context.BACKUP_SERVICE));
10346 bm.agentDisconnected(app.info.packageName);
10347 } catch (RemoteException e) {
10348 // can't happen; backup manager is local
10349 }
10350 }
10351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010352 // If the caller is restarting this app, then leave it in its
10353 // current lists and let the caller take care of it.
10354 if (restarting) {
10355 return;
10356 }
10357
10358 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010359 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010360 "Removing non-persistent process during cleanup: " + app);
10361 mProcessNames.remove(app.processName, app.info.uid);
10362 } else if (!app.removed) {
10363 // This app is persistent, so we need to keep its record around.
10364 // If it is not already on the pending app list, add it there
10365 // and start a new process for it.
10366 app.thread = null;
10367 app.forcingToForeground = null;
10368 app.foregroundServices = false;
10369 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10370 mPersistentStartingProcesses.add(app);
10371 restart = true;
10372 }
10373 }
10374 mProcessesOnHold.remove(app);
10375
The Android Open Source Project4df24232009-03-05 14:34:35 -080010376 if (app == mHomeProcess) {
10377 mHomeProcess = null;
10378 }
10379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010380 if (restart) {
10381 // We have components that still need to be running in the
10382 // process, so re-launch it.
10383 mProcessNames.put(app.processName, app.info.uid, app);
10384 startProcessLocked(app, "restart", app.processName);
10385 } else if (app.pid > 0 && app.pid != MY_PID) {
10386 // Goodbye!
10387 synchronized (mPidsSelfLocked) {
10388 mPidsSelfLocked.remove(app.pid);
10389 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10390 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010391 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010392 }
10393 }
10394
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010395 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10396 // Look through the content providers we are waiting to have launched,
10397 // and if any run in this process then either schedule a restart of
10398 // the process or kill the client waiting for it if this process has
10399 // gone bad.
10400 int NL = mLaunchingProviders.size();
10401 boolean restart = false;
10402 for (int i=0; i<NL; i++) {
10403 ContentProviderRecord cpr = (ContentProviderRecord)
10404 mLaunchingProviders.get(i);
10405 if (cpr.launchingApp == app) {
10406 if (!alwaysBad && !app.bad) {
10407 restart = true;
10408 } else {
10409 removeDyingProviderLocked(app, cpr);
10410 NL = mLaunchingProviders.size();
10411 }
10412 }
10413 }
10414 return restart;
10415 }
10416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010417 // =========================================================
10418 // SERVICES
10419 // =========================================================
10420
10421 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10422 ActivityManager.RunningServiceInfo info =
10423 new ActivityManager.RunningServiceInfo();
10424 info.service = r.name;
10425 if (r.app != null) {
10426 info.pid = r.app.pid;
10427 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010428 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010429 info.process = r.processName;
10430 info.foreground = r.isForeground;
10431 info.activeSince = r.createTime;
10432 info.started = r.startRequested;
10433 info.clientCount = r.connections.size();
10434 info.crashCount = r.crashCount;
10435 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010436 if (r.isForeground) {
10437 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10438 }
10439 if (r.startRequested) {
10440 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10441 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010442 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010443 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10444 }
10445 if (r.app != null && r.app.persistent) {
10446 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10447 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010448 for (ConnectionRecord conn : r.connections.values()) {
10449 if (conn.clientLabel != 0) {
10450 info.clientPackage = conn.binding.client.info.packageName;
10451 info.clientLabel = conn.clientLabel;
10452 break;
10453 }
10454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010455 return info;
10456 }
10457
10458 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10459 int flags) {
10460 synchronized (this) {
10461 ArrayList<ActivityManager.RunningServiceInfo> res
10462 = new ArrayList<ActivityManager.RunningServiceInfo>();
10463
10464 if (mServices.size() > 0) {
10465 Iterator<ServiceRecord> it = mServices.values().iterator();
10466 while (it.hasNext() && res.size() < maxNum) {
10467 res.add(makeRunningServiceInfoLocked(it.next()));
10468 }
10469 }
10470
10471 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10472 ServiceRecord r = mRestartingServices.get(i);
10473 ActivityManager.RunningServiceInfo info =
10474 makeRunningServiceInfoLocked(r);
10475 info.restarting = r.nextRestartTime;
10476 res.add(info);
10477 }
10478
10479 return res;
10480 }
10481 }
10482
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010483 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10484 synchronized (this) {
10485 ServiceRecord r = mServices.get(name);
10486 if (r != null) {
10487 for (ConnectionRecord conn : r.connections.values()) {
10488 if (conn.clientIntent != null) {
10489 return conn.clientIntent;
10490 }
10491 }
10492 }
10493 }
10494 return null;
10495 }
10496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010497 private final ServiceRecord findServiceLocked(ComponentName name,
10498 IBinder token) {
10499 ServiceRecord r = mServices.get(name);
10500 return r == token ? r : null;
10501 }
10502
10503 private final class ServiceLookupResult {
10504 final ServiceRecord record;
10505 final String permission;
10506
10507 ServiceLookupResult(ServiceRecord _record, String _permission) {
10508 record = _record;
10509 permission = _permission;
10510 }
10511 };
10512
10513 private ServiceLookupResult findServiceLocked(Intent service,
10514 String resolvedType) {
10515 ServiceRecord r = null;
10516 if (service.getComponent() != null) {
10517 r = mServices.get(service.getComponent());
10518 }
10519 if (r == null) {
10520 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10521 r = mServicesByIntent.get(filter);
10522 }
10523
10524 if (r == null) {
10525 try {
10526 ResolveInfo rInfo =
10527 ActivityThread.getPackageManager().resolveService(
10528 service, resolvedType, 0);
10529 ServiceInfo sInfo =
10530 rInfo != null ? rInfo.serviceInfo : null;
10531 if (sInfo == null) {
10532 return null;
10533 }
10534
10535 ComponentName name = new ComponentName(
10536 sInfo.applicationInfo.packageName, sInfo.name);
10537 r = mServices.get(name);
10538 } catch (RemoteException ex) {
10539 // pm is in same process, this will never happen.
10540 }
10541 }
10542 if (r != null) {
10543 int callingPid = Binder.getCallingPid();
10544 int callingUid = Binder.getCallingUid();
10545 if (checkComponentPermission(r.permission,
10546 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10547 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010548 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010549 + " from pid=" + callingPid
10550 + ", uid=" + callingUid
10551 + " requires " + r.permission);
10552 return new ServiceLookupResult(null, r.permission);
10553 }
10554 return new ServiceLookupResult(r, null);
10555 }
10556 return null;
10557 }
10558
10559 private class ServiceRestarter implements Runnable {
10560 private ServiceRecord mService;
10561
10562 void setService(ServiceRecord service) {
10563 mService = service;
10564 }
10565
10566 public void run() {
10567 synchronized(ActivityManagerService.this) {
10568 performServiceRestartLocked(mService);
10569 }
10570 }
10571 }
10572
10573 private ServiceLookupResult retrieveServiceLocked(Intent service,
10574 String resolvedType, int callingPid, int callingUid) {
10575 ServiceRecord r = null;
10576 if (service.getComponent() != null) {
10577 r = mServices.get(service.getComponent());
10578 }
10579 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10580 r = mServicesByIntent.get(filter);
10581 if (r == null) {
10582 try {
10583 ResolveInfo rInfo =
10584 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010585 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010586 ServiceInfo sInfo =
10587 rInfo != null ? rInfo.serviceInfo : null;
10588 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010589 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010590 ": not found");
10591 return null;
10592 }
10593
10594 ComponentName name = new ComponentName(
10595 sInfo.applicationInfo.packageName, sInfo.name);
10596 r = mServices.get(name);
10597 if (r == null) {
10598 filter = new Intent.FilterComparison(service.cloneFilter());
10599 ServiceRestarter res = new ServiceRestarter();
10600 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10601 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10602 synchronized (stats) {
10603 ss = stats.getServiceStatsLocked(
10604 sInfo.applicationInfo.uid, sInfo.packageName,
10605 sInfo.name);
10606 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010607 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010608 res.setService(r);
10609 mServices.put(name, r);
10610 mServicesByIntent.put(filter, r);
10611
10612 // Make sure this component isn't in the pending list.
10613 int N = mPendingServices.size();
10614 for (int i=0; i<N; i++) {
10615 ServiceRecord pr = mPendingServices.get(i);
10616 if (pr.name.equals(name)) {
10617 mPendingServices.remove(i);
10618 i--;
10619 N--;
10620 }
10621 }
10622 }
10623 } catch (RemoteException ex) {
10624 // pm is in same process, this will never happen.
10625 }
10626 }
10627 if (r != null) {
10628 if (checkComponentPermission(r.permission,
10629 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10630 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010631 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632 + " from pid=" + Binder.getCallingPid()
10633 + ", uid=" + Binder.getCallingUid()
10634 + " requires " + r.permission);
10635 return new ServiceLookupResult(null, r.permission);
10636 }
10637 return new ServiceLookupResult(r, null);
10638 }
10639 return null;
10640 }
10641
10642 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10643 long now = SystemClock.uptimeMillis();
10644 if (r.executeNesting == 0 && r.app != null) {
10645 if (r.app.executingServices.size() == 0) {
10646 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10647 msg.obj = r.app;
10648 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10649 }
10650 r.app.executingServices.add(r);
10651 }
10652 r.executeNesting++;
10653 r.executingStart = now;
10654 }
10655
10656 private final void sendServiceArgsLocked(ServiceRecord r,
10657 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010658 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010659 if (N == 0) {
10660 return;
10661 }
10662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010663 int i = 0;
10664 while (i < N) {
10665 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010666 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010667 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010668 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010669 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010670 // If somehow we got a dummy start at the front, then
10671 // just drop it here.
10672 i++;
10673 continue;
10674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010675 bumpServiceExecutingLocked(r);
10676 if (!oomAdjusted) {
10677 oomAdjusted = true;
10678 updateOomAdjLocked(r.app);
10679 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010680 int flags = 0;
10681 if (si.deliveryCount > 0) {
10682 flags |= Service.START_FLAG_RETRY;
10683 }
10684 if (si.doneExecutingCount > 0) {
10685 flags |= Service.START_FLAG_REDELIVERY;
10686 }
10687 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10688 si.deliveredTime = SystemClock.uptimeMillis();
10689 r.deliveredStarts.add(si);
10690 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010691 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010692 } catch (RemoteException e) {
10693 // Remote process gone... we'll let the normal cleanup take
10694 // care of this.
10695 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010696 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010697 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010698 break;
10699 }
10700 }
10701 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010702 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010703 } else {
10704 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010705 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010706 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010707 }
10708 }
10709 }
10710
10711 private final boolean requestServiceBindingLocked(ServiceRecord r,
10712 IntentBindRecord i, boolean rebind) {
10713 if (r.app == null || r.app.thread == null) {
10714 // If service is not currently running, can't yet bind.
10715 return false;
10716 }
10717 if ((!i.requested || rebind) && i.apps.size() > 0) {
10718 try {
10719 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010720 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010721 + ": shouldUnbind=" + i.hasBound);
10722 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10723 if (!rebind) {
10724 i.requested = true;
10725 }
10726 i.hasBound = true;
10727 i.doRebind = false;
10728 } catch (RemoteException e) {
10729 return false;
10730 }
10731 }
10732 return true;
10733 }
10734
10735 private final void requestServiceBindingsLocked(ServiceRecord r) {
10736 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10737 while (bindings.hasNext()) {
10738 IntentBindRecord i = bindings.next();
10739 if (!requestServiceBindingLocked(r, i, false)) {
10740 break;
10741 }
10742 }
10743 }
10744
10745 private final void realStartServiceLocked(ServiceRecord r,
10746 ProcessRecord app) throws RemoteException {
10747 if (app.thread == null) {
10748 throw new RemoteException();
10749 }
10750
10751 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010752 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753
10754 app.services.add(r);
10755 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010756 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757
10758 boolean created = false;
10759 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010760 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010762 mStringBuilder.setLength(0);
10763 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010764 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010766 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010767 synchronized (r.stats.getBatteryStats()) {
10768 r.stats.startLaunchedLocked();
10769 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010770 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010771 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010772 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010773 created = true;
10774 } finally {
10775 if (!created) {
10776 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010777 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778 }
10779 }
10780
10781 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010782
10783 // If the service is in the started state, and there are no
10784 // pending arguments, then fake up one so its onStartCommand() will
10785 // be called.
10786 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10787 r.lastStartId++;
10788 if (r.lastStartId < 1) {
10789 r.lastStartId = 1;
10790 }
10791 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10792 }
10793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 sendServiceArgsLocked(r, true);
10795 }
10796
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010797 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10798 boolean allowCancel) {
10799 boolean canceled = false;
10800
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010801 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010802 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010803 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010804
10805 // Any delivered but not yet finished starts should be put back
10806 // on the pending list.
10807 final int N = r.deliveredStarts.size();
10808 if (N > 0) {
10809 for (int i=N-1; i>=0; i--) {
10810 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10811 if (si.intent == null) {
10812 // We'll generate this again if needed.
10813 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10814 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10815 r.pendingStarts.add(0, si);
10816 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10817 dur *= 2;
10818 if (minDuration < dur) minDuration = dur;
10819 if (resetTime < dur) resetTime = dur;
10820 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010821 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010822 + r.name);
10823 canceled = true;
10824 }
10825 }
10826 r.deliveredStarts.clear();
10827 }
10828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 r.totalRestartCount++;
10830 if (r.restartDelay == 0) {
10831 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010832 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833 } else {
10834 // If it has been a "reasonably long time" since the service
10835 // was started, then reset our restart duration back to
10836 // the beginning, so we don't infinitely increase the duration
10837 // on a service that just occasionally gets killed (which is
10838 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010839 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010840 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010841 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010842 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010843 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010844 if (r.restartDelay < minDuration) {
10845 r.restartDelay = minDuration;
10846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010847 }
10848 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010849
10850 r.nextRestartTime = now + r.restartDelay;
10851
10852 // Make sure that we don't end up restarting a bunch of services
10853 // all at the same time.
10854 boolean repeat;
10855 do {
10856 repeat = false;
10857 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10858 ServiceRecord r2 = mRestartingServices.get(i);
10859 if (r2 != r && r.nextRestartTime
10860 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10861 && r.nextRestartTime
10862 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10863 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10864 r.restartDelay = r.nextRestartTime - now;
10865 repeat = true;
10866 break;
10867 }
10868 }
10869 } while (repeat);
10870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010871 if (!mRestartingServices.contains(r)) {
10872 mRestartingServices.add(r);
10873 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010874
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010875 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010877 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010878 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010879 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010880 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010881 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010882 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010883 r.shortName, r.restartDelay);
10884
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010885 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010886 }
10887
10888 final void performServiceRestartLocked(ServiceRecord r) {
10889 if (!mRestartingServices.contains(r)) {
10890 return;
10891 }
10892 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10893 }
10894
10895 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10896 if (r.restartDelay == 0) {
10897 return false;
10898 }
10899 r.resetRestartCounter();
10900 mRestartingServices.remove(r);
10901 mHandler.removeCallbacks(r.restarter);
10902 return true;
10903 }
10904
10905 private final boolean bringUpServiceLocked(ServiceRecord r,
10906 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010907 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 //r.dump(" ");
10909
Dianne Hackborn36124872009-10-08 16:22:03 -070010910 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010911 sendServiceArgsLocked(r, false);
10912 return true;
10913 }
10914
10915 if (!whileRestarting && r.restartDelay > 0) {
10916 // If waiting for a restart, then do nothing.
10917 return true;
10918 }
10919
Joe Onorato8a9b2202010-02-26 18:56:32 -080010920 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 + " " + r.intent);
10922
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010923 // We are now bringing the service up, so no longer in the
10924 // restarting state.
10925 mRestartingServices.remove(r);
10926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927 final String appName = r.processName;
10928 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10929 if (app != null && app.thread != null) {
10930 try {
10931 realStartServiceLocked(r, app);
10932 return true;
10933 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010934 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010935 }
10936
10937 // If a dead object exception was thrown -- fall through to
10938 // restart the application.
10939 }
10940
Dianne Hackborn36124872009-10-08 16:22:03 -070010941 // Not running -- get it started, and enqueue this service record
10942 // to be executed when the app comes up.
10943 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10944 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010945 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070010946 + r.appInfo.packageName + "/"
10947 + r.appInfo.uid + " for service "
10948 + r.intent.getIntent() + ": process is bad");
10949 bringDownServiceLocked(r, true);
10950 return false;
10951 }
10952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010953 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 mPendingServices.add(r);
10955 }
Dianne Hackborn36124872009-10-08 16:22:03 -070010956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 return true;
10958 }
10959
10960 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010961 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010962 //r.dump(" ");
10963
10964 // Does it still need to run?
10965 if (!force && r.startRequested) {
10966 return;
10967 }
10968 if (r.connections.size() > 0) {
10969 if (!force) {
10970 // XXX should probably keep a count of the number of auto-create
10971 // connections directly in the service.
10972 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10973 while (it.hasNext()) {
10974 ConnectionRecord cr = it.next();
10975 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10976 return;
10977 }
10978 }
10979 }
10980
10981 // Report to all of the connections that the service is no longer
10982 // available.
10983 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10984 while (it.hasNext()) {
10985 ConnectionRecord c = it.next();
10986 try {
10987 // todo: shouldn't be a synchronous call!
10988 c.conn.connected(r.name, null);
10989 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010990 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010991 " to connection " + c.conn.asBinder() +
10992 " (in " + c.binding.client.processName + ")", e);
10993 }
10994 }
10995 }
10996
10997 // Tell the service that it has been unbound.
10998 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10999 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11000 while (it.hasNext()) {
11001 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011002 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011003 + ": hasBound=" + ibr.hasBound);
11004 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11005 try {
11006 bumpServiceExecutingLocked(r);
11007 updateOomAdjLocked(r.app);
11008 ibr.hasBound = false;
11009 r.app.thread.scheduleUnbindService(r,
11010 ibr.intent.getIntent());
11011 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011012 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011013 + r.shortName, e);
11014 serviceDoneExecutingLocked(r, true);
11015 }
11016 }
11017 }
11018 }
11019
Joe Onorato8a9b2202010-02-26 18:56:32 -080011020 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011022 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 System.identityHashCode(r), r.shortName,
11024 (r.app != null) ? r.app.pid : -1);
11025
11026 mServices.remove(r.name);
11027 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011028 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 r.totalRestartCount = 0;
11030 unscheduleServiceRestartLocked(r);
11031
11032 // Also make sure it is not on the pending list.
11033 int N = mPendingServices.size();
11034 for (int i=0; i<N; i++) {
11035 if (mPendingServices.get(i) == r) {
11036 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011037 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011038 TAG, "Removed pending service: " + r.shortName);
11039 i--;
11040 N--;
11041 }
11042 }
11043
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011044 r.cancelNotification();
11045 r.isForeground = false;
11046 r.foregroundId = 0;
11047 r.foregroundNoti = null;
11048
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011049 // Clear start entries.
11050 r.deliveredStarts.clear();
11051 r.pendingStarts.clear();
11052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 if (r.app != null) {
11054 synchronized (r.stats.getBatteryStats()) {
11055 r.stats.stopLaunchedLocked();
11056 }
11057 r.app.services.remove(r);
11058 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011059 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011060 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011061 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 bumpServiceExecutingLocked(r);
11063 mStoppingServices.add(r);
11064 updateOomAdjLocked(r.app);
11065 r.app.thread.scheduleStopService(r);
11066 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011067 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011068 + r.shortName, e);
11069 serviceDoneExecutingLocked(r, true);
11070 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011071 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011073 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011074 TAG, "Removed service that has no process: " + r.shortName);
11075 }
11076 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011077 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011078 TAG, "Removed service that is not running: " + r.shortName);
11079 }
11080 }
11081
11082 ComponentName startServiceLocked(IApplicationThread caller,
11083 Intent service, String resolvedType,
11084 int callingPid, int callingUid) {
11085 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011086 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 + " type=" + resolvedType + " args=" + service.getExtras());
11088
11089 if (caller != null) {
11090 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11091 if (callerApp == null) {
11092 throw new SecurityException(
11093 "Unable to find app for caller " + caller
11094 + " (pid=" + Binder.getCallingPid()
11095 + ") when starting service " + service);
11096 }
11097 }
11098
11099 ServiceLookupResult res =
11100 retrieveServiceLocked(service, resolvedType,
11101 callingPid, callingUid);
11102 if (res == null) {
11103 return null;
11104 }
11105 if (res.record == null) {
11106 return new ComponentName("!", res.permission != null
11107 ? res.permission : "private to package");
11108 }
11109 ServiceRecord r = res.record;
11110 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011111 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011112 + r.shortName);
11113 }
11114 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011115 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011116 r.lastStartId++;
11117 if (r.lastStartId < 1) {
11118 r.lastStartId = 1;
11119 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011120 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011121 r.lastActivity = SystemClock.uptimeMillis();
11122 synchronized (r.stats.getBatteryStats()) {
11123 r.stats.startRunningLocked();
11124 }
11125 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11126 return new ComponentName("!", "Service process is bad");
11127 }
11128 return r.name;
11129 }
11130 }
11131
11132 public ComponentName startService(IApplicationThread caller, Intent service,
11133 String resolvedType) {
11134 // Refuse possible leaked file descriptors
11135 if (service != null && service.hasFileDescriptors() == true) {
11136 throw new IllegalArgumentException("File descriptors passed in Intent");
11137 }
11138
11139 synchronized(this) {
11140 final int callingPid = Binder.getCallingPid();
11141 final int callingUid = Binder.getCallingUid();
11142 final long origId = Binder.clearCallingIdentity();
11143 ComponentName res = startServiceLocked(caller, service,
11144 resolvedType, callingPid, callingUid);
11145 Binder.restoreCallingIdentity(origId);
11146 return res;
11147 }
11148 }
11149
11150 ComponentName startServiceInPackage(int uid,
11151 Intent service, String resolvedType) {
11152 synchronized(this) {
11153 final long origId = Binder.clearCallingIdentity();
11154 ComponentName res = startServiceLocked(null, service,
11155 resolvedType, -1, uid);
11156 Binder.restoreCallingIdentity(origId);
11157 return res;
11158 }
11159 }
11160
11161 public int stopService(IApplicationThread caller, Intent service,
11162 String resolvedType) {
11163 // Refuse possible leaked file descriptors
11164 if (service != null && service.hasFileDescriptors() == true) {
11165 throw new IllegalArgumentException("File descriptors passed in Intent");
11166 }
11167
11168 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011169 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011170 + " type=" + resolvedType);
11171
11172 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11173 if (caller != null && callerApp == null) {
11174 throw new SecurityException(
11175 "Unable to find app for caller " + caller
11176 + " (pid=" + Binder.getCallingPid()
11177 + ") when stopping service " + service);
11178 }
11179
11180 // If this service is active, make sure it is stopped.
11181 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11182 if (r != null) {
11183 if (r.record != null) {
11184 synchronized (r.record.stats.getBatteryStats()) {
11185 r.record.stats.stopRunningLocked();
11186 }
11187 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011188 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189 final long origId = Binder.clearCallingIdentity();
11190 bringDownServiceLocked(r.record, false);
11191 Binder.restoreCallingIdentity(origId);
11192 return 1;
11193 }
11194 return -1;
11195 }
11196 }
11197
11198 return 0;
11199 }
11200
11201 public IBinder peekService(Intent service, String resolvedType) {
11202 // Refuse possible leaked file descriptors
11203 if (service != null && service.hasFileDescriptors() == true) {
11204 throw new IllegalArgumentException("File descriptors passed in Intent");
11205 }
11206
11207 IBinder ret = null;
11208
11209 synchronized(this) {
11210 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11211
11212 if (r != null) {
11213 // r.record is null if findServiceLocked() failed the caller permission check
11214 if (r.record == null) {
11215 throw new SecurityException(
11216 "Permission Denial: Accessing service " + r.record.name
11217 + " from pid=" + Binder.getCallingPid()
11218 + ", uid=" + Binder.getCallingUid()
11219 + " requires " + r.permission);
11220 }
11221 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11222 if (ib != null) {
11223 ret = ib.binder;
11224 }
11225 }
11226 }
11227
11228 return ret;
11229 }
11230
11231 public boolean stopServiceToken(ComponentName className, IBinder token,
11232 int startId) {
11233 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011234 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 + " " + token + " startId=" + startId);
11236 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011237 if (r != null) {
11238 if (startId >= 0) {
11239 // Asked to only stop if done with all work. Note that
11240 // to avoid leaks, we will take this as dropping all
11241 // start items up to and including this one.
11242 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11243 if (si != null) {
11244 while (r.deliveredStarts.size() > 0) {
11245 if (r.deliveredStarts.remove(0) == si) {
11246 break;
11247 }
11248 }
11249 }
11250
11251 if (r.lastStartId != startId) {
11252 return false;
11253 }
11254
11255 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011256 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011257 + " is last, but have " + r.deliveredStarts.size()
11258 + " remaining args");
11259 }
11260 }
11261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 synchronized (r.stats.getBatteryStats()) {
11263 r.stats.stopRunningLocked();
11264 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011265 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 }
11267 final long origId = Binder.clearCallingIdentity();
11268 bringDownServiceLocked(r, false);
11269 Binder.restoreCallingIdentity(origId);
11270 return true;
11271 }
11272 }
11273 return false;
11274 }
11275
11276 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011277 int id, Notification notification, boolean removeNotification) {
11278 final long origId = Binder.clearCallingIdentity();
11279 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011280 synchronized(this) {
11281 ServiceRecord r = findServiceLocked(className, token);
11282 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011283 if (id != 0) {
11284 if (notification == null) {
11285 throw new IllegalArgumentException("null notification");
11286 }
11287 if (r.foregroundId != id) {
11288 r.cancelNotification();
11289 r.foregroundId = id;
11290 }
11291 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11292 r.foregroundNoti = notification;
11293 r.isForeground = true;
11294 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 if (r.app != null) {
11296 updateServiceForegroundLocked(r.app, true);
11297 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011298 } else {
11299 if (r.isForeground) {
11300 r.isForeground = false;
11301 if (r.app != null) {
11302 updateServiceForegroundLocked(r.app, true);
11303 }
11304 }
11305 if (removeNotification) {
11306 r.cancelNotification();
11307 r.foregroundId = 0;
11308 r.foregroundNoti = null;
11309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011310 }
11311 }
11312 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011313 } finally {
11314 Binder.restoreCallingIdentity(origId);
11315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011316 }
11317
11318 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11319 boolean anyForeground = false;
11320 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11321 if (sr.isForeground) {
11322 anyForeground = true;
11323 break;
11324 }
11325 }
11326 if (anyForeground != proc.foregroundServices) {
11327 proc.foregroundServices = anyForeground;
11328 if (oomAdj) {
11329 updateOomAdjLocked();
11330 }
11331 }
11332 }
11333
11334 public int bindService(IApplicationThread caller, IBinder token,
11335 Intent service, String resolvedType,
11336 IServiceConnection connection, int flags) {
11337 // Refuse possible leaked file descriptors
11338 if (service != null && service.hasFileDescriptors() == true) {
11339 throw new IllegalArgumentException("File descriptors passed in Intent");
11340 }
11341
11342 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011343 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011344 + " type=" + resolvedType + " conn=" + connection.asBinder()
11345 + " flags=0x" + Integer.toHexString(flags));
11346 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11347 if (callerApp == null) {
11348 throw new SecurityException(
11349 "Unable to find app for caller " + caller
11350 + " (pid=" + Binder.getCallingPid()
11351 + ") when binding service " + service);
11352 }
11353
11354 HistoryRecord activity = null;
11355 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011356 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011358 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011359 return 0;
11360 }
11361 activity = (HistoryRecord)mHistory.get(aindex);
11362 }
11363
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011364 int clientLabel = 0;
11365 PendingIntent clientIntent = null;
11366
11367 if (callerApp.info.uid == Process.SYSTEM_UID) {
11368 // Hacky kind of thing -- allow system stuff to tell us
11369 // what they are, so we can report this elsewhere for
11370 // others to know why certain services are running.
11371 try {
11372 clientIntent = (PendingIntent)service.getParcelableExtra(
11373 Intent.EXTRA_CLIENT_INTENT);
11374 } catch (RuntimeException e) {
11375 }
11376 if (clientIntent != null) {
11377 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11378 if (clientLabel != 0) {
11379 // There are no useful extras in the intent, trash them.
11380 // System code calling with this stuff just needs to know
11381 // this will happen.
11382 service = service.cloneFilter();
11383 }
11384 }
11385 }
11386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387 ServiceLookupResult res =
11388 retrieveServiceLocked(service, resolvedType,
11389 Binder.getCallingPid(), Binder.getCallingUid());
11390 if (res == null) {
11391 return 0;
11392 }
11393 if (res.record == null) {
11394 return -1;
11395 }
11396 ServiceRecord s = res.record;
11397
11398 final long origId = Binder.clearCallingIdentity();
11399
11400 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011401 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011402 + s.shortName);
11403 }
11404
11405 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11406 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011407 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408
11409 IBinder binder = connection.asBinder();
11410 s.connections.put(binder, c);
11411 b.connections.add(c);
11412 if (activity != null) {
11413 if (activity.connections == null) {
11414 activity.connections = new HashSet<ConnectionRecord>();
11415 }
11416 activity.connections.add(c);
11417 }
11418 b.client.connections.add(c);
11419 mServiceConnections.put(binder, c);
11420
11421 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11422 s.lastActivity = SystemClock.uptimeMillis();
11423 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11424 return 0;
11425 }
11426 }
11427
11428 if (s.app != null) {
11429 // This could have made the service more important.
11430 updateOomAdjLocked(s.app);
11431 }
11432
Joe Onorato8a9b2202010-02-26 18:56:32 -080011433 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 + ": received=" + b.intent.received
11435 + " apps=" + b.intent.apps.size()
11436 + " doRebind=" + b.intent.doRebind);
11437
11438 if (s.app != null && b.intent.received) {
11439 // Service is already running, so we can immediately
11440 // publish the connection.
11441 try {
11442 c.conn.connected(s.name, b.intent.binder);
11443 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011444 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011445 + " to connection " + c.conn.asBinder()
11446 + " (in " + c.binding.client.processName + ")", e);
11447 }
11448
11449 // If this is the first app connected back to this binding,
11450 // and the service had previously asked to be told when
11451 // rebound, then do so.
11452 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11453 requestServiceBindingLocked(s, b.intent, true);
11454 }
11455 } else if (!b.intent.requested) {
11456 requestServiceBindingLocked(s, b.intent, false);
11457 }
11458
11459 Binder.restoreCallingIdentity(origId);
11460 }
11461
11462 return 1;
11463 }
11464
11465 private void removeConnectionLocked(
11466 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11467 IBinder binder = c.conn.asBinder();
11468 AppBindRecord b = c.binding;
11469 ServiceRecord s = b.service;
11470 s.connections.remove(binder);
11471 b.connections.remove(c);
11472 if (c.activity != null && c.activity != skipAct) {
11473 if (c.activity.connections != null) {
11474 c.activity.connections.remove(c);
11475 }
11476 }
11477 if (b.client != skipApp) {
11478 b.client.connections.remove(c);
11479 }
11480 mServiceConnections.remove(binder);
11481
11482 if (b.connections.size() == 0) {
11483 b.intent.apps.remove(b.client);
11484 }
11485
Joe Onorato8a9b2202010-02-26 18:56:32 -080011486 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011487 + ": shouldUnbind=" + b.intent.hasBound);
11488 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11489 && b.intent.hasBound) {
11490 try {
11491 bumpServiceExecutingLocked(s);
11492 updateOomAdjLocked(s.app);
11493 b.intent.hasBound = false;
11494 // Assume the client doesn't want to know about a rebind;
11495 // we will deal with that later if it asks for one.
11496 b.intent.doRebind = false;
11497 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11498 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011499 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 serviceDoneExecutingLocked(s, true);
11501 }
11502 }
11503
11504 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11505 bringDownServiceLocked(s, false);
11506 }
11507 }
11508
11509 public boolean unbindService(IServiceConnection connection) {
11510 synchronized (this) {
11511 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011512 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 ConnectionRecord r = mServiceConnections.get(binder);
11514 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011515 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011516 + connection.asBinder());
11517 return false;
11518 }
11519
11520 final long origId = Binder.clearCallingIdentity();
11521
11522 removeConnectionLocked(r, null, null);
11523
11524 if (r.binding.service.app != null) {
11525 // This could have made the service less important.
11526 updateOomAdjLocked(r.binding.service.app);
11527 }
11528
11529 Binder.restoreCallingIdentity(origId);
11530 }
11531
11532 return true;
11533 }
11534
11535 public void publishService(IBinder token, Intent intent, IBinder service) {
11536 // Refuse possible leaked file descriptors
11537 if (intent != null && intent.hasFileDescriptors() == true) {
11538 throw new IllegalArgumentException("File descriptors passed in Intent");
11539 }
11540
11541 synchronized(this) {
11542 if (!(token instanceof ServiceRecord)) {
11543 throw new IllegalArgumentException("Invalid service token");
11544 }
11545 ServiceRecord r = (ServiceRecord)token;
11546
11547 final long origId = Binder.clearCallingIdentity();
11548
Joe Onorato8a9b2202010-02-26 18:56:32 -080011549 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011550 + " " + intent + ": " + service);
11551 if (r != null) {
11552 Intent.FilterComparison filter
11553 = new Intent.FilterComparison(intent);
11554 IntentBindRecord b = r.bindings.get(filter);
11555 if (b != null && !b.received) {
11556 b.binder = service;
11557 b.requested = true;
11558 b.received = true;
11559 if (r.connections.size() > 0) {
11560 Iterator<ConnectionRecord> it
11561 = r.connections.values().iterator();
11562 while (it.hasNext()) {
11563 ConnectionRecord c = it.next();
11564 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011565 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011567 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011568 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011569 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 TAG, "Published intent: " + intent);
11571 continue;
11572 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011573 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011574 try {
11575 c.conn.connected(r.name, service);
11576 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011577 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 " to connection " + c.conn.asBinder() +
11579 " (in " + c.binding.client.processName + ")", e);
11580 }
11581 }
11582 }
11583 }
11584
11585 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11586
11587 Binder.restoreCallingIdentity(origId);
11588 }
11589 }
11590 }
11591
11592 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11593 // Refuse possible leaked file descriptors
11594 if (intent != null && intent.hasFileDescriptors() == true) {
11595 throw new IllegalArgumentException("File descriptors passed in Intent");
11596 }
11597
11598 synchronized(this) {
11599 if (!(token instanceof ServiceRecord)) {
11600 throw new IllegalArgumentException("Invalid service token");
11601 }
11602 ServiceRecord r = (ServiceRecord)token;
11603
11604 final long origId = Binder.clearCallingIdentity();
11605
11606 if (r != null) {
11607 Intent.FilterComparison filter
11608 = new Intent.FilterComparison(intent);
11609 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011610 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011611 + " at " + b + ": apps="
11612 + (b != null ? b.apps.size() : 0));
11613 if (b != null) {
11614 if (b.apps.size() > 0) {
11615 // Applications have already bound since the last
11616 // unbind, so just rebind right here.
11617 requestServiceBindingLocked(r, b, true);
11618 } else {
11619 // Note to tell the service the next time there is
11620 // a new client.
11621 b.doRebind = true;
11622 }
11623 }
11624
11625 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11626
11627 Binder.restoreCallingIdentity(origId);
11628 }
11629 }
11630 }
11631
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011632 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 synchronized(this) {
11634 if (!(token instanceof ServiceRecord)) {
11635 throw new IllegalArgumentException("Invalid service token");
11636 }
11637 ServiceRecord r = (ServiceRecord)token;
11638 boolean inStopping = mStoppingServices.contains(token);
11639 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011640 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011641 + ": nesting=" + r.executeNesting
11642 + ", inStopping=" + inStopping);
11643 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011644 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011645 + " with incorrect token: given " + token
11646 + ", expected " + r);
11647 return;
11648 }
11649
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011650 if (type == 1) {
11651 // This is a call from a service start... take care of
11652 // book-keeping.
11653 r.callStart = true;
11654 switch (res) {
11655 case Service.START_STICKY_COMPATIBILITY:
11656 case Service.START_STICKY: {
11657 // We are done with the associated start arguments.
11658 r.findDeliveredStart(startId, true);
11659 // Don't stop if killed.
11660 r.stopIfKilled = false;
11661 break;
11662 }
11663 case Service.START_NOT_STICKY: {
11664 // We are done with the associated start arguments.
11665 r.findDeliveredStart(startId, true);
11666 if (r.lastStartId == startId) {
11667 // There is no more work, and this service
11668 // doesn't want to hang around if killed.
11669 r.stopIfKilled = true;
11670 }
11671 break;
11672 }
11673 case Service.START_REDELIVER_INTENT: {
11674 // We'll keep this item until they explicitly
11675 // call stop for it, but keep track of the fact
11676 // that it was delivered.
11677 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11678 if (si != null) {
11679 si.deliveryCount = 0;
11680 si.doneExecutingCount++;
11681 // Don't stop if killed.
11682 r.stopIfKilled = true;
11683 }
11684 break;
11685 }
11686 default:
11687 throw new IllegalArgumentException(
11688 "Unknown service start result: " + res);
11689 }
11690 if (res == Service.START_STICKY_COMPATIBILITY) {
11691 r.callStart = false;
11692 }
11693 }
11694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011695 final long origId = Binder.clearCallingIdentity();
11696 serviceDoneExecutingLocked(r, inStopping);
11697 Binder.restoreCallingIdentity(origId);
11698 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011699 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011700 + " with token " + token);
11701 }
11702 }
11703 }
11704
11705 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11706 r.executeNesting--;
11707 if (r.executeNesting <= 0 && r.app != null) {
11708 r.app.executingServices.remove(r);
11709 if (r.app.executingServices.size() == 0) {
11710 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11711 }
11712 if (inStopping) {
11713 mStoppingServices.remove(r);
11714 }
11715 updateOomAdjLocked(r.app);
11716 }
11717 }
11718
11719 void serviceTimeout(ProcessRecord proc) {
11720 synchronized(this) {
11721 if (proc.executingServices.size() == 0 || proc.thread == null) {
11722 return;
11723 }
11724 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11725 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11726 ServiceRecord timeout = null;
11727 long nextTime = 0;
11728 while (it.hasNext()) {
11729 ServiceRecord sr = it.next();
11730 if (sr.executingStart < maxTime) {
11731 timeout = sr;
11732 break;
11733 }
11734 if (sr.executingStart > nextTime) {
11735 nextTime = sr.executingStart;
11736 }
11737 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011738 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011739 Slog.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011740 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011741 } else {
11742 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11743 msg.obj = proc;
11744 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11745 }
11746 }
11747 }
11748
11749 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011750 // BACKUP AND RESTORE
11751 // =========================================================
11752
11753 // Cause the target app to be launched if necessary and its backup agent
11754 // instantiated. The backup agent will invoke backupAgentCreated() on the
11755 // activity manager to announce its creation.
11756 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011757 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011758 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11759
11760 synchronized(this) {
11761 // !!! TODO: currently no check here that we're already bound
11762 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11763 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11764 synchronized (stats) {
11765 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11766 }
11767
11768 BackupRecord r = new BackupRecord(ss, app, backupMode);
11769 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11770 // startProcessLocked() returns existing proc's record if it's already running
11771 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011772 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011773 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011774 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011775 return false;
11776 }
11777
11778 r.app = proc;
11779 mBackupTarget = r;
11780 mBackupAppName = app.packageName;
11781
Christopher Tate6fa95972009-06-05 18:43:55 -070011782 // Try not to kill the process during backup
11783 updateOomAdjLocked(proc);
11784
Christopher Tate181fafa2009-05-14 11:12:14 -070011785 // If the process is already attached, schedule the creation of the backup agent now.
11786 // If it is not yet live, this will be done when it attaches to the framework.
11787 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011788 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011789 try {
11790 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11791 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011792 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011793 }
11794 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011795 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011796 }
11797 // Invariants: at this point, the target app process exists and the application
11798 // is either already running or in the process of coming up. mBackupTarget and
11799 // mBackupAppName describe the app, so that when it binds back to the AM we
11800 // know that it's scheduled for a backup-agent operation.
11801 }
11802
11803 return true;
11804 }
11805
11806 // A backup agent has just come up
11807 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011808 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011809 + " = " + agent);
11810
11811 synchronized(this) {
11812 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011813 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011814 return;
11815 }
11816
Christopher Tate043dadc2009-06-02 16:11:00 -070011817 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011818 try {
11819 IBackupManager bm = IBackupManager.Stub.asInterface(
11820 ServiceManager.getService(Context.BACKUP_SERVICE));
11821 bm.agentConnected(agentPackageName, agent);
11822 } catch (RemoteException e) {
11823 // can't happen; the backup manager service is local
11824 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011825 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070011826 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011827 } finally {
11828 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011829 }
11830 }
11831 }
11832
11833 // done with this agent
11834 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011835 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011836 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011837 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011838 return;
11839 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011840
11841 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011842 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011843 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011844 return;
11845 }
11846
Christopher Tate181fafa2009-05-14 11:12:14 -070011847 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011848 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011849 return;
11850 }
11851
Christopher Tate6fa95972009-06-05 18:43:55 -070011852 ProcessRecord proc = mBackupTarget.app;
11853 mBackupTarget = null;
11854 mBackupAppName = null;
11855
11856 // Not backing this app up any more; reset its OOM adjustment
11857 updateOomAdjLocked(proc);
11858
Christopher Tatec7b31e32009-06-10 15:49:30 -070011859 // If the app crashed during backup, 'thread' will be null here
11860 if (proc.thread != null) {
11861 try {
11862 proc.thread.scheduleDestroyBackupAgent(appInfo);
11863 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011864 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070011865 e.printStackTrace();
11866 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011867 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011868 }
11869 }
11870 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011871 // BROADCASTS
11872 // =========================================================
11873
11874 private final List getStickies(String action, IntentFilter filter,
11875 List cur) {
11876 final ContentResolver resolver = mContext.getContentResolver();
11877 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11878 if (list == null) {
11879 return cur;
11880 }
11881 int N = list.size();
11882 for (int i=0; i<N; i++) {
11883 Intent intent = list.get(i);
11884 if (filter.match(resolver, intent, true, TAG) >= 0) {
11885 if (cur == null) {
11886 cur = new ArrayList<Intent>();
11887 }
11888 cur.add(intent);
11889 }
11890 }
11891 return cur;
11892 }
11893
11894 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011895 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011896 + mBroadcastsScheduled);
11897
11898 if (mBroadcastsScheduled) {
11899 return;
11900 }
11901 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11902 mBroadcastsScheduled = true;
11903 }
11904
11905 public Intent registerReceiver(IApplicationThread caller,
11906 IIntentReceiver receiver, IntentFilter filter, String permission) {
11907 synchronized(this) {
11908 ProcessRecord callerApp = null;
11909 if (caller != null) {
11910 callerApp = getRecordForAppLocked(caller);
11911 if (callerApp == null) {
11912 throw new SecurityException(
11913 "Unable to find app for caller " + caller
11914 + " (pid=" + Binder.getCallingPid()
11915 + ") when registering receiver " + receiver);
11916 }
11917 }
11918
11919 List allSticky = null;
11920
11921 // Look for any matching sticky broadcasts...
11922 Iterator actions = filter.actionsIterator();
11923 if (actions != null) {
11924 while (actions.hasNext()) {
11925 String action = (String)actions.next();
11926 allSticky = getStickies(action, filter, allSticky);
11927 }
11928 } else {
11929 allSticky = getStickies(null, filter, allSticky);
11930 }
11931
11932 // The first sticky in the list is returned directly back to
11933 // the client.
11934 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11935
Joe Onorato8a9b2202010-02-26 18:56:32 -080011936 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011937 + ": " + sticky);
11938
11939 if (receiver == null) {
11940 return sticky;
11941 }
11942
11943 ReceiverList rl
11944 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11945 if (rl == null) {
11946 rl = new ReceiverList(this, callerApp,
11947 Binder.getCallingPid(),
11948 Binder.getCallingUid(), receiver);
11949 if (rl.app != null) {
11950 rl.app.receivers.add(rl);
11951 } else {
11952 try {
11953 receiver.asBinder().linkToDeath(rl, 0);
11954 } catch (RemoteException e) {
11955 return sticky;
11956 }
11957 rl.linkedToDeath = true;
11958 }
11959 mRegisteredReceivers.put(receiver.asBinder(), rl);
11960 }
11961 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
11962 rl.add(bf);
11963 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011964 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011965 }
11966 mReceiverResolver.addFilter(bf);
11967
11968 // Enqueue broadcasts for all existing stickies that match
11969 // this filter.
11970 if (allSticky != null) {
11971 ArrayList receivers = new ArrayList();
11972 receivers.add(bf);
11973
11974 int N = allSticky.size();
11975 for (int i=0; i<N; i++) {
11976 Intent intent = (Intent)allSticky.get(i);
11977 BroadcastRecord r = new BroadcastRecord(intent, null,
11978 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011979 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011980 if (mParallelBroadcasts.size() == 0) {
11981 scheduleBroadcastsLocked();
11982 }
11983 mParallelBroadcasts.add(r);
11984 }
11985 }
11986
11987 return sticky;
11988 }
11989 }
11990
11991 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011992 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011993
11994 boolean doNext = false;
11995
11996 synchronized(this) {
11997 ReceiverList rl
11998 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11999 if (rl != null) {
12000 if (rl.curBroadcast != null) {
12001 BroadcastRecord r = rl.curBroadcast;
12002 doNext = finishReceiverLocked(
12003 receiver.asBinder(), r.resultCode, r.resultData,
12004 r.resultExtras, r.resultAbort, true);
12005 }
12006
12007 if (rl.app != null) {
12008 rl.app.receivers.remove(rl);
12009 }
12010 removeReceiverLocked(rl);
12011 if (rl.linkedToDeath) {
12012 rl.linkedToDeath = false;
12013 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12014 }
12015 }
12016 }
12017
12018 if (!doNext) {
12019 return;
12020 }
12021
12022 final long origId = Binder.clearCallingIdentity();
12023 processNextBroadcast(false);
12024 trimApplications();
12025 Binder.restoreCallingIdentity(origId);
12026 }
12027
12028 void removeReceiverLocked(ReceiverList rl) {
12029 mRegisteredReceivers.remove(rl.receiver.asBinder());
12030 int N = rl.size();
12031 for (int i=0; i<N; i++) {
12032 mReceiverResolver.removeFilter(rl.get(i));
12033 }
12034 }
12035
12036 private final int broadcastIntentLocked(ProcessRecord callerApp,
12037 String callerPackage, Intent intent, String resolvedType,
12038 IIntentReceiver resultTo, int resultCode, String resultData,
12039 Bundle map, String requiredPermission,
12040 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12041 intent = new Intent(intent);
12042
Joe Onorato8a9b2202010-02-26 18:56:32 -080012043 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012044 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12045 + " ordered=" + ordered);
12046 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012047 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012048 }
12049
12050 // Handle special intents: if this broadcast is from the package
12051 // manager about a package being removed, we need to remove all of
12052 // its activities from the history stack.
12053 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12054 intent.getAction());
12055 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12056 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012057 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012058 || uidRemoved) {
12059 if (checkComponentPermission(
12060 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12061 callingPid, callingUid, -1)
12062 == PackageManager.PERMISSION_GRANTED) {
12063 if (uidRemoved) {
12064 final Bundle intentExtras = intent.getExtras();
12065 final int uid = intentExtras != null
12066 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12067 if (uid >= 0) {
12068 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12069 synchronized (bs) {
12070 bs.removeUidStatsLocked(uid);
12071 }
12072 }
12073 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012074 // If resources are unvailble just force stop all
12075 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012076 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012077 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12078 if (list != null && (list.length > 0)) {
12079 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012080 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012081 }
12082 }
12083 } else {
12084 Uri data = intent.getData();
12085 String ssp;
12086 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12087 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12088 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012089 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012091 }
12092 }
12093 }
12094 } else {
12095 String msg = "Permission Denial: " + intent.getAction()
12096 + " broadcast from " + callerPackage + " (pid=" + callingPid
12097 + ", uid=" + callingUid + ")"
12098 + " requires "
12099 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012100 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012101 throw new SecurityException(msg);
12102 }
12103 }
12104
12105 /*
12106 * If this is the time zone changed action, queue up a message that will reset the timezone
12107 * of all currently running processes. This message will get queued up before the broadcast
12108 * happens.
12109 */
12110 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12111 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12112 }
12113
Dianne Hackborn854060af2009-07-09 18:14:31 -070012114 /*
12115 * Prevent non-system code (defined here to be non-persistent
12116 * processes) from sending protected broadcasts.
12117 */
12118 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12119 || callingUid == Process.SHELL_UID || callingUid == 0) {
12120 // Always okay.
12121 } else if (callerApp == null || !callerApp.persistent) {
12122 try {
12123 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12124 intent.getAction())) {
12125 String msg = "Permission Denial: not allowed to send broadcast "
12126 + intent.getAction() + " from pid="
12127 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012128 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012129 throw new SecurityException(msg);
12130 }
12131 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012132 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012133 return BROADCAST_SUCCESS;
12134 }
12135 }
12136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012137 // Add to the sticky list if requested.
12138 if (sticky) {
12139 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12140 callingPid, callingUid)
12141 != PackageManager.PERMISSION_GRANTED) {
12142 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12143 + callingPid + ", uid=" + callingUid
12144 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012145 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012146 throw new SecurityException(msg);
12147 }
12148 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012149 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012150 + " and enforce permission " + requiredPermission);
12151 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12152 }
12153 if (intent.getComponent() != null) {
12154 throw new SecurityException(
12155 "Sticky broadcasts can't target a specific component");
12156 }
12157 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12158 if (list == null) {
12159 list = new ArrayList<Intent>();
12160 mStickyBroadcasts.put(intent.getAction(), list);
12161 }
12162 int N = list.size();
12163 int i;
12164 for (i=0; i<N; i++) {
12165 if (intent.filterEquals(list.get(i))) {
12166 // This sticky already exists, replace it.
12167 list.set(i, new Intent(intent));
12168 break;
12169 }
12170 }
12171 if (i >= N) {
12172 list.add(new Intent(intent));
12173 }
12174 }
12175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012176 // Figure out who all will receive this broadcast.
12177 List receivers = null;
12178 List<BroadcastFilter> registeredReceivers = null;
12179 try {
12180 if (intent.getComponent() != null) {
12181 // Broadcast is going to one specific receiver class...
12182 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012183 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012184 if (ai != null) {
12185 receivers = new ArrayList();
12186 ResolveInfo ri = new ResolveInfo();
12187 ri.activityInfo = ai;
12188 receivers.add(ri);
12189 }
12190 } else {
12191 // Need to resolve the intent to interested receivers...
12192 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12193 == 0) {
12194 receivers =
12195 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012196 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012197 }
Mihai Preda074edef2009-05-18 17:13:31 +020012198 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012199 }
12200 } catch (RemoteException ex) {
12201 // pm is in same process, this will never happen.
12202 }
12203
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012204 final boolean replacePending =
12205 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12206
Joe Onorato8a9b2202010-02-26 18:56:32 -080012207 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012208 + " replacePending=" + replacePending);
12209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012210 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12211 if (!ordered && NR > 0) {
12212 // If we are not serializing this broadcast, then send the
12213 // registered receivers separately so they don't wait for the
12214 // components to be launched.
12215 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12216 callerPackage, callingPid, callingUid, requiredPermission,
12217 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012218 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012219 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012220 TAG, "Enqueueing parallel broadcast " + r
12221 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012222 boolean replaced = false;
12223 if (replacePending) {
12224 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12225 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012226 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012227 "***** DROPPING PARALLEL: " + intent);
12228 mParallelBroadcasts.set(i, r);
12229 replaced = true;
12230 break;
12231 }
12232 }
12233 }
12234 if (!replaced) {
12235 mParallelBroadcasts.add(r);
12236 scheduleBroadcastsLocked();
12237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012238 registeredReceivers = null;
12239 NR = 0;
12240 }
12241
12242 // Merge into one list.
12243 int ir = 0;
12244 if (receivers != null) {
12245 // A special case for PACKAGE_ADDED: do not allow the package
12246 // being added to see this broadcast. This prevents them from
12247 // using this as a back door to get run as soon as they are
12248 // installed. Maybe in the future we want to have a special install
12249 // broadcast or such for apps, but we'd like to deliberately make
12250 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012251 String skipPackages[] = null;
12252 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12253 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12254 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12255 Uri data = intent.getData();
12256 if (data != null) {
12257 String pkgName = data.getSchemeSpecificPart();
12258 if (pkgName != null) {
12259 skipPackages = new String[] { pkgName };
12260 }
12261 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012262 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012263 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012264 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012265 if (skipPackages != null && (skipPackages.length > 0)) {
12266 for (String skipPackage : skipPackages) {
12267 if (skipPackage != null) {
12268 int NT = receivers.size();
12269 for (int it=0; it<NT; it++) {
12270 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12271 if (curt.activityInfo.packageName.equals(skipPackage)) {
12272 receivers.remove(it);
12273 it--;
12274 NT--;
12275 }
12276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012277 }
12278 }
12279 }
12280
12281 int NT = receivers != null ? receivers.size() : 0;
12282 int it = 0;
12283 ResolveInfo curt = null;
12284 BroadcastFilter curr = null;
12285 while (it < NT && ir < NR) {
12286 if (curt == null) {
12287 curt = (ResolveInfo)receivers.get(it);
12288 }
12289 if (curr == null) {
12290 curr = registeredReceivers.get(ir);
12291 }
12292 if (curr.getPriority() >= curt.priority) {
12293 // Insert this broadcast record into the final list.
12294 receivers.add(it, curr);
12295 ir++;
12296 curr = null;
12297 it++;
12298 NT++;
12299 } else {
12300 // Skip to the next ResolveInfo in the final list.
12301 it++;
12302 curt = null;
12303 }
12304 }
12305 }
12306 while (ir < NR) {
12307 if (receivers == null) {
12308 receivers = new ArrayList();
12309 }
12310 receivers.add(registeredReceivers.get(ir));
12311 ir++;
12312 }
12313
12314 if ((receivers != null && receivers.size() > 0)
12315 || resultTo != null) {
12316 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12317 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012318 receivers, resultTo, resultCode, resultData, map, ordered,
12319 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012320 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012321 TAG, "Enqueueing ordered broadcast " + r
12322 + ": prev had " + mOrderedBroadcasts.size());
12323 if (DEBUG_BROADCAST) {
12324 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012325 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012326 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012327 boolean replaced = false;
12328 if (replacePending) {
12329 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12330 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012331 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012332 "***** DROPPING ORDERED: " + intent);
12333 mOrderedBroadcasts.set(i, r);
12334 replaced = true;
12335 break;
12336 }
12337 }
12338 }
12339 if (!replaced) {
12340 mOrderedBroadcasts.add(r);
12341 scheduleBroadcastsLocked();
12342 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012343 }
12344
12345 return BROADCAST_SUCCESS;
12346 }
12347
12348 public final int broadcastIntent(IApplicationThread caller,
12349 Intent intent, String resolvedType, IIntentReceiver resultTo,
12350 int resultCode, String resultData, Bundle map,
12351 String requiredPermission, boolean serialized, boolean sticky) {
12352 // Refuse possible leaked file descriptors
12353 if (intent != null && intent.hasFileDescriptors() == true) {
12354 throw new IllegalArgumentException("File descriptors passed in Intent");
12355 }
12356
12357 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012358 int flags = intent.getFlags();
12359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012360 if (!mSystemReady) {
12361 // if the caller really truly claims to know what they're doing, go
12362 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012363 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12364 intent = new Intent(intent);
12365 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12366 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012367 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012368 + " before boot completion");
12369 throw new IllegalStateException("Cannot broadcast before boot completed");
12370 }
12371 }
12372
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012373 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12374 throw new IllegalArgumentException(
12375 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12376 }
12377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012378 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12379 final int callingPid = Binder.getCallingPid();
12380 final int callingUid = Binder.getCallingUid();
12381 final long origId = Binder.clearCallingIdentity();
12382 int res = broadcastIntentLocked(callerApp,
12383 callerApp != null ? callerApp.info.packageName : null,
12384 intent, resolvedType, resultTo,
12385 resultCode, resultData, map, requiredPermission, serialized,
12386 sticky, callingPid, callingUid);
12387 Binder.restoreCallingIdentity(origId);
12388 return res;
12389 }
12390 }
12391
12392 int broadcastIntentInPackage(String packageName, int uid,
12393 Intent intent, String resolvedType, IIntentReceiver resultTo,
12394 int resultCode, String resultData, Bundle map,
12395 String requiredPermission, boolean serialized, boolean sticky) {
12396 synchronized(this) {
12397 final long origId = Binder.clearCallingIdentity();
12398 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12399 resultTo, resultCode, resultData, map, requiredPermission,
12400 serialized, sticky, -1, uid);
12401 Binder.restoreCallingIdentity(origId);
12402 return res;
12403 }
12404 }
12405
12406 public final void unbroadcastIntent(IApplicationThread caller,
12407 Intent intent) {
12408 // Refuse possible leaked file descriptors
12409 if (intent != null && intent.hasFileDescriptors() == true) {
12410 throw new IllegalArgumentException("File descriptors passed in Intent");
12411 }
12412
12413 synchronized(this) {
12414 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12415 != PackageManager.PERMISSION_GRANTED) {
12416 String msg = "Permission Denial: unbroadcastIntent() from pid="
12417 + Binder.getCallingPid()
12418 + ", uid=" + Binder.getCallingUid()
12419 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012420 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012421 throw new SecurityException(msg);
12422 }
12423 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12424 if (list != null) {
12425 int N = list.size();
12426 int i;
12427 for (i=0; i<N; i++) {
12428 if (intent.filterEquals(list.get(i))) {
12429 list.remove(i);
12430 break;
12431 }
12432 }
12433 }
12434 }
12435 }
12436
12437 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12438 String resultData, Bundle resultExtras, boolean resultAbort,
12439 boolean explicit) {
12440 if (mOrderedBroadcasts.size() == 0) {
12441 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012442 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012443 }
12444 return false;
12445 }
12446 BroadcastRecord r = mOrderedBroadcasts.get(0);
12447 if (r.receiver == null) {
12448 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012449 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012450 }
12451 return false;
12452 }
12453 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012454 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012455 return false;
12456 }
12457 int state = r.state;
12458 r.state = r.IDLE;
12459 if (state == r.IDLE) {
12460 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012461 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012462 }
12463 }
12464 r.receiver = null;
12465 r.intent.setComponent(null);
12466 if (r.curApp != null) {
12467 r.curApp.curReceiver = null;
12468 }
12469 if (r.curFilter != null) {
12470 r.curFilter.receiverList.curBroadcast = null;
12471 }
12472 r.curFilter = null;
12473 r.curApp = null;
12474 r.curComponent = null;
12475 r.curReceiver = null;
12476 mPendingBroadcast = null;
12477
12478 r.resultCode = resultCode;
12479 r.resultData = resultData;
12480 r.resultExtras = resultExtras;
12481 r.resultAbort = resultAbort;
12482
12483 // We will process the next receiver right now if this is finishing
12484 // an app receiver (which is always asynchronous) or after we have
12485 // come back from calling a receiver.
12486 return state == BroadcastRecord.APP_RECEIVE
12487 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12488 }
12489
12490 public void finishReceiver(IBinder who, int resultCode, String resultData,
12491 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012492 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012493
12494 // Refuse possible leaked file descriptors
12495 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12496 throw new IllegalArgumentException("File descriptors passed in Bundle");
12497 }
12498
12499 boolean doNext;
12500
12501 final long origId = Binder.clearCallingIdentity();
12502
12503 synchronized(this) {
12504 doNext = finishReceiverLocked(
12505 who, resultCode, resultData, resultExtras, resultAbort, true);
12506 }
12507
12508 if (doNext) {
12509 processNextBroadcast(false);
12510 }
12511 trimApplications();
12512
12513 Binder.restoreCallingIdentity(origId);
12514 }
12515
12516 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12517 if (r.nextReceiver > 0) {
12518 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12519 if (curReceiver instanceof BroadcastFilter) {
12520 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012521 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012522 System.identityHashCode(r),
12523 r.intent.getAction(),
12524 r.nextReceiver - 1,
12525 System.identityHashCode(bf));
12526 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012527 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012528 System.identityHashCode(r),
12529 r.intent.getAction(),
12530 r.nextReceiver - 1,
12531 ((ResolveInfo)curReceiver).toString());
12532 }
12533 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012534 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012535 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012536 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012537 System.identityHashCode(r),
12538 r.intent.getAction(),
12539 r.nextReceiver,
12540 "NONE");
12541 }
12542 }
12543
12544 private final void broadcastTimeout() {
12545 synchronized (this) {
12546 if (mOrderedBroadcasts.size() == 0) {
12547 return;
12548 }
12549 long now = SystemClock.uptimeMillis();
12550 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012551 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012552 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012553 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012554 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012555 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012556 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012557 return;
12558 }
12559
Joe Onorato8a9b2202010-02-26 18:56:32 -080012560 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012561 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012562 r.anrCount++;
12563
12564 // Current receiver has passed its expiration date.
12565 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012566 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012567 return;
12568 }
12569
12570 ProcessRecord app = null;
12571
12572 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012573 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012574 logBroadcastReceiverDiscard(r);
12575 if (curReceiver instanceof BroadcastFilter) {
12576 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12577 if (bf.receiverList.pid != 0
12578 && bf.receiverList.pid != MY_PID) {
12579 synchronized (this.mPidsSelfLocked) {
12580 app = this.mPidsSelfLocked.get(
12581 bf.receiverList.pid);
12582 }
12583 }
12584 } else {
12585 app = r.curApp;
12586 }
12587
12588 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012589 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012590 }
12591
12592 if (mPendingBroadcast == r) {
12593 mPendingBroadcast = null;
12594 }
12595
12596 // Move on to the next receiver.
12597 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12598 r.resultExtras, r.resultAbort, true);
12599 scheduleBroadcastsLocked();
12600 }
12601 }
12602
12603 private final void processCurBroadcastLocked(BroadcastRecord r,
12604 ProcessRecord app) throws RemoteException {
12605 if (app.thread == null) {
12606 throw new RemoteException();
12607 }
12608 r.receiver = app.thread.asBinder();
12609 r.curApp = app;
12610 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012611 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012612
12613 // Tell the application to launch this receiver.
12614 r.intent.setComponent(r.curComponent);
12615
12616 boolean started = false;
12617 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012618 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012619 "Delivering to component " + r.curComponent
12620 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012621 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012622 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12623 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12624 started = true;
12625 } finally {
12626 if (!started) {
12627 r.receiver = null;
12628 r.curApp = null;
12629 app.curReceiver = null;
12630 }
12631 }
12632
12633 }
12634
12635 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012636 Intent intent, int resultCode, String data, Bundle extras,
12637 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012638 if (app != null && app.thread != null) {
12639 // If we have an app thread, do the call through that so it is
12640 // correctly ordered with other one-way calls.
12641 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012642 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012643 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012644 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012645 }
12646 }
12647
12648 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12649 BroadcastFilter filter, boolean ordered) {
12650 boolean skip = false;
12651 if (filter.requiredPermission != null) {
12652 int perm = checkComponentPermission(filter.requiredPermission,
12653 r.callingPid, r.callingUid, -1);
12654 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012655 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012656 + r.intent.toString()
12657 + " from " + r.callerPackage + " (pid="
12658 + r.callingPid + ", uid=" + r.callingUid + ")"
12659 + " requires " + filter.requiredPermission
12660 + " due to registered receiver " + filter);
12661 skip = true;
12662 }
12663 }
12664 if (r.requiredPermission != null) {
12665 int perm = checkComponentPermission(r.requiredPermission,
12666 filter.receiverList.pid, filter.receiverList.uid, -1);
12667 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012668 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012669 + r.intent.toString()
12670 + " to " + filter.receiverList.app
12671 + " (pid=" + filter.receiverList.pid
12672 + ", uid=" + filter.receiverList.uid + ")"
12673 + " requires " + r.requiredPermission
12674 + " due to sender " + r.callerPackage
12675 + " (uid " + r.callingUid + ")");
12676 skip = true;
12677 }
12678 }
12679
12680 if (!skip) {
12681 // If this is not being sent as an ordered broadcast, then we
12682 // don't want to touch the fields that keep track of the current
12683 // state of ordered broadcasts.
12684 if (ordered) {
12685 r.receiver = filter.receiverList.receiver.asBinder();
12686 r.curFilter = filter;
12687 filter.receiverList.curBroadcast = r;
12688 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012689 if (filter.receiverList.app != null) {
12690 // Bump hosting application to no longer be in background
12691 // scheduling class. Note that we can't do that if there
12692 // isn't an app... but we can only be in that case for
12693 // things that directly call the IActivityManager API, which
12694 // are already core system stuff so don't matter for this.
12695 r.curApp = filter.receiverList.app;
12696 filter.receiverList.app.curReceiver = r;
12697 updateOomAdjLocked();
12698 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012699 }
12700 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012701 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012702 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012703 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012704 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012705 }
12706 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12707 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012708 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012709 if (ordered) {
12710 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12711 }
12712 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012713 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012714 if (ordered) {
12715 r.receiver = null;
12716 r.curFilter = null;
12717 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012718 if (filter.receiverList.app != null) {
12719 filter.receiverList.app.curReceiver = null;
12720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012721 }
12722 }
12723 }
12724 }
12725
Dianne Hackborn12527f92009-11-11 17:39:50 -080012726 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12727 if (r.callingUid < 0) {
12728 // This was from a registerReceiver() call; ignore it.
12729 return;
12730 }
12731 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12732 MAX_BROADCAST_HISTORY-1);
12733 r.finishTime = SystemClock.uptimeMillis();
12734 mBroadcastHistory[0] = r;
12735 }
12736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012737 private final void processNextBroadcast(boolean fromMsg) {
12738 synchronized(this) {
12739 BroadcastRecord r;
12740
Joe Onorato8a9b2202010-02-26 18:56:32 -080012741 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012742 + mParallelBroadcasts.size() + " broadcasts, "
12743 + mOrderedBroadcasts.size() + " serialized broadcasts");
12744
12745 updateCpuStats();
12746
12747 if (fromMsg) {
12748 mBroadcastsScheduled = false;
12749 }
12750
12751 // First, deliver any non-serialized broadcasts right away.
12752 while (mParallelBroadcasts.size() > 0) {
12753 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012754 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012755 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012756 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012757 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012758 for (int i=0; i<N; i++) {
12759 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012760 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012761 "Delivering non-serialized to registered "
12762 + target + ": " + r);
12763 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12764 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012765 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012766 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012767 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012768 }
12769
12770 // Now take care of the next serialized one...
12771
12772 // If we are waiting for a process to come up to handle the next
12773 // broadcast, then do nothing at this point. Just in case, we
12774 // check that the process we're waiting for still exists.
12775 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012776 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012777 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012778 + mPendingBroadcast.curApp);
12779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012780
12781 boolean isDead;
12782 synchronized (mPidsSelfLocked) {
12783 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12784 }
12785 if (!isDead) {
12786 // It's still alive, so keep waiting
12787 return;
12788 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012789 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012790 + " died before responding to broadcast");
12791 mPendingBroadcast = null;
12792 }
12793 }
12794
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012795 boolean looped = false;
12796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012797 do {
12798 if (mOrderedBroadcasts.size() == 0) {
12799 // No more broadcasts pending, so all done!
12800 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012801 if (looped) {
12802 // If we had finished the last ordered broadcast, then
12803 // make sure all processes have correct oom and sched
12804 // adjustments.
12805 updateOomAdjLocked();
12806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012807 return;
12808 }
12809 r = mOrderedBroadcasts.get(0);
12810 boolean forceReceive = false;
12811
12812 // Ensure that even if something goes awry with the timeout
12813 // detection, we catch "hung" broadcasts here, discard them,
12814 // and continue to make progress.
12815 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12816 long now = SystemClock.uptimeMillis();
12817 if (r.dispatchTime > 0) {
12818 if ((numReceivers > 0) &&
12819 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012820 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012821 + " now=" + now
12822 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012823 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012824 + " intent=" + r.intent
12825 + " numReceivers=" + numReceivers
12826 + " nextReceiver=" + r.nextReceiver
12827 + " state=" + r.state);
12828 broadcastTimeout(); // forcibly finish this broadcast
12829 forceReceive = true;
12830 r.state = BroadcastRecord.IDLE;
12831 }
12832 }
12833
12834 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012835 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012836 "processNextBroadcast() called when not idle (state="
12837 + r.state + ")");
12838 return;
12839 }
12840
12841 if (r.receivers == null || r.nextReceiver >= numReceivers
12842 || r.resultAbort || forceReceive) {
12843 // No more receivers for this broadcast! Send the final
12844 // result if requested...
12845 if (r.resultTo != null) {
12846 try {
12847 if (DEBUG_BROADCAST) {
12848 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012849 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012850 + " seq=" + seq + " app=" + r.callerApp);
12851 }
12852 performReceive(r.callerApp, r.resultTo,
12853 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012854 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012855 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012856 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012857 }
12858 }
12859
Joe Onorato8a9b2202010-02-26 18:56:32 -080012860 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012861 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12862
Joe Onorato8a9b2202010-02-26 18:56:32 -080012863 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012864 + r);
12865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012866 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012867 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012868 mOrderedBroadcasts.remove(0);
12869 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012870 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012871 continue;
12872 }
12873 } while (r == null);
12874
12875 // Get the next receiver...
12876 int recIdx = r.nextReceiver++;
12877
12878 // Keep track of when this receiver started, and make sure there
12879 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012880 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012881 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012882 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012883
Joe Onorato8a9b2202010-02-26 18:56:32 -080012884 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012885 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012886 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012887 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012888 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012889 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012890 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012891 }
12892
12893 Object nextReceiver = r.receivers.get(recIdx);
12894 if (nextReceiver instanceof BroadcastFilter) {
12895 // Simple case: this is a registered receiver who gets
12896 // a direct call.
12897 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012898 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012899 "Delivering serialized to registered "
12900 + filter + ": " + r);
12901 deliverToRegisteredReceiver(r, filter, r.ordered);
12902 if (r.receiver == null || !r.ordered) {
12903 // The receiver has already finished, so schedule to
12904 // process the next one.
12905 r.state = BroadcastRecord.IDLE;
12906 scheduleBroadcastsLocked();
12907 }
12908 return;
12909 }
12910
12911 // Hard case: need to instantiate the receiver, possibly
12912 // starting its application process to host it.
12913
12914 ResolveInfo info =
12915 (ResolveInfo)nextReceiver;
12916
12917 boolean skip = false;
12918 int perm = checkComponentPermission(info.activityInfo.permission,
12919 r.callingPid, r.callingUid,
12920 info.activityInfo.exported
12921 ? -1 : info.activityInfo.applicationInfo.uid);
12922 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012923 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012924 + r.intent.toString()
12925 + " from " + r.callerPackage + " (pid=" + r.callingPid
12926 + ", uid=" + r.callingUid + ")"
12927 + " requires " + info.activityInfo.permission
12928 + " due to receiver " + info.activityInfo.packageName
12929 + "/" + info.activityInfo.name);
12930 skip = true;
12931 }
12932 if (r.callingUid != Process.SYSTEM_UID &&
12933 r.requiredPermission != null) {
12934 try {
12935 perm = ActivityThread.getPackageManager().
12936 checkPermission(r.requiredPermission,
12937 info.activityInfo.applicationInfo.packageName);
12938 } catch (RemoteException e) {
12939 perm = PackageManager.PERMISSION_DENIED;
12940 }
12941 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012942 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012943 + r.intent + " to "
12944 + info.activityInfo.applicationInfo.packageName
12945 + " requires " + r.requiredPermission
12946 + " due to sender " + r.callerPackage
12947 + " (uid " + r.callingUid + ")");
12948 skip = true;
12949 }
12950 }
12951 if (r.curApp != null && r.curApp.crashing) {
12952 // If the target process is crashing, just skip it.
12953 skip = true;
12954 }
12955
12956 if (skip) {
12957 r.receiver = null;
12958 r.curFilter = null;
12959 r.state = BroadcastRecord.IDLE;
12960 scheduleBroadcastsLocked();
12961 return;
12962 }
12963
12964 r.state = BroadcastRecord.APP_RECEIVE;
12965 String targetProcess = info.activityInfo.processName;
12966 r.curComponent = new ComponentName(
12967 info.activityInfo.applicationInfo.packageName,
12968 info.activityInfo.name);
12969 r.curReceiver = info.activityInfo;
12970
12971 // Is this receiver's application already running?
12972 ProcessRecord app = getProcessRecordLocked(targetProcess,
12973 info.activityInfo.applicationInfo.uid);
12974 if (app != null && app.thread != null) {
12975 try {
12976 processCurBroadcastLocked(r, app);
12977 return;
12978 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012979 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012980 + r.curComponent, e);
12981 }
12982
12983 // If a dead object exception was thrown -- fall through to
12984 // restart the application.
12985 }
12986
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012987 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012988 if ((r.curApp=startProcessLocked(targetProcess,
12989 info.activityInfo.applicationInfo, true,
12990 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012991 "broadcast", r.curComponent,
12992 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12993 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012994 // Ah, this recipient is unavailable. Finish it if necessary,
12995 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012996 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012997 + info.activityInfo.applicationInfo.packageName + "/"
12998 + info.activityInfo.applicationInfo.uid + " for broadcast "
12999 + r.intent + ": process is bad");
13000 logBroadcastReceiverDiscard(r);
13001 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13002 r.resultExtras, r.resultAbort, true);
13003 scheduleBroadcastsLocked();
13004 r.state = BroadcastRecord.IDLE;
13005 return;
13006 }
13007
13008 mPendingBroadcast = r;
13009 }
13010 }
13011
13012 // =========================================================
13013 // INSTRUMENTATION
13014 // =========================================================
13015
13016 public boolean startInstrumentation(ComponentName className,
13017 String profileFile, int flags, Bundle arguments,
13018 IInstrumentationWatcher watcher) {
13019 // Refuse possible leaked file descriptors
13020 if (arguments != null && arguments.hasFileDescriptors()) {
13021 throw new IllegalArgumentException("File descriptors passed in Bundle");
13022 }
13023
13024 synchronized(this) {
13025 InstrumentationInfo ii = null;
13026 ApplicationInfo ai = null;
13027 try {
13028 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013029 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013030 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013031 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013032 } catch (PackageManager.NameNotFoundException e) {
13033 }
13034 if (ii == null) {
13035 reportStartInstrumentationFailure(watcher, className,
13036 "Unable to find instrumentation info for: " + className);
13037 return false;
13038 }
13039 if (ai == null) {
13040 reportStartInstrumentationFailure(watcher, className,
13041 "Unable to find instrumentation target package: " + ii.targetPackage);
13042 return false;
13043 }
13044
13045 int match = mContext.getPackageManager().checkSignatures(
13046 ii.targetPackage, ii.packageName);
13047 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13048 String msg = "Permission Denial: starting instrumentation "
13049 + className + " from pid="
13050 + Binder.getCallingPid()
13051 + ", uid=" + Binder.getCallingPid()
13052 + " not allowed because package " + ii.packageName
13053 + " does not have a signature matching the target "
13054 + ii.targetPackage;
13055 reportStartInstrumentationFailure(watcher, className, msg);
13056 throw new SecurityException(msg);
13057 }
13058
13059 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013060 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013061 ProcessRecord app = addAppLocked(ai);
13062 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013063 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013064 app.instrumentationProfileFile = profileFile;
13065 app.instrumentationArguments = arguments;
13066 app.instrumentationWatcher = watcher;
13067 app.instrumentationResultClass = className;
13068 Binder.restoreCallingIdentity(origId);
13069 }
13070
13071 return true;
13072 }
13073
13074 /**
13075 * Report errors that occur while attempting to start Instrumentation. Always writes the
13076 * error to the logs, but if somebody is watching, send the report there too. This enables
13077 * the "am" command to report errors with more information.
13078 *
13079 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13080 * @param cn The component name of the instrumentation.
13081 * @param report The error report.
13082 */
13083 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13084 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013085 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013086 try {
13087 if (watcher != null) {
13088 Bundle results = new Bundle();
13089 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13090 results.putString("Error", report);
13091 watcher.instrumentationStatus(cn, -1, results);
13092 }
13093 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013094 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013095 }
13096 }
13097
13098 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13099 if (app.instrumentationWatcher != null) {
13100 try {
13101 // NOTE: IInstrumentationWatcher *must* be oneway here
13102 app.instrumentationWatcher.instrumentationFinished(
13103 app.instrumentationClass,
13104 resultCode,
13105 results);
13106 } catch (RemoteException e) {
13107 }
13108 }
13109 app.instrumentationWatcher = null;
13110 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013111 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013112 app.instrumentationProfileFile = null;
13113 app.instrumentationArguments = null;
13114
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013115 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013116 }
13117
13118 public void finishInstrumentation(IApplicationThread target,
13119 int resultCode, Bundle results) {
13120 // Refuse possible leaked file descriptors
13121 if (results != null && results.hasFileDescriptors()) {
13122 throw new IllegalArgumentException("File descriptors passed in Intent");
13123 }
13124
13125 synchronized(this) {
13126 ProcessRecord app = getRecordForAppLocked(target);
13127 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013128 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013129 return;
13130 }
13131 final long origId = Binder.clearCallingIdentity();
13132 finishInstrumentationLocked(app, resultCode, results);
13133 Binder.restoreCallingIdentity(origId);
13134 }
13135 }
13136
13137 // =========================================================
13138 // CONFIGURATION
13139 // =========================================================
13140
13141 public ConfigurationInfo getDeviceConfigurationInfo() {
13142 ConfigurationInfo config = new ConfigurationInfo();
13143 synchronized (this) {
13144 config.reqTouchScreen = mConfiguration.touchscreen;
13145 config.reqKeyboardType = mConfiguration.keyboard;
13146 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013147 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13148 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013149 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13150 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013151 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13152 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013153 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13154 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013155 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013156 }
13157 return config;
13158 }
13159
13160 public Configuration getConfiguration() {
13161 Configuration ci;
13162 synchronized(this) {
13163 ci = new Configuration(mConfiguration);
13164 }
13165 return ci;
13166 }
13167
13168 public void updateConfiguration(Configuration values) {
13169 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13170 "updateConfiguration()");
13171
13172 synchronized(this) {
13173 if (values == null && mWindowManager != null) {
13174 // sentinel: fetch the current configuration from the window manager
13175 values = mWindowManager.computeNewConfiguration();
13176 }
13177
13178 final long origId = Binder.clearCallingIdentity();
13179 updateConfigurationLocked(values, null);
13180 Binder.restoreCallingIdentity(origId);
13181 }
13182 }
13183
13184 /**
13185 * Do either or both things: (1) change the current configuration, and (2)
13186 * make sure the given activity is running with the (now) current
13187 * configuration. Returns true if the activity has been left running, or
13188 * false if <var>starting</var> is being destroyed to match the new
13189 * configuration.
13190 */
13191 public boolean updateConfigurationLocked(Configuration values,
13192 HistoryRecord starting) {
13193 int changes = 0;
13194
13195 boolean kept = true;
13196
13197 if (values != null) {
13198 Configuration newConfig = new Configuration(mConfiguration);
13199 changes = newConfig.updateFrom(values);
13200 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013201 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013202 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203 }
13204
Doug Zongker2bec3d42009-12-04 12:52:44 -080013205 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013206
13207 if (values.locale != null) {
13208 saveLocaleLocked(values.locale,
13209 !values.locale.equals(mConfiguration.locale),
13210 values.userSetLocale);
13211 }
13212
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013213 mConfigurationSeq++;
13214 if (mConfigurationSeq <= 0) {
13215 mConfigurationSeq = 1;
13216 }
13217 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013218 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013219 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013220
13221 AttributeCache ac = AttributeCache.instance();
13222 if (ac != null) {
13223 ac.updateConfiguration(mConfiguration);
13224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013225
13226 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13227 msg.obj = new Configuration(mConfiguration);
13228 mHandler.sendMessage(msg);
13229
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013230 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13231 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013232 try {
13233 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013234 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013235 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013236 app.thread.scheduleConfigurationChanged(mConfiguration);
13237 }
13238 } catch (Exception e) {
13239 }
13240 }
13241 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013242 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13243 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013244 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13245 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013246 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13247 broadcastIntentLocked(null, null,
13248 new Intent(Intent.ACTION_LOCALE_CHANGED),
13249 null, null, 0, null, null,
13250 null, false, false, MY_PID, Process.SYSTEM_UID);
13251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013252 }
13253 }
13254
13255 if (changes != 0 && starting == null) {
13256 // If the configuration changed, and the caller is not already
13257 // in the process of starting an activity, then find the top
13258 // activity to check if its configuration needs to change.
13259 starting = topRunningActivityLocked(null);
13260 }
13261
13262 if (starting != null) {
13263 kept = ensureActivityConfigurationLocked(starting, changes);
13264 if (kept) {
13265 // If this didn't result in the starting activity being
13266 // destroyed, then we need to make sure at this point that all
13267 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013268 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013269 + ", ensuring others are correct.");
13270 ensureActivitiesVisibleLocked(starting, changes);
13271 }
13272 }
13273
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013274 if (values != null && mWindowManager != null) {
13275 mWindowManager.setNewConfiguration(mConfiguration);
13276 }
13277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013278 return kept;
13279 }
13280
13281 private final boolean relaunchActivityLocked(HistoryRecord r,
13282 int changes, boolean andResume) {
13283 List<ResultInfo> results = null;
13284 List<Intent> newIntents = null;
13285 if (andResume) {
13286 results = r.results;
13287 newIntents = r.newIntents;
13288 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013289 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013290 + " with results=" + results + " newIntents=" + newIntents
13291 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013292 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13293 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013294 r.task.taskId, r.shortComponentName);
13295
13296 r.startFreezingScreenLocked(r.app, 0);
13297
13298 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013299 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013300 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013301 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013302 // Note: don't need to call pauseIfSleepingLocked() here, because
13303 // the caller will only pass in 'andResume' if this activity is
13304 // currently resumed, which implies we aren't sleeping.
13305 } catch (RemoteException e) {
13306 return false;
13307 }
13308
13309 if (andResume) {
13310 r.results = null;
13311 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013312 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013313 }
13314
13315 return true;
13316 }
13317
13318 /**
13319 * Make sure the given activity matches the current configuration. Returns
13320 * false if the activity had to be destroyed. Returns true if the
13321 * configuration is the same, or the activity will remain running as-is
13322 * for whatever reason. Ensures the HistoryRecord is updated with the
13323 * correct configuration and all other bookkeeping is handled.
13324 */
13325 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13326 int globalChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013327 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013328 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013329
13330 // Short circuit: if the two configurations are the exact same
13331 // object (the common case), then there is nothing to do.
13332 Configuration newConfig = mConfiguration;
13333 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013334 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013335 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013336 return true;
13337 }
13338
13339 // We don't worry about activities that are finishing.
13340 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013341 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013342 "Configuration doesn't matter in finishing " + r);
13343 r.stopFreezingScreenLocked(false);
13344 return true;
13345 }
13346
13347 // Okay we now are going to make this activity have the new config.
13348 // But then we need to figure out how it needs to deal with that.
13349 Configuration oldConfig = r.configuration;
13350 r.configuration = newConfig;
13351
13352 // If the activity isn't currently running, just leave the new
13353 // configuration and it will pick that up next time it starts.
13354 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013355 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013356 "Configuration doesn't matter not running " + r);
13357 r.stopFreezingScreenLocked(false);
13358 return true;
13359 }
13360
13361 // If the activity isn't persistent, there is a chance we will
13362 // need to restart it.
13363 if (!r.persistent) {
13364
13365 // Figure out what has changed between the two configurations.
13366 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013367 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013368 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013369 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013370 + Integer.toHexString(r.info.configChanges)
13371 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013372 }
13373 if ((changes&(~r.info.configChanges)) != 0) {
13374 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13375 r.configChangeFlags |= changes;
13376 r.startFreezingScreenLocked(r.app, globalChanges);
13377 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013378 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013379 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013380 destroyActivityLocked(r, true);
13381 } else if (r.state == ActivityState.PAUSING) {
13382 // A little annoying: we are waiting for this activity to
13383 // finish pausing. Let's not do anything now, but just
13384 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013385 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013386 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013387 r.configDestroy = true;
13388 return true;
13389 } else if (r.state == ActivityState.RESUMED) {
13390 // Try to optimize this case: the configuration is changing
13391 // and we need to restart the top, resumed activity.
13392 // Instead of doing the normal handshaking, just say
13393 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013394 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013395 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013396 relaunchActivityLocked(r, r.configChangeFlags, true);
13397 r.configChangeFlags = 0;
13398 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013399 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013400 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013401 relaunchActivityLocked(r, r.configChangeFlags, false);
13402 r.configChangeFlags = 0;
13403 }
13404
13405 // All done... tell the caller we weren't able to keep this
13406 // activity around.
13407 return false;
13408 }
13409 }
13410
13411 // Default case: the activity can handle this new configuration, so
13412 // hand it over. Note that we don't need to give it the new
13413 // configuration, since we always send configuration changes to all
13414 // process when they happen so it can just use whatever configuration
13415 // it last got.
13416 if (r.app != null && r.app.thread != null) {
13417 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013418 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013419 r.app.thread.scheduleActivityConfigurationChanged(r);
13420 } catch (RemoteException e) {
13421 // If process died, whatever.
13422 }
13423 }
13424 r.stopFreezingScreenLocked(false);
13425
13426 return true;
13427 }
13428
13429 /**
13430 * Save the locale. You must be inside a synchronized (this) block.
13431 */
13432 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13433 if(isDiff) {
13434 SystemProperties.set("user.language", l.getLanguage());
13435 SystemProperties.set("user.region", l.getCountry());
13436 }
13437
13438 if(isPersist) {
13439 SystemProperties.set("persist.sys.language", l.getLanguage());
13440 SystemProperties.set("persist.sys.country", l.getCountry());
13441 SystemProperties.set("persist.sys.localevar", l.getVariant());
13442 }
13443 }
13444
13445 // =========================================================
13446 // LIFETIME MANAGEMENT
13447 // =========================================================
13448
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013449 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13450 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013451 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013452 // This adjustment has already been computed. If we are calling
13453 // from the top, we may have already computed our adjustment with
13454 // an earlier hidden adjustment that isn't really for us... if
13455 // so, use the new hidden adjustment.
13456 if (!recursed && app.hidden) {
13457 app.curAdj = hiddenAdj;
13458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013459 return app.curAdj;
13460 }
13461
13462 if (app.thread == null) {
13463 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013464 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013465 return (app.curAdj=EMPTY_APP_ADJ);
13466 }
13467
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013468 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13469 // The max adjustment doesn't allow this app to be anything
13470 // below foreground, so it is not worth doing work for it.
13471 app.adjType = "fixed";
13472 app.adjSeq = mAdjSeq;
13473 app.curRawAdj = app.maxAdj;
13474 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13475 return (app.curAdj=app.maxAdj);
13476 }
13477
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013478 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013479 app.adjSource = null;
13480 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013481 app.empty = false;
13482 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013483
The Android Open Source Project4df24232009-03-05 14:34:35 -080013484 // Determine the importance of the process, starting with most
13485 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013486 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013487 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013488 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013489 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013490 // The last app on the list is the foreground app.
13491 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013492 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013493 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013494 } else if (app.instrumentationClass != null) {
13495 // Don't want to kill running instrumentation.
13496 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013497 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013498 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013499 } else if (app.persistentActivities > 0) {
13500 // Special persistent activities... shouldn't be used these days.
13501 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013502 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013503 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013504 } else if (app.curReceiver != null ||
13505 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13506 // An app that is currently receiving a broadcast also
13507 // counts as being in the foreground.
13508 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013509 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013510 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013511 } else if (app.executingServices.size() > 0) {
13512 // An app that is currently executing a service callback also
13513 // counts as being in the foreground.
13514 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013515 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013516 app.adjType = "exec-service";
13517 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013518 // The user is aware of this app, so make it visible.
13519 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013520 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013521 app.adjType = "foreground-service";
13522 } else if (app.forcingToForeground != null) {
13523 // The user is aware of this app, so make it visible.
13524 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013525 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013526 app.adjType = "force-foreground";
13527 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013528 } else if (app == mHomeProcess) {
13529 // This process is hosting what we currently consider to be the
13530 // home app, so we don't want to let it go into the background.
13531 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013532 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013533 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013534 } else if ((N=app.activities.size()) != 0) {
13535 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013536 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013537 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013538 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013539 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013540 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013541 for (int j=0; j<N; j++) {
13542 if (((HistoryRecord)app.activities.get(j)).visible) {
13543 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013544 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013545 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013546 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013547 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013548 break;
13549 }
13550 }
13551 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013552 // A very not-needed process. If this is lower in the lru list,
13553 // we will push it in to the empty bucket.
13554 app.hidden = true;
13555 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013556 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013557 adj = hiddenAdj;
13558 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013559 }
13560
Joe Onorato8a9b2202010-02-26 18:56:32 -080013561 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013562
The Android Open Source Project4df24232009-03-05 14:34:35 -080013563 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013564 // there are applications dependent on our services or providers, but
13565 // this gives us a baseline and makes sure we don't get into an
13566 // infinite recursion.
13567 app.adjSeq = mAdjSeq;
13568 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013569
Christopher Tate6fa95972009-06-05 18:43:55 -070013570 if (mBackupTarget != null && app == mBackupTarget.app) {
13571 // If possible we want to avoid killing apps while they're being backed up
13572 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013573 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013574 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013575 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013576 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013577 }
13578 }
13579
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013580 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13581 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013582 final long now = SystemClock.uptimeMillis();
13583 // This process is more important if the top activity is
13584 // bound to the service.
13585 Iterator jt = app.services.iterator();
13586 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13587 ServiceRecord s = (ServiceRecord)jt.next();
13588 if (s.startRequested) {
13589 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13590 // This service has seen some activity within
13591 // recent memory, so we will keep its process ahead
13592 // of the background processes.
13593 if (adj > SECONDARY_SERVER_ADJ) {
13594 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013595 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013596 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013597 }
13598 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013599 // If we have let the service slide into the background
13600 // state, still have some text describing what it is doing
13601 // even though the service no longer has an impact.
13602 if (adj > SECONDARY_SERVER_ADJ) {
13603 app.adjType = "started-bg-services";
13604 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013605 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013606 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13607 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013608 Iterator<ConnectionRecord> kt
13609 = s.connections.values().iterator();
13610 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13611 // XXX should compute this based on the max of
13612 // all connected clients.
13613 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013614 if (cr.binding.client == app) {
13615 // Binding to ourself is not interesting.
13616 continue;
13617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013618 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13619 ProcessRecord client = cr.binding.client;
13620 int myHiddenAdj = hiddenAdj;
13621 if (myHiddenAdj > client.hiddenAdj) {
13622 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13623 myHiddenAdj = client.hiddenAdj;
13624 } else {
13625 myHiddenAdj = VISIBLE_APP_ADJ;
13626 }
13627 }
13628 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013629 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013630 if (adj > clientAdj) {
13631 adj = clientAdj > VISIBLE_APP_ADJ
13632 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013633 if (!client.hidden) {
13634 app.hidden = false;
13635 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013636 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013637 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13638 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013639 app.adjSource = cr.binding.client;
13640 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013641 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013642 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13643 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13644 schedGroup = Process.THREAD_GROUP_DEFAULT;
13645 }
13646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013647 }
13648 HistoryRecord a = cr.activity;
13649 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013650 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013651 //}
13652 if (a != null && adj > FOREGROUND_APP_ADJ &&
13653 (a.state == ActivityState.RESUMED
13654 || a.state == ActivityState.PAUSING)) {
13655 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013656 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013657 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013658 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013659 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13660 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013661 app.adjSource = a;
13662 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013663 }
13664 }
13665 }
13666 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013667
13668 // Finally, f this process has active services running in it, we
13669 // would like to avoid killing it unless it would prevent the current
13670 // application from running. By default we put the process in
13671 // with the rest of the background processes; as we scan through
13672 // its services we may bump it up from there.
13673 if (adj > hiddenAdj) {
13674 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013675 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013676 app.adjType = "bg-services";
13677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013678 }
13679
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013680 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13681 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013682 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013683 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13684 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013685 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13686 if (cpr.clients.size() != 0) {
13687 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13688 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13689 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013690 if (client == app) {
13691 // Being our own client is not interesting.
13692 continue;
13693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013694 int myHiddenAdj = hiddenAdj;
13695 if (myHiddenAdj > client.hiddenAdj) {
13696 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13697 myHiddenAdj = client.hiddenAdj;
13698 } else {
13699 myHiddenAdj = FOREGROUND_APP_ADJ;
13700 }
13701 }
13702 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013703 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013704 if (adj > clientAdj) {
13705 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013706 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013707 if (!client.hidden) {
13708 app.hidden = false;
13709 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013710 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013711 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13712 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013713 app.adjSource = client;
13714 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013715 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013716 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13717 schedGroup = Process.THREAD_GROUP_DEFAULT;
13718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013719 }
13720 }
13721 // If the provider has external (non-framework) process
13722 // dependencies, ensure that its adjustment is at least
13723 // FOREGROUND_APP_ADJ.
13724 if (cpr.externals != 0) {
13725 if (adj > FOREGROUND_APP_ADJ) {
13726 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013727 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013728 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013729 app.adjType = "provider";
13730 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013731 }
13732 }
13733 }
13734 }
13735
13736 app.curRawAdj = adj;
13737
Joe Onorato8a9b2202010-02-26 18:56:32 -080013738 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013739 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13740 if (adj > app.maxAdj) {
13741 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013742 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13743 schedGroup = Process.THREAD_GROUP_DEFAULT;
13744 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013745 }
13746
13747 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013748 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013750 return adj;
13751 }
13752
13753 /**
13754 * Ask a given process to GC right now.
13755 */
13756 final void performAppGcLocked(ProcessRecord app) {
13757 try {
13758 app.lastRequestedGc = SystemClock.uptimeMillis();
13759 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013760 if (app.reportLowMemory) {
13761 app.reportLowMemory = false;
13762 app.thread.scheduleLowMemory();
13763 } else {
13764 app.thread.processInBackground();
13765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013766 }
13767 } catch (Exception e) {
13768 // whatever.
13769 }
13770 }
13771
13772 /**
13773 * Returns true if things are idle enough to perform GCs.
13774 */
13775 private final boolean canGcNow() {
13776 return mParallelBroadcasts.size() == 0
13777 && mOrderedBroadcasts.size() == 0
13778 && (mSleeping || (mResumedActivity != null &&
13779 mResumedActivity.idle));
13780 }
13781
13782 /**
13783 * Perform GCs on all processes that are waiting for it, but only
13784 * if things are idle.
13785 */
13786 final void performAppGcsLocked() {
13787 final int N = mProcessesToGc.size();
13788 if (N <= 0) {
13789 return;
13790 }
13791 if (canGcNow()) {
13792 while (mProcessesToGc.size() > 0) {
13793 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013794 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13795 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13796 <= SystemClock.uptimeMillis()) {
13797 // To avoid spamming the system, we will GC processes one
13798 // at a time, waiting a few seconds between each.
13799 performAppGcLocked(proc);
13800 scheduleAppGcsLocked();
13801 return;
13802 } else {
13803 // It hasn't been long enough since we last GCed this
13804 // process... put it in the list to wait for its time.
13805 addProcessToGcListLocked(proc);
13806 break;
13807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013808 }
13809 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013810
13811 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013812 }
13813 }
13814
13815 /**
13816 * If all looks good, perform GCs on all processes waiting for them.
13817 */
13818 final void performAppGcsIfAppropriateLocked() {
13819 if (canGcNow()) {
13820 performAppGcsLocked();
13821 return;
13822 }
13823 // Still not idle, wait some more.
13824 scheduleAppGcsLocked();
13825 }
13826
13827 /**
13828 * Schedule the execution of all pending app GCs.
13829 */
13830 final void scheduleAppGcsLocked() {
13831 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013832
13833 if (mProcessesToGc.size() > 0) {
13834 // Schedule a GC for the time to the next process.
13835 ProcessRecord proc = mProcessesToGc.get(0);
13836 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13837
13838 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13839 long now = SystemClock.uptimeMillis();
13840 if (when < (now+GC_TIMEOUT)) {
13841 when = now + GC_TIMEOUT;
13842 }
13843 mHandler.sendMessageAtTime(msg, when);
13844 }
13845 }
13846
13847 /**
13848 * Add a process to the array of processes waiting to be GCed. Keeps the
13849 * list in sorted order by the last GC time. The process can't already be
13850 * on the list.
13851 */
13852 final void addProcessToGcListLocked(ProcessRecord proc) {
13853 boolean added = false;
13854 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13855 if (mProcessesToGc.get(i).lastRequestedGc <
13856 proc.lastRequestedGc) {
13857 added = true;
13858 mProcessesToGc.add(i+1, proc);
13859 break;
13860 }
13861 }
13862 if (!added) {
13863 mProcessesToGc.add(0, proc);
13864 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013865 }
13866
13867 /**
13868 * Set up to ask a process to GC itself. This will either do it
13869 * immediately, or put it on the list of processes to gc the next
13870 * time things are idle.
13871 */
13872 final void scheduleAppGcLocked(ProcessRecord app) {
13873 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013874 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013875 return;
13876 }
13877 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013878 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013879 scheduleAppGcsLocked();
13880 }
13881 }
13882
13883 private final boolean updateOomAdjLocked(
13884 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13885 app.hiddenAdj = hiddenAdj;
13886
13887 if (app.thread == null) {
13888 return true;
13889 }
13890
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013891 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013892
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013893 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013894 if (app.curRawAdj != app.setRawAdj) {
13895 if (app.curRawAdj > FOREGROUND_APP_ADJ
13896 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13897 // If this app is transitioning from foreground to
13898 // non-foreground, have it do a gc.
13899 scheduleAppGcLocked(app);
13900 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13901 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13902 // Likewise do a gc when an app is moving in to the
13903 // background (such as a service stopping).
13904 scheduleAppGcLocked(app);
13905 }
13906 app.setRawAdj = app.curRawAdj;
13907 }
13908 if (adj != app.setAdj) {
13909 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013910 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013911 TAG, "Set app " + app.processName +
13912 " oom adj to " + adj);
13913 app.setAdj = adj;
13914 } else {
13915 return false;
13916 }
13917 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013918 if (app.setSchedGroup != app.curSchedGroup) {
13919 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013920 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013921 "Setting process group of " + app.processName
13922 + " to " + app.curSchedGroup);
13923 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013924 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013925 try {
13926 Process.setProcessGroup(app.pid, app.curSchedGroup);
13927 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013928 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013929 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013930 e.printStackTrace();
13931 } finally {
13932 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013933 }
13934 }
13935 if (false) {
13936 if (app.thread != null) {
13937 try {
13938 app.thread.setSchedulingGroup(app.curSchedGroup);
13939 } catch (RemoteException e) {
13940 }
13941 }
13942 }
13943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013944 }
13945
13946 return true;
13947 }
13948
13949 private final HistoryRecord resumedAppLocked() {
13950 HistoryRecord resumedActivity = mResumedActivity;
13951 if (resumedActivity == null || resumedActivity.app == null) {
13952 resumedActivity = mPausingActivity;
13953 if (resumedActivity == null || resumedActivity.app == null) {
13954 resumedActivity = topRunningActivityLocked(null);
13955 }
13956 }
13957 return resumedActivity;
13958 }
13959
13960 private final boolean updateOomAdjLocked(ProcessRecord app) {
13961 final HistoryRecord TOP_ACT = resumedAppLocked();
13962 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13963 int curAdj = app.curAdj;
13964 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13965 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13966
13967 mAdjSeq++;
13968
13969 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13970 if (res) {
13971 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13972 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13973 if (nowHidden != wasHidden) {
13974 // Changed to/from hidden state, so apps after it in the LRU
13975 // list may also be changed.
13976 updateOomAdjLocked();
13977 }
13978 }
13979 return res;
13980 }
13981
13982 private final boolean updateOomAdjLocked() {
13983 boolean didOomAdj = true;
13984 final HistoryRecord TOP_ACT = resumedAppLocked();
13985 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13986
13987 if (false) {
13988 RuntimeException e = new RuntimeException();
13989 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013990 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013991 }
13992
13993 mAdjSeq++;
13994
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013995 // Let's determine how many processes we have running vs.
13996 // how many slots we have for background processes; we may want
13997 // to put multiple processes in a slot of there are enough of
13998 // them.
13999 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14000 int factor = (mLruProcesses.size()-4)/numSlots;
14001 if (factor < 1) factor = 1;
14002 int step = 0;
14003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014004 // First try updating the OOM adjustment for each of the
14005 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014006 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014007 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14008 while (i > 0) {
14009 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014010 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014011 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014012 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014013 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014014 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014015 step++;
14016 if (step >= factor) {
14017 step = 0;
14018 curHiddenAdj++;
14019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014020 }
14021 } else {
14022 didOomAdj = false;
14023 }
14024 }
14025
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014026 // If we return false, we will fall back on killing processes to
14027 // have a fixed limit. Do this if a limit has been requested; else
14028 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014029 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14030 }
14031
14032 private final void trimApplications() {
14033 synchronized (this) {
14034 int i;
14035
14036 // First remove any unused application processes whose package
14037 // has been removed.
14038 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14039 final ProcessRecord app = mRemovedProcesses.get(i);
14040 if (app.activities.size() == 0
14041 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014042 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014043 TAG, "Exiting empty application process "
14044 + app.processName + " ("
14045 + (app.thread != null ? app.thread.asBinder() : null)
14046 + ")\n");
14047 if (app.pid > 0 && app.pid != MY_PID) {
14048 Process.killProcess(app.pid);
14049 } else {
14050 try {
14051 app.thread.scheduleExit();
14052 } catch (Exception e) {
14053 // Ignore exceptions.
14054 }
14055 }
14056 cleanUpApplicationRecordLocked(app, false, -1);
14057 mRemovedProcesses.remove(i);
14058
14059 if (app.persistent) {
14060 if (app.persistent) {
14061 addAppLocked(app.info);
14062 }
14063 }
14064 }
14065 }
14066
14067 // Now try updating the OOM adjustment for each of the
14068 // application processes based on their current state.
14069 // If the setOomAdj() API is not supported, then go with our
14070 // back-up plan...
14071 if (!updateOomAdjLocked()) {
14072
14073 // Count how many processes are running services.
14074 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014075 for (i=mLruProcesses.size()-1; i>=0; i--) {
14076 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014077
14078 if (app.persistent || app.services.size() != 0
14079 || app.curReceiver != null
14080 || app.persistentActivities > 0) {
14081 // Don't count processes holding services against our
14082 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014083 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014084 TAG, "Not trimming app " + app + " with services: "
14085 + app.services);
14086 numServiceProcs++;
14087 }
14088 }
14089
14090 int curMaxProcs = mProcessLimit;
14091 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14092 if (mAlwaysFinishActivities) {
14093 curMaxProcs = 1;
14094 }
14095 curMaxProcs += numServiceProcs;
14096
14097 // Quit as many processes as we can to get down to the desired
14098 // process count. First remove any processes that no longer
14099 // have activites running in them.
14100 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014101 i<mLruProcesses.size()
14102 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014103 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014104 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014105 // Quit an application only if it is not currently
14106 // running any activities.
14107 if (!app.persistent && app.activities.size() == 0
14108 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014109 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014110 TAG, "Exiting empty application process "
14111 + app.processName + " ("
14112 + (app.thread != null ? app.thread.asBinder() : null)
14113 + ")\n");
14114 if (app.pid > 0 && app.pid != MY_PID) {
14115 Process.killProcess(app.pid);
14116 } else {
14117 try {
14118 app.thread.scheduleExit();
14119 } catch (Exception e) {
14120 // Ignore exceptions.
14121 }
14122 }
14123 // todo: For now we assume the application is not buggy
14124 // or evil, and will quit as a result of our request.
14125 // Eventually we need to drive this off of the death
14126 // notification, and kill the process if it takes too long.
14127 cleanUpApplicationRecordLocked(app, false, i);
14128 i--;
14129 }
14130 }
14131
14132 // If we still have too many processes, now from the least
14133 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014134 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014135 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014136 " of " + curMaxProcs + " processes");
14137 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014138 i<mLruProcesses.size()
14139 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014140 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014141 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014142 // Quit the application only if we have a state saved for
14143 // all of its activities.
14144 boolean canQuit = !app.persistent && app.curReceiver == null
14145 && app.services.size() == 0
14146 && app.persistentActivities == 0;
14147 int NUMA = app.activities.size();
14148 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014149 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014150 TAG, "Looking to quit " + app.processName);
14151 for (j=0; j<NUMA && canQuit; j++) {
14152 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014153 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014154 TAG, " " + r.intent.getComponent().flattenToShortString()
14155 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14156 canQuit = (r.haveState || !r.stateNotNeeded)
14157 && !r.visible && r.stopped;
14158 }
14159 if (canQuit) {
14160 // Finish all of the activities, and then the app itself.
14161 for (j=0; j<NUMA; j++) {
14162 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14163 if (!r.finishing) {
14164 destroyActivityLocked(r, false);
14165 }
14166 r.resultTo = null;
14167 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014168 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014169 + app.processName + " ("
14170 + (app.thread != null ? app.thread.asBinder() : null)
14171 + ")\n");
14172 if (app.pid > 0 && app.pid != MY_PID) {
14173 Process.killProcess(app.pid);
14174 } else {
14175 try {
14176 app.thread.scheduleExit();
14177 } catch (Exception e) {
14178 // Ignore exceptions.
14179 }
14180 }
14181 // todo: For now we assume the application is not buggy
14182 // or evil, and will quit as a result of our request.
14183 // Eventually we need to drive this off of the death
14184 // notification, and kill the process if it takes too long.
14185 cleanUpApplicationRecordLocked(app, false, i);
14186 i--;
14187 //dump();
14188 }
14189 }
14190
14191 }
14192
14193 int curMaxActivities = MAX_ACTIVITIES;
14194 if (mAlwaysFinishActivities) {
14195 curMaxActivities = 1;
14196 }
14197
14198 // Finally, if there are too many activities now running, try to
14199 // finish as many as we can to get back down to the limit.
14200 for ( i=0;
14201 i<mLRUActivities.size()
14202 && mLRUActivities.size() > curMaxActivities;
14203 i++) {
14204 final HistoryRecord r
14205 = (HistoryRecord)mLRUActivities.get(i);
14206
14207 // We can finish this one if we have its icicle saved and
14208 // it is not persistent.
14209 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14210 && r.stopped && !r.persistent && !r.finishing) {
14211 final int origSize = mLRUActivities.size();
14212 destroyActivityLocked(r, true);
14213
14214 // This will remove it from the LRU list, so keep
14215 // our index at the same value. Note that this check to
14216 // see if the size changes is just paranoia -- if
14217 // something unexpected happens, we don't want to end up
14218 // in an infinite loop.
14219 if (origSize > mLRUActivities.size()) {
14220 i--;
14221 }
14222 }
14223 }
14224 }
14225 }
14226
14227 /** This method sends the specified signal to each of the persistent apps */
14228 public void signalPersistentProcesses(int sig) throws RemoteException {
14229 if (sig != Process.SIGNAL_USR1) {
14230 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14231 }
14232
14233 synchronized (this) {
14234 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14235 != PackageManager.PERMISSION_GRANTED) {
14236 throw new SecurityException("Requires permission "
14237 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14238 }
14239
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014240 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14241 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014242 if (r.thread != null && r.persistent) {
14243 Process.sendSignal(r.pid, sig);
14244 }
14245 }
14246 }
14247 }
14248
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014249 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014250 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014251
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014252 try {
14253 synchronized (this) {
14254 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14255 // its own permission.
14256 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14257 != PackageManager.PERMISSION_GRANTED) {
14258 throw new SecurityException("Requires permission "
14259 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014260 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014261
14262 if (start && fd == null) {
14263 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014264 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014265
14266 ProcessRecord proc = null;
14267 try {
14268 int pid = Integer.parseInt(process);
14269 synchronized (mPidsSelfLocked) {
14270 proc = mPidsSelfLocked.get(pid);
14271 }
14272 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014273 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014274
14275 if (proc == null) {
14276 HashMap<String, SparseArray<ProcessRecord>> all
14277 = mProcessNames.getMap();
14278 SparseArray<ProcessRecord> procs = all.get(process);
14279 if (procs != null && procs.size() > 0) {
14280 proc = procs.valueAt(0);
14281 }
14282 }
14283
14284 if (proc == null || proc.thread == null) {
14285 throw new IllegalArgumentException("Unknown process: " + process);
14286 }
14287
14288 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14289 if (isSecure) {
14290 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14291 throw new SecurityException("Process not debuggable: " + proc);
14292 }
14293 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014294
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014295 proc.thread.profilerControl(start, path, fd);
14296 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014297 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014298 }
14299 } catch (RemoteException e) {
14300 throw new IllegalStateException("Process disappeared");
14301 } finally {
14302 if (fd != null) {
14303 try {
14304 fd.close();
14305 } catch (IOException e) {
14306 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014307 }
14308 }
14309 }
14310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014311 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14312 public void monitor() {
14313 synchronized (this) { }
14314 }
14315}