blob: d628a3b8764401fb99a95b6465a5b34c5e4dbe93 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.util.PrintWriterPrinter;
102import android.util.SparseArray;
103import android.view.Gravity;
104import android.view.LayoutInflater;
105import android.view.View;
106import android.view.WindowManager;
107import android.view.WindowManagerPolicy;
108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import java.io.File;
110import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200112import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import java.io.PrintWriter;
114import java.lang.IllegalStateException;
115import java.lang.ref.WeakReference;
116import java.util.ArrayList;
117import java.util.HashMap;
118import java.util.HashSet;
119import java.util.Iterator;
120import java.util.List;
121import java.util.Locale;
122import java.util.Map;
123
124public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
125 static final String TAG = "ActivityManager";
126 static final boolean DEBUG = false;
127 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
128 static final boolean DEBUG_SWITCH = localLOGV || false;
129 static final boolean DEBUG_TASKS = localLOGV || false;
130 static final boolean DEBUG_PAUSE = localLOGV || false;
131 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
132 static final boolean DEBUG_TRANSITION = localLOGV || false;
133 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700134 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 static final boolean DEBUG_SERVICE = localLOGV || false;
136 static final boolean DEBUG_VISBILITY = localLOGV || false;
137 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700138 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800139 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700141 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700142 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700143 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 static final boolean VALIDATE_TOKENS = false;
145 static final boolean SHOW_ACTIVITY_START_TIME = true;
146
147 // Control over CPU and battery monitoring.
148 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
149 static final boolean MONITOR_CPU_USAGE = true;
150 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
151 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
152 static final boolean MONITOR_THREAD_CPU_USAGE = false;
153
Dianne Hackborn1655be42009-05-08 14:29:01 -0700154 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700155 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 private static final String SYSTEM_SECURE = "ro.secure";
158
159 // This is the maximum number of application processes we would like
160 // to have running. Due to the asynchronous nature of things, we can
161 // temporarily go beyond this limit.
162 static final int MAX_PROCESSES = 2;
163
164 // Set to false to leave processes running indefinitely, relying on
165 // the kernel killing them as resources are required.
166 static final boolean ENFORCE_PROCESS_LIMIT = false;
167
168 // This is the maximum number of activities that we would like to have
169 // running at a given time.
170 static final int MAX_ACTIVITIES = 20;
171
172 // Maximum number of recent tasks that we can remember.
173 static final int MAX_RECENT_TASKS = 20;
174
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700175 // Amount of time after a call to stopAppSwitches() during which we will
176 // prevent further untrusted switches from happening.
177 static final long APP_SWITCH_DELAY_TIME = 5*1000;
178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 // How long until we reset a task when the user returns to it. Currently
180 // 30 minutes.
181 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
182
183 // Set to true to disable the icon that is shown while a new activity
184 // is being started.
185 static final boolean SHOW_APP_STARTING_ICON = true;
186
187 // How long we wait until giving up on the last activity to pause. This
188 // is short because it directly impacts the responsiveness of starting the
189 // next activity.
190 static final int PAUSE_TIMEOUT = 500;
191
192 /**
193 * How long we can hold the launch wake lock before giving up.
194 */
195 static final int LAUNCH_TIMEOUT = 10*1000;
196
197 // How long we wait for a launched process to attach to the activity manager
198 // before we decide it's never going to come up for real.
199 static final int PROC_START_TIMEOUT = 10*1000;
200
201 // How long we wait until giving up on the last activity telling us it
202 // is idle.
203 static final int IDLE_TIMEOUT = 10*1000;
204
205 // How long to wait after going idle before forcing apps to GC.
206 static final int GC_TIMEOUT = 5*1000;
207
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700208 // The minimum amount of time between successive GC requests for a process.
209 static final int GC_MIN_INTERVAL = 60*1000;
210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 // How long we wait until giving up on an activity telling us it has
212 // finished destroying itself.
213 static final int DESTROY_TIMEOUT = 10*1000;
214
215 // How long we allow a receiver to run before giving up on it.
216 static final int BROADCAST_TIMEOUT = 10*1000;
217
218 // How long we wait for a service to finish executing.
219 static final int SERVICE_TIMEOUT = 20*1000;
220
221 // How long a service needs to be running until restarting its process
222 // is no longer considered to be a relaunch of the service.
223 static final int SERVICE_RESTART_DURATION = 5*1000;
224
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700225 // How long a service needs to be running until it will start back at
226 // SERVICE_RESTART_DURATION after being killed.
227 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
228
229 // Multiplying factor to increase restart duration time by, for each time
230 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
231 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
232
233 // The minimum amount of time between restarting services that we allow.
234 // That is, when multiple services are restarting, we won't allow each
235 // to restart less than this amount of time from the last one.
236 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 // Maximum amount of time for there to be no activity on a service before
239 // we consider it non-essential and allow its process to go on the
240 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700241 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242
243 // How long we wait until we timeout on key dispatching.
244 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
245
246 // The minimum time we allow between crashes, for us to consider this
247 // application to be bad and stop and its services and reject broadcasts.
248 static final int MIN_CRASH_INTERVAL = 60*1000;
249
250 // How long we wait until we timeout on key dispatching during instrumentation.
251 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
252
253 // OOM adjustments for processes in various states:
254
255 // This is a process without anything currently running in it. Definitely
256 // the first to go! Value set in system/rootdir/init.rc on startup.
257 // This value is initalized in the constructor, careful when refering to
258 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800259 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260
261 // This is a process only hosting activities that are not visible,
262 // so it can be killed without any disruption. Value set in
263 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800264 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 static int HIDDEN_APP_MIN_ADJ;
266
The Android Open Source Project4df24232009-03-05 14:34:35 -0800267 // This is a process holding the home application -- we want to try
268 // avoiding killing it, even if it would normally be in the background,
269 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800270 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800271
Christopher Tate6fa95972009-06-05 18:43:55 -0700272 // This is a process currently hosting a backup operation. Killing it
273 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800274 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 // This is a process holding a secondary server -- killing it will not
277 // have much of an impact as far as the user is concerned. Value set in
278 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800279 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280
281 // This is a process only hosting activities that are visible to the
282 // user, so we'd prefer they don't disappear. Value set in
283 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
286 // This is the process running the current foreground app. We'd really
287 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800288 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289
290 // This is a process running a core server, such as telephony. Definitely
291 // don't want to kill it, but doing so is not completely fatal.
292 static final int CORE_SERVER_ADJ = -12;
293
294 // The system process runs at the default adjustment.
295 static final int SYSTEM_ADJ = -16;
296
297 // Memory pages are 4K.
298 static final int PAGE_SIZE = 4*1024;
299
300 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800301 static final int EMPTY_APP_MEM;
302 static final int HIDDEN_APP_MEM;
303 static final int HOME_APP_MEM;
304 static final int BACKUP_APP_MEM;
305 static final int SECONDARY_SERVER_MEM;
306 static final int VISIBLE_APP_MEM;
307 static final int FOREGROUND_APP_MEM;
308
309 // The minimum number of hidden apps we want to be able to keep around,
310 // without empty apps being able to push them out of memory.
311 static final int MIN_HIDDEN_APPS = 2;
312
313 // We put empty content processes after any hidden processes that have
314 // been idle for less than 30 seconds.
315 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
316
317 // We put empty content processes after any hidden processes that have
318 // been idle for less than 60 seconds.
319 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
320
321 static {
322 // These values are set in system/rootdir/init.rc on startup.
323 FOREGROUND_APP_ADJ =
324 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
325 VISIBLE_APP_ADJ =
326 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
327 SECONDARY_SERVER_ADJ =
328 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
329 BACKUP_APP_ADJ =
330 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
331 HOME_APP_ADJ =
332 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
333 HIDDEN_APP_MIN_ADJ =
334 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
335 EMPTY_APP_ADJ =
336 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
337 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
338 FOREGROUND_APP_MEM =
339 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
340 VISIBLE_APP_MEM =
341 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
342 SECONDARY_SERVER_MEM =
343 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
344 BACKUP_APP_MEM =
345 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
346 HOME_APP_MEM =
347 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
348 HIDDEN_APP_MEM =
349 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
350 EMPTY_APP_MEM =
351 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353
Dan Egnor42471dd2010-01-07 17:25:22 -0800354 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355
356 static final String[] EMPTY_STRING_ARRAY = new String[0];
357
358 enum ActivityState {
359 INITIALIZING,
360 RESUMED,
361 PAUSING,
362 PAUSED,
363 STOPPING,
364 STOPPED,
365 FINISHING,
366 DESTROYING,
367 DESTROYED
368 }
369
370 /**
371 * The back history of all previous (and possibly still
372 * running) activities. It contains HistoryRecord objects.
373 */
374 final ArrayList mHistory = new ArrayList();
375
376 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700377 * Description of a request to start a new activity, which has been held
378 * due to app switches being disabled.
379 */
380 class PendingActivityLaunch {
381 HistoryRecord r;
382 HistoryRecord sourceRecord;
383 Uri[] grantedUriPermissions;
384 int grantedMode;
385 boolean onlyIfNeeded;
386 }
387
388 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
389 = new ArrayList<PendingActivityLaunch>();
390
391 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800392 * List of people waiting to find out about the next launched activity.
393 */
394 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
395 = new ArrayList<IActivityManager.WaitResult>();
396
397 /**
398 * List of people waiting to find out about the next visible activity.
399 */
400 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
401 = new ArrayList<IActivityManager.WaitResult>();
402
403 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 * List of all active broadcasts that are to be executed immediately
405 * (without waiting for another broadcast to finish). Currently this only
406 * contains broadcasts to registered receivers, to avoid spinning up
407 * a bunch of processes to execute IntentReceiver components.
408 */
409 final ArrayList<BroadcastRecord> mParallelBroadcasts
410 = new ArrayList<BroadcastRecord>();
411
412 /**
413 * List of all active broadcasts that are to be executed one at a time.
414 * The object at the top of the list is the currently activity broadcasts;
415 * those after it are waiting for the top to finish..
416 */
417 final ArrayList<BroadcastRecord> mOrderedBroadcasts
418 = new ArrayList<BroadcastRecord>();
419
420 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800421 * Historical data of past broadcasts, for debugging.
422 */
423 static final int MAX_BROADCAST_HISTORY = 100;
424 final BroadcastRecord[] mBroadcastHistory
425 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
426
427 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 * Set when we current have a BROADCAST_INTENT_MSG in flight.
429 */
430 boolean mBroadcastsScheduled = false;
431
432 /**
433 * Set to indicate whether to issue an onUserLeaving callback when a
434 * newly launched activity is being brought in front of us.
435 */
436 boolean mUserLeaving = false;
437
438 /**
439 * When we are in the process of pausing an activity, before starting the
440 * next one, this variable holds the activity that is currently being paused.
441 */
442 HistoryRecord mPausingActivity = null;
443
444 /**
445 * Current activity that is resumed, or null if there is none.
446 */
447 HistoryRecord mResumedActivity = null;
448
449 /**
450 * Activity we have told the window manager to have key focus.
451 */
452 HistoryRecord mFocusedActivity = null;
453
454 /**
455 * This is the last activity that we put into the paused state. This is
456 * used to determine if we need to do an activity transition while sleeping,
457 * when we normally hold the top activity paused.
458 */
459 HistoryRecord mLastPausedActivity = null;
460
461 /**
462 * List of activities that are waiting for a new activity
463 * to become visible before completing whatever operation they are
464 * supposed to do.
465 */
466 final ArrayList mWaitingVisibleActivities = new ArrayList();
467
468 /**
469 * List of activities that are ready to be stopped, but waiting
470 * for the next activity to settle down before doing so. It contains
471 * HistoryRecord objects.
472 */
473 final ArrayList<HistoryRecord> mStoppingActivities
474 = new ArrayList<HistoryRecord>();
475
476 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700477 * Animations that for the current transition have requested not to
478 * be considered for the transition animation.
479 */
480 final ArrayList<HistoryRecord> mNoAnimActivities
481 = new ArrayList<HistoryRecord>();
482
483 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 * List of intents that were used to start the most recent tasks.
485 */
486 final ArrayList<TaskRecord> mRecentTasks
487 = new ArrayList<TaskRecord>();
488
489 /**
490 * List of activities that are ready to be finished, but waiting
491 * for the previous activity to settle down before doing so. It contains
492 * HistoryRecord objects.
493 */
494 final ArrayList mFinishingActivities = new ArrayList();
495
496 /**
497 * All of the applications we currently have running organized by name.
498 * The keys are strings of the application package name (as
499 * returned by the package manager), and the keys are ApplicationRecord
500 * objects.
501 */
502 final ProcessMap<ProcessRecord> mProcessNames
503 = new ProcessMap<ProcessRecord>();
504
505 /**
506 * The last time that various processes have crashed.
507 */
508 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
509
510 /**
511 * Set of applications that we consider to be bad, and will reject
512 * incoming broadcasts from (which the user has no control over).
513 * Processes are added to this set when they have crashed twice within
514 * a minimum amount of time; they are removed from it when they are
515 * later restarted (hopefully due to some user action). The value is the
516 * time it was added to the list.
517 */
518 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
519
520 /**
521 * All of the processes we currently have running organized by pid.
522 * The keys are the pid running the application.
523 *
524 * <p>NOTE: This object is protected by its own lock, NOT the global
525 * activity manager lock!
526 */
527 final SparseArray<ProcessRecord> mPidsSelfLocked
528 = new SparseArray<ProcessRecord>();
529
530 /**
531 * All of the processes that have been forced to be foreground. The key
532 * is the pid of the caller who requested it (we hold a death
533 * link on it).
534 */
535 abstract class ForegroundToken implements IBinder.DeathRecipient {
536 int pid;
537 IBinder token;
538 }
539 final SparseArray<ForegroundToken> mForegroundProcesses
540 = new SparseArray<ForegroundToken>();
541
542 /**
543 * List of records for processes that someone had tried to start before the
544 * system was ready. We don't start them at that point, but ensure they
545 * are started by the time booting is complete.
546 */
547 final ArrayList<ProcessRecord> mProcessesOnHold
548 = new ArrayList<ProcessRecord>();
549
550 /**
551 * List of records for processes that we have started and are waiting
552 * for them to call back. This is really only needed when running in
553 * single processes mode, in which case we do not have a unique pid for
554 * each process.
555 */
556 final ArrayList<ProcessRecord> mStartingProcesses
557 = new ArrayList<ProcessRecord>();
558
559 /**
560 * List of persistent applications that are in the process
561 * of being started.
562 */
563 final ArrayList<ProcessRecord> mPersistentStartingProcesses
564 = new ArrayList<ProcessRecord>();
565
566 /**
567 * Processes that are being forcibly torn down.
568 */
569 final ArrayList<ProcessRecord> mRemovedProcesses
570 = new ArrayList<ProcessRecord>();
571
572 /**
573 * List of running applications, sorted by recent usage.
574 * The first entry in the list is the least recently used.
575 * It contains ApplicationRecord objects. This list does NOT include
576 * any persistent application records (since we never want to exit them).
577 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800578 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 = new ArrayList<ProcessRecord>();
580
581 /**
582 * List of processes that should gc as soon as things are idle.
583 */
584 final ArrayList<ProcessRecord> mProcessesToGc
585 = new ArrayList<ProcessRecord>();
586
587 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800588 * This is the process holding what we currently consider to be
589 * the "home" activity.
590 */
591 private ProcessRecord mHomeProcess;
592
593 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 * List of running activities, sorted by recent usage.
595 * The first entry in the list is the least recently used.
596 * It contains HistoryRecord objects.
597 */
598 private final ArrayList mLRUActivities = new ArrayList();
599
600 /**
601 * Set of PendingResultRecord objects that are currently active.
602 */
603 final HashSet mPendingResultRecords = new HashSet();
604
605 /**
606 * Set of IntentSenderRecord objects that are currently active.
607 */
608 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
609 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
610
611 /**
612 * Intent broadcast that we have tried to start, but are
613 * waiting for its application's process to be created. We only
614 * need one (instead of a list) because we always process broadcasts
615 * one at a time, so no others can be started while waiting for this
616 * one.
617 */
618 BroadcastRecord mPendingBroadcast = null;
619
620 /**
621 * Keeps track of all IIntentReceivers that have been registered for
622 * broadcasts. Hash keys are the receiver IBinder, hash value is
623 * a ReceiverList.
624 */
625 final HashMap mRegisteredReceivers = new HashMap();
626
627 /**
628 * Resolver for broadcast intents to registered receivers.
629 * Holds BroadcastFilter (subclass of IntentFilter).
630 */
631 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
632 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
633 @Override
634 protected boolean allowFilterResult(
635 BroadcastFilter filter, List<BroadcastFilter> dest) {
636 IBinder target = filter.receiverList.receiver.asBinder();
637 for (int i=dest.size()-1; i>=0; i--) {
638 if (dest.get(i).receiverList.receiver.asBinder() == target) {
639 return false;
640 }
641 }
642 return true;
643 }
644 };
645
646 /**
647 * State of all active sticky broadcasts. Keys are the action of the
648 * sticky Intent, values are an ArrayList of all broadcasted intents with
649 * that action (which should usually be one).
650 */
651 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
652 new HashMap<String, ArrayList<Intent>>();
653
654 /**
655 * All currently running services.
656 */
657 final HashMap<ComponentName, ServiceRecord> mServices =
658 new HashMap<ComponentName, ServiceRecord>();
659
660 /**
661 * All currently running services indexed by the Intent used to start them.
662 */
663 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
664 new HashMap<Intent.FilterComparison, ServiceRecord>();
665
666 /**
667 * All currently bound service connections. Keys are the IBinder of
668 * the client's IServiceConnection.
669 */
670 final HashMap<IBinder, ConnectionRecord> mServiceConnections
671 = new HashMap<IBinder, ConnectionRecord>();
672
673 /**
674 * List of services that we have been asked to start,
675 * but haven't yet been able to. It is used to hold start requests
676 * while waiting for their corresponding application thread to get
677 * going.
678 */
679 final ArrayList<ServiceRecord> mPendingServices
680 = new ArrayList<ServiceRecord>();
681
682 /**
683 * List of services that are scheduled to restart following a crash.
684 */
685 final ArrayList<ServiceRecord> mRestartingServices
686 = new ArrayList<ServiceRecord>();
687
688 /**
689 * List of services that are in the process of being stopped.
690 */
691 final ArrayList<ServiceRecord> mStoppingServices
692 = new ArrayList<ServiceRecord>();
693
694 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700695 * Backup/restore process management
696 */
697 String mBackupAppName = null;
698 BackupRecord mBackupTarget = null;
699
700 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 * List of PendingThumbnailsRecord objects of clients who are still
702 * waiting to receive all of the thumbnails for a task.
703 */
704 final ArrayList mPendingThumbnails = new ArrayList();
705
706 /**
707 * List of HistoryRecord objects that have been finished and must
708 * still report back to a pending thumbnail receiver.
709 */
710 final ArrayList mCancelledThumbnails = new ArrayList();
711
712 /**
713 * All of the currently running global content providers. Keys are a
714 * string containing the provider name and values are a
715 * ContentProviderRecord object containing the data about it. Note
716 * that a single provider may be published under multiple names, so
717 * there may be multiple entries here for a single one in mProvidersByClass.
718 */
719 final HashMap mProvidersByName = new HashMap();
720
721 /**
722 * All of the currently running global content providers. Keys are a
723 * string containing the provider's implementation class and values are a
724 * ContentProviderRecord object containing the data about it.
725 */
726 final HashMap mProvidersByClass = new HashMap();
727
728 /**
729 * List of content providers who have clients waiting for them. The
730 * application is currently being launched and the provider will be
731 * removed from this list once it is published.
732 */
733 final ArrayList mLaunchingProviders = new ArrayList();
734
735 /**
736 * Global set of specific Uri permissions that have been granted.
737 */
738 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
739 = new SparseArray<HashMap<Uri, UriPermission>>();
740
741 /**
742 * Thread-local storage used to carry caller permissions over through
743 * indirect content-provider access.
744 * @see #ActivityManagerService.openContentUri()
745 */
746 private class Identity {
747 public int pid;
748 public int uid;
749
750 Identity(int _pid, int _uid) {
751 pid = _pid;
752 uid = _uid;
753 }
754 }
755 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
756
757 /**
758 * All information we have collected about the runtime performance of
759 * any user id that can impact battery performance.
760 */
761 final BatteryStatsService mBatteryStatsService;
762
763 /**
764 * information about component usage
765 */
766 final UsageStatsService mUsageStatsService;
767
768 /**
769 * Current configuration information. HistoryRecord objects are given
770 * a reference to this object to indicate which configuration they are
771 * currently running in, so this object must be kept immutable.
772 */
773 Configuration mConfiguration = new Configuration();
774
775 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800776 * Current sequencing integer of the configuration, for skipping old
777 * configurations.
778 */
779 int mConfigurationSeq = 0;
780
781 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700782 * Hardware-reported OpenGLES version.
783 */
784 final int GL_ES_VERSION;
785
786 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 * List of initialization arguments to pass to all processes when binding applications to them.
788 * For example, references to the commonly used services.
789 */
790 HashMap<String, IBinder> mAppBindArgs;
791
792 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700793 * Temporary to avoid allocations. Protected by main lock.
794 */
795 final StringBuilder mStringBuilder = new StringBuilder(256);
796
797 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 * Used to control how we initialize the service.
799 */
800 boolean mStartRunning = false;
801 ComponentName mTopComponent;
802 String mTopAction;
803 String mTopData;
804 boolean mSystemReady = false;
805 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700806 boolean mWaitingUpdate = false;
807 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808
809 Context mContext;
810
811 int mFactoryTest;
812
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700813 boolean mCheckedForSetup;
814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700816 * The time at which we will allow normal application switches again,
817 * after a call to {@link #stopAppSwitches()}.
818 */
819 long mAppSwitchesAllowedTime;
820
821 /**
822 * This is set to true after the first switch after mAppSwitchesAllowedTime
823 * is set; any switches after that will clear the time.
824 */
825 boolean mDidAppSwitch;
826
827 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 * Set while we are wanting to sleep, to prevent any
829 * activities from being started/resumed.
830 */
831 boolean mSleeping = false;
832
833 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700834 * Set if we are shutting down the system, similar to sleeping.
835 */
836 boolean mShuttingDown = false;
837
838 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 * Set when the system is going to sleep, until we have
840 * successfully paused the current activity and released our wake lock.
841 * At that point the system is allowed to actually sleep.
842 */
843 PowerManager.WakeLock mGoingToSleep;
844
845 /**
846 * We don't want to allow the device to go to sleep while in the process
847 * of launching an activity. This is primarily to allow alarm intent
848 * receivers to launch an activity and get that to run before the device
849 * goes back to sleep.
850 */
851 PowerManager.WakeLock mLaunchingActivity;
852
853 /**
854 * Task identifier that activities are currently being started
855 * in. Incremented each time a new task is created.
856 * todo: Replace this with a TokenSpace class that generates non-repeating
857 * integers that won't wrap.
858 */
859 int mCurTask = 1;
860
861 /**
862 * Current sequence id for oom_adj computation traversal.
863 */
864 int mAdjSeq = 0;
865
866 /**
867 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
868 * is set, indicating the user wants processes started in such a way
869 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
870 * running in each process (thus no pre-initialized process, etc).
871 */
872 boolean mSimpleProcessManagement = false;
873
874 /**
875 * System monitoring: number of processes that died since the last
876 * N procs were started.
877 */
878 int[] mProcDeaths = new int[20];
879
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700880 /**
881 * This is set if we had to do a delayed dexopt of an app before launching
882 * it, to increasing the ANR timeouts in that case.
883 */
884 boolean mDidDexOpt;
885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 String mDebugApp = null;
887 boolean mWaitForDebugger = false;
888 boolean mDebugTransient = false;
889 String mOrigDebugApp = null;
890 boolean mOrigWaitForDebugger = false;
891 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700892 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700894 final RemoteCallbackList<IActivityWatcher> mWatchers
895 = new RemoteCallbackList<IActivityWatcher>();
896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 /**
898 * Callback of last caller to {@link #requestPss}.
899 */
900 Runnable mRequestPssCallback;
901
902 /**
903 * Remaining processes for which we are waiting results from the last
904 * call to {@link #requestPss}.
905 */
906 final ArrayList<ProcessRecord> mRequestPssList
907 = new ArrayList<ProcessRecord>();
908
909 /**
910 * Runtime statistics collection thread. This object's lock is used to
911 * protect all related state.
912 */
913 final Thread mProcessStatsThread;
914
915 /**
916 * Used to collect process stats when showing not responding dialog.
917 * Protected by mProcessStatsThread.
918 */
919 final ProcessStats mProcessStats = new ProcessStats(
920 MONITOR_THREAD_CPU_USAGE);
921 long mLastCpuTime = 0;
922 long mLastWriteTime = 0;
923
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700924 long mInitialStartTime = 0;
925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 /**
927 * Set to true after the system has finished booting.
928 */
929 boolean mBooted = false;
930
931 int mProcessLimit = 0;
932
933 WindowManagerService mWindowManager;
934
935 static ActivityManagerService mSelf;
936 static ActivityThread mSystemThread;
937
938 private final class AppDeathRecipient implements IBinder.DeathRecipient {
939 final ProcessRecord mApp;
940 final int mPid;
941 final IApplicationThread mAppThread;
942
943 AppDeathRecipient(ProcessRecord app, int pid,
944 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800945 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 TAG, "New death recipient " + this
947 + " for thread " + thread.asBinder());
948 mApp = app;
949 mPid = pid;
950 mAppThread = thread;
951 }
952
953 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800954 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 TAG, "Death received in " + this
956 + " for thread " + mAppThread.asBinder());
957 removeRequestedPss(mApp);
958 synchronized(ActivityManagerService.this) {
959 appDiedLocked(mApp, mPid, mAppThread);
960 }
961 }
962 }
963
964 static final int SHOW_ERROR_MSG = 1;
965 static final int SHOW_NOT_RESPONDING_MSG = 2;
966 static final int SHOW_FACTORY_ERROR_MSG = 3;
967 static final int UPDATE_CONFIGURATION_MSG = 4;
968 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
969 static final int WAIT_FOR_DEBUGGER_MSG = 6;
970 static final int BROADCAST_INTENT_MSG = 7;
971 static final int BROADCAST_TIMEOUT_MSG = 8;
972 static final int PAUSE_TIMEOUT_MSG = 9;
973 static final int IDLE_TIMEOUT_MSG = 10;
974 static final int IDLE_NOW_MSG = 11;
975 static final int SERVICE_TIMEOUT_MSG = 12;
976 static final int UPDATE_TIME_ZONE = 13;
977 static final int SHOW_UID_ERROR_MSG = 14;
978 static final int IM_FEELING_LUCKY_MSG = 15;
979 static final int LAUNCH_TIMEOUT_MSG = 16;
980 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 static final int RESUME_TOP_ACTIVITY_MSG = 19;
982 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700983 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700984 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800985 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986
987 AlertDialog mUidAlert;
988
989 final Handler mHandler = new Handler() {
990 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800991 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 //}
993
994 public void handleMessage(Message msg) {
995 switch (msg.what) {
996 case SHOW_ERROR_MSG: {
997 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 synchronized (ActivityManagerService.this) {
999 ProcessRecord proc = (ProcessRecord)data.get("app");
1000 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001001 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 return;
1003 }
1004 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001005 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001006 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 d.show();
1008 proc.crashDialog = d;
1009 } else {
1010 // The device is asleep, so just pretend that the user
1011 // saw a crash dialog and hit "force quit".
1012 res.set(0);
1013 }
1014 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001015
1016 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 } break;
1018 case SHOW_NOT_RESPONDING_MSG: {
1019 synchronized (ActivityManagerService.this) {
1020 HashMap data = (HashMap) msg.obj;
1021 ProcessRecord proc = (ProcessRecord)data.get("app");
1022 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001023 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 return;
1025 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001026
1027 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1028 null, null, 0, null, null, null,
1029 false, false, MY_PID, Process.SYSTEM_UID);
1030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1032 mContext, proc, (HistoryRecord)data.get("activity"));
1033 d.show();
1034 proc.anrDialog = d;
1035 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001036
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001037 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 } break;
1039 case SHOW_FACTORY_ERROR_MSG: {
1040 Dialog d = new FactoryErrorDialog(
1041 mContext, msg.getData().getCharSequence("msg"));
1042 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001043 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 } break;
1045 case UPDATE_CONFIGURATION_MSG: {
1046 final ContentResolver resolver = mContext.getContentResolver();
1047 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1048 } break;
1049 case GC_BACKGROUND_PROCESSES_MSG: {
1050 synchronized (ActivityManagerService.this) {
1051 performAppGcsIfAppropriateLocked();
1052 }
1053 } break;
1054 case WAIT_FOR_DEBUGGER_MSG: {
1055 synchronized (ActivityManagerService.this) {
1056 ProcessRecord app = (ProcessRecord)msg.obj;
1057 if (msg.arg1 != 0) {
1058 if (!app.waitedForDebugger) {
1059 Dialog d = new AppWaitingForDebuggerDialog(
1060 ActivityManagerService.this,
1061 mContext, app);
1062 app.waitDialog = d;
1063 app.waitedForDebugger = true;
1064 d.show();
1065 }
1066 } else {
1067 if (app.waitDialog != null) {
1068 app.waitDialog.dismiss();
1069 app.waitDialog = null;
1070 }
1071 }
1072 }
1073 } break;
1074 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001075 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 TAG, "Received BROADCAST_INTENT_MSG");
1077 processNextBroadcast(true);
1078 } break;
1079 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001080 if (mDidDexOpt) {
1081 mDidDexOpt = false;
1082 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1083 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1084 return;
1085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 broadcastTimeout();
1087 } break;
1088 case PAUSE_TIMEOUT_MSG: {
1089 IBinder token = (IBinder)msg.obj;
1090 // We don't at this point know if the activity is fullscreen,
1091 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001092 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 activityPaused(token, null, true);
1094 } break;
1095 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001096 if (mDidDexOpt) {
1097 mDidDexOpt = false;
1098 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1099 nmsg.obj = msg.obj;
1100 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1101 return;
1102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 // We don't at this point know if the activity is fullscreen,
1104 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001105 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001106 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001107 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 } break;
1109 case DESTROY_TIMEOUT_MSG: {
1110 IBinder token = (IBinder)msg.obj;
1111 // We don't at this point know if the activity is fullscreen,
1112 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001113 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 activityDestroyed(token);
1115 } break;
1116 case IDLE_NOW_MSG: {
1117 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001118 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 } break;
1120 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001121 if (mDidDexOpt) {
1122 mDidDexOpt = false;
1123 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1124 nmsg.obj = msg.obj;
1125 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1126 return;
1127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 serviceTimeout((ProcessRecord)msg.obj);
1129 } break;
1130 case UPDATE_TIME_ZONE: {
1131 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001132 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1133 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 if (r.thread != null) {
1135 try {
1136 r.thread.updateTimeZone();
1137 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001138 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139 }
1140 }
1141 }
1142 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001143 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144 case SHOW_UID_ERROR_MSG: {
1145 // XXX This is a temporary dialog, no need to localize.
1146 AlertDialog d = new BaseErrorDialog(mContext);
1147 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1148 d.setCancelable(false);
1149 d.setTitle("System UIDs Inconsistent");
1150 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1151 d.setButton("I'm Feeling Lucky",
1152 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1153 mUidAlert = d;
1154 d.show();
1155 } break;
1156 case IM_FEELING_LUCKY_MSG: {
1157 if (mUidAlert != null) {
1158 mUidAlert.dismiss();
1159 mUidAlert = null;
1160 }
1161 } break;
1162 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001163 if (mDidDexOpt) {
1164 mDidDexOpt = false;
1165 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1166 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1167 return;
1168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 synchronized (ActivityManagerService.this) {
1170 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001171 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 mLaunchingActivity.release();
1173 }
1174 }
1175 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 case RESUME_TOP_ACTIVITY_MSG: {
1177 synchronized (ActivityManagerService.this) {
1178 resumeTopActivityLocked(null);
1179 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001180 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001182 if (mDidDexOpt) {
1183 mDidDexOpt = false;
1184 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1185 nmsg.obj = msg.obj;
1186 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1187 return;
1188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 ProcessRecord app = (ProcessRecord)msg.obj;
1190 synchronized (ActivityManagerService.this) {
1191 processStartTimedOutLocked(app);
1192 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001193 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001194 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1195 synchronized (ActivityManagerService.this) {
1196 doPendingActivityLaunchesLocked(true);
1197 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001198 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001199 case KILL_APPLICATION_MSG: {
1200 synchronized (ActivityManagerService.this) {
1201 int uid = msg.arg1;
1202 boolean restart = (msg.arg2 == 1);
1203 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001204 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001205 }
1206 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001207 case FINALIZE_PENDING_INTENT_MSG: {
1208 ((PendingIntentRecord)msg.obj).completeFinalize();
1209 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210 }
1211 }
1212 };
1213
1214 public static void setSystemProcess() {
1215 try {
1216 ActivityManagerService m = mSelf;
1217
1218 ServiceManager.addService("activity", m);
1219 ServiceManager.addService("meminfo", new MemBinder(m));
1220 if (MONITOR_CPU_USAGE) {
1221 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 ServiceManager.addService("permission", new PermissionController(m));
1224
1225 ApplicationInfo info =
1226 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001227 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001228 mSystemThread.installSystemApplicationInfo(info);
1229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 synchronized (mSelf) {
1231 ProcessRecord app = mSelf.newProcessRecordLocked(
1232 mSystemThread.getApplicationThread(), info,
1233 info.processName);
1234 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001235 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 app.maxAdj = SYSTEM_ADJ;
1237 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1238 synchronized (mSelf.mPidsSelfLocked) {
1239 mSelf.mPidsSelfLocked.put(app.pid, app);
1240 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001241 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242 }
1243 } catch (PackageManager.NameNotFoundException e) {
1244 throw new RuntimeException(
1245 "Unable to find android system package", e);
1246 }
1247 }
1248
1249 public void setWindowManager(WindowManagerService wm) {
1250 mWindowManager = wm;
1251 }
1252
1253 public static final Context main(int factoryTest) {
1254 AThread thr = new AThread();
1255 thr.start();
1256
1257 synchronized (thr) {
1258 while (thr.mService == null) {
1259 try {
1260 thr.wait();
1261 } catch (InterruptedException e) {
1262 }
1263 }
1264 }
1265
1266 ActivityManagerService m = thr.mService;
1267 mSelf = m;
1268 ActivityThread at = ActivityThread.systemMain();
1269 mSystemThread = at;
1270 Context context = at.getSystemContext();
1271 m.mContext = context;
1272 m.mFactoryTest = factoryTest;
1273 PowerManager pm =
1274 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1275 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1276 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1277 m.mLaunchingActivity.setReferenceCounted(false);
1278
1279 m.mBatteryStatsService.publish(context);
1280 m.mUsageStatsService.publish(context);
1281
1282 synchronized (thr) {
1283 thr.mReady = true;
1284 thr.notifyAll();
1285 }
1286
1287 m.startRunning(null, null, null, null);
1288
1289 return context;
1290 }
1291
1292 public static ActivityManagerService self() {
1293 return mSelf;
1294 }
1295
1296 static class AThread extends Thread {
1297 ActivityManagerService mService;
1298 boolean mReady = false;
1299
1300 public AThread() {
1301 super("ActivityManager");
1302 }
1303
1304 public void run() {
1305 Looper.prepare();
1306
1307 android.os.Process.setThreadPriority(
1308 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1309
1310 ActivityManagerService m = new ActivityManagerService();
1311
1312 synchronized (this) {
1313 mService = m;
1314 notifyAll();
1315 }
1316
1317 synchronized (this) {
1318 while (!mReady) {
1319 try {
1320 wait();
1321 } catch (InterruptedException e) {
1322 }
1323 }
1324 }
1325
1326 Looper.loop();
1327 }
1328 }
1329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 static class MemBinder extends Binder {
1331 ActivityManagerService mActivityManagerService;
1332 MemBinder(ActivityManagerService activityManagerService) {
1333 mActivityManagerService = activityManagerService;
1334 }
1335
1336 @Override
1337 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1338 ActivityManagerService service = mActivityManagerService;
1339 ArrayList<ProcessRecord> procs;
1340 synchronized (mActivityManagerService) {
1341 if (args != null && args.length > 0
1342 && args[0].charAt(0) != '-') {
1343 procs = new ArrayList<ProcessRecord>();
1344 int pid = -1;
1345 try {
1346 pid = Integer.parseInt(args[0]);
1347 } catch (NumberFormatException e) {
1348
1349 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001350 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1351 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 if (proc.pid == pid) {
1353 procs.add(proc);
1354 } else if (proc.processName.equals(args[0])) {
1355 procs.add(proc);
1356 }
1357 }
1358 if (procs.size() <= 0) {
1359 pw.println("No process found for: " + args[0]);
1360 return;
1361 }
1362 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001363 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 }
1365 }
1366 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1367 }
1368 }
1369
1370 static class CpuBinder extends Binder {
1371 ActivityManagerService mActivityManagerService;
1372 CpuBinder(ActivityManagerService activityManagerService) {
1373 mActivityManagerService = activityManagerService;
1374 }
1375
1376 @Override
1377 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1378 synchronized (mActivityManagerService.mProcessStatsThread) {
1379 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1380 }
1381 }
1382 }
1383
1384 private ActivityManagerService() {
1385 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1386 if (v != null && Integer.getInteger(v) != 0) {
1387 mSimpleProcessManagement = true;
1388 }
1389 v = System.getenv("ANDROID_DEBUG_APP");
1390 if (v != null) {
1391 mSimpleProcessManagement = true;
1392 }
1393
Joe Onorato8a9b2202010-02-26 18:56:32 -08001394 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 File dataDir = Environment.getDataDirectory();
1397 File systemDir = new File(dataDir, "system");
1398 systemDir.mkdirs();
1399 mBatteryStatsService = new BatteryStatsService(new File(
1400 systemDir, "batterystats.bin").toString());
1401 mBatteryStatsService.getActiveStatistics().readLocked();
1402 mBatteryStatsService.getActiveStatistics().writeLocked();
1403
1404 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001405 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406
Jack Palevichb90d28c2009-07-22 15:35:24 -07001407 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1408 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1409
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001410 mConfiguration.setToDefaults();
1411 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 mProcessStats.init();
1413
1414 // Add ourself to the Watchdog monitors.
1415 Watchdog.getInstance().addMonitor(this);
1416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 mProcessStatsThread = new Thread("ProcessStats") {
1418 public void run() {
1419 while (true) {
1420 try {
1421 try {
1422 synchronized(this) {
1423 final long now = SystemClock.uptimeMillis();
1424 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1425 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001426 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 // + ", write delay=" + nextWriteDelay);
1428 if (nextWriteDelay < nextCpuDelay) {
1429 nextCpuDelay = nextWriteDelay;
1430 }
1431 if (nextCpuDelay > 0) {
1432 this.wait(nextCpuDelay);
1433 }
1434 }
1435 } catch (InterruptedException e) {
1436 }
1437
1438 updateCpuStatsNow();
1439 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001440 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 }
1442 }
1443 }
1444 };
1445 mProcessStatsThread.start();
1446 }
1447
1448 @Override
1449 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1450 throws RemoteException {
1451 try {
1452 return super.onTransact(code, data, reply, flags);
1453 } catch (RuntimeException e) {
1454 // The activity manager only throws security exceptions, so let's
1455 // log all others.
1456 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001457 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 }
1459 throw e;
1460 }
1461 }
1462
1463 void updateCpuStats() {
1464 synchronized (mProcessStatsThread) {
1465 final long now = SystemClock.uptimeMillis();
1466 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1467 mProcessStatsThread.notify();
1468 }
1469 }
1470 }
1471
1472 void updateCpuStatsNow() {
1473 synchronized (mProcessStatsThread) {
1474 final long now = SystemClock.uptimeMillis();
1475 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 if (MONITOR_CPU_USAGE &&
1478 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1479 mLastCpuTime = now;
1480 haveNewCpuStats = true;
1481 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001482 //Slog.i(TAG, mProcessStats.printCurrentState());
1483 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 // + mProcessStats.getTotalCpuPercent() + "%");
1485
Joe Onorato8a9b2202010-02-26 18:56:32 -08001486 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 if ("true".equals(SystemProperties.get("events.cpu"))) {
1488 int user = mProcessStats.getLastUserTime();
1489 int system = mProcessStats.getLastSystemTime();
1490 int iowait = mProcessStats.getLastIoWaitTime();
1491 int irq = mProcessStats.getLastIrqTime();
1492 int softIrq = mProcessStats.getLastSoftIrqTime();
1493 int idle = mProcessStats.getLastIdleTime();
1494
1495 int total = user + system + iowait + irq + softIrq + idle;
1496 if (total == 0) total = 1;
1497
Doug Zongker2bec3d42009-12-04 12:52:44 -08001498 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 ((user+system+iowait+irq+softIrq) * 100) / total,
1500 (user * 100) / total,
1501 (system * 100) / total,
1502 (iowait * 100) / total,
1503 (irq * 100) / total,
1504 (softIrq * 100) / total);
1505 }
1506 }
1507
Amith Yamasanie43530a2009-08-21 13:11:37 -07001508 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001509 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001510 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 synchronized(mPidsSelfLocked) {
1512 if (haveNewCpuStats) {
1513 if (mBatteryStatsService.isOnBattery()) {
1514 final int N = mProcessStats.countWorkingStats();
1515 for (int i=0; i<N; i++) {
1516 ProcessStats.Stats st
1517 = mProcessStats.getWorkingStats(i);
1518 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1519 if (pr != null) {
1520 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1521 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001522 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001523 } else {
1524 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001525 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001526 if (ps != null) {
1527 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001528 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001529 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 }
1531 }
1532 }
1533 }
1534 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1537 mLastWriteTime = now;
1538 mBatteryStatsService.getActiveStatistics().writeLocked();
1539 }
1540 }
1541 }
1542 }
1543
1544 /**
1545 * Initialize the application bind args. These are passed to each
1546 * process when the bindApplication() IPC is sent to the process. They're
1547 * lazily setup to make sure the services are running when they're asked for.
1548 */
1549 private HashMap<String, IBinder> getCommonServicesLocked() {
1550 if (mAppBindArgs == null) {
1551 mAppBindArgs = new HashMap<String, IBinder>();
1552
1553 // Setup the application init args
1554 mAppBindArgs.put("package", ServiceManager.getService("package"));
1555 mAppBindArgs.put("window", ServiceManager.getService("window"));
1556 mAppBindArgs.put(Context.ALARM_SERVICE,
1557 ServiceManager.getService(Context.ALARM_SERVICE));
1558 }
1559 return mAppBindArgs;
1560 }
1561
1562 private final void setFocusedActivityLocked(HistoryRecord r) {
1563 if (mFocusedActivity != r) {
1564 mFocusedActivity = r;
1565 mWindowManager.setFocusedApp(r, true);
1566 }
1567 }
1568
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001569 private final void updateLruProcessLocked(ProcessRecord app,
1570 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001572 int lrui = mLruProcesses.indexOf(app);
1573 if (lrui >= 0) mLruProcesses.remove(lrui);
1574
1575 int i = mLruProcesses.size()-1;
1576 int skipTop = 0;
1577
1578 // compute the new weight for this process.
1579 if (updateActivityTime) {
1580 app.lastActivityTime = SystemClock.uptimeMillis();
1581 }
1582 if (app.activities.size() > 0) {
1583 // If this process has activities, we more strongly want to keep
1584 // it around.
1585 app.lruWeight = app.lastActivityTime;
1586 } else if (app.pubProviders.size() > 0) {
1587 // If this process contains content providers, we want to keep
1588 // it a little more strongly.
1589 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1590 // Also don't let it kick out the first few "real" hidden processes.
1591 skipTop = MIN_HIDDEN_APPS;
1592 } else {
1593 // If this process doesn't have activities, we less strongly
1594 // want to keep it around, and generally want to avoid getting
1595 // in front of any very recently used activities.
1596 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1597 // Also don't let it kick out the first few "real" hidden processes.
1598 skipTop = MIN_HIDDEN_APPS;
1599 }
1600 while (i >= 0) {
1601 ProcessRecord p = mLruProcesses.get(i);
1602 // If this app shouldn't be in front of the first N background
1603 // apps, then skip over that many that are currently hidden.
1604 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1605 skipTop--;
1606 }
1607 if (p.lruWeight <= app.lruWeight){
1608 mLruProcesses.add(i+1, app);
1609 break;
1610 }
1611 i--;
1612 }
1613 if (i < 0) {
1614 mLruProcesses.add(0, app);
1615 }
1616
Joe Onorato8a9b2202010-02-26 18:56:32 -08001617 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 if (oomAdj) {
1619 updateOomAdjLocked();
1620 }
1621 }
1622
1623 private final boolean updateLRUListLocked(HistoryRecord r) {
1624 final boolean hadit = mLRUActivities.remove(r);
1625 mLRUActivities.add(r);
1626 return hadit;
1627 }
1628
1629 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1630 int i = mHistory.size()-1;
1631 while (i >= 0) {
1632 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1633 if (!r.finishing && r != notTop) {
1634 return r;
1635 }
1636 i--;
1637 }
1638 return null;
1639 }
1640
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001641 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1642 int i = mHistory.size()-1;
1643 while (i >= 0) {
1644 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1645 if (!r.finishing && !r.delayedResume && r != notTop) {
1646 return r;
1647 }
1648 i--;
1649 }
1650 return null;
1651 }
1652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 /**
1654 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001655 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 *
1657 * @param token If non-null, any history records matching this token will be skipped.
1658 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1659 *
1660 * @return Returns the HistoryRecord of the next activity on the stack.
1661 */
1662 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1663 int i = mHistory.size()-1;
1664 while (i >= 0) {
1665 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1666 // Note: the taskId check depends on real taskId fields being non-zero
1667 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1668 return r;
1669 }
1670 i--;
1671 }
1672 return null;
1673 }
1674
1675 private final ProcessRecord getProcessRecordLocked(
1676 String processName, int uid) {
1677 if (uid == Process.SYSTEM_UID) {
1678 // The system gets to run in any process. If there are multiple
1679 // processes with the same uid, just pick the first (this
1680 // should never happen).
1681 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1682 processName);
1683 return procs != null ? procs.valueAt(0) : null;
1684 }
1685 ProcessRecord proc = mProcessNames.get(processName, uid);
1686 return proc;
1687 }
1688
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001689 private void ensurePackageDexOpt(String packageName) {
1690 IPackageManager pm = ActivityThread.getPackageManager();
1691 try {
1692 if (pm.performDexOpt(packageName)) {
1693 mDidDexOpt = true;
1694 }
1695 } catch (RemoteException e) {
1696 }
1697 }
1698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 private boolean isNextTransitionForward() {
1700 int transit = mWindowManager.getPendingAppTransition();
1701 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1702 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1703 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1704 }
1705
1706 private final boolean realStartActivityLocked(HistoryRecord r,
1707 ProcessRecord app, boolean andResume, boolean checkConfig)
1708 throws RemoteException {
1709
1710 r.startFreezingScreenLocked(app, 0);
1711 mWindowManager.setAppVisibility(r, true);
1712
1713 // Have the window manager re-evaluate the orientation of
1714 // the screen based on the new activity order. Note that
1715 // as a result of this, it can call back into the activity
1716 // manager with a new orientation. We don't care about that,
1717 // because the activity is not currently running so we are
1718 // just restarting it anyway.
1719 if (checkConfig) {
1720 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001721 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001722 r.mayFreezeScreenLocked(app) ? r : null);
1723 updateConfigurationLocked(config, r);
1724 }
1725
1726 r.app = app;
1727
Joe Onorato8a9b2202010-02-26 18:56:32 -08001728 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729
1730 int idx = app.activities.indexOf(r);
1731 if (idx < 0) {
1732 app.activities.add(r);
1733 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001734 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735
1736 try {
1737 if (app.thread == null) {
1738 throw new RemoteException();
1739 }
1740 List<ResultInfo> results = null;
1741 List<Intent> newIntents = null;
1742 if (andResume) {
1743 results = r.results;
1744 newIntents = r.newIntents;
1745 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001746 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 + " icicle=" + r.icicle
1748 + " with results=" + results + " newIntents=" + newIntents
1749 + " andResume=" + andResume);
1750 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001751 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752 System.identityHashCode(r),
1753 r.task.taskId, r.shortComponentName);
1754 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001755 if (r.isHomeActivity) {
1756 mHomeProcess = app;
1757 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001758 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001760 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 r.info, r.icicle, results, newIntents, !andResume,
1762 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 } catch (RemoteException e) {
1764 if (r.launchFailed) {
1765 // This is the second time we failed -- finish activity
1766 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001767 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 + r.intent.getComponent().flattenToShortString()
1769 + ", giving up", e);
1770 appDiedLocked(app, app.pid, app.thread);
1771 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1772 "2nd-crash");
1773 return false;
1774 }
1775
1776 // This is the first time we failed -- restart process and
1777 // retry.
1778 app.activities.remove(r);
1779 throw e;
1780 }
1781
1782 r.launchFailed = false;
1783 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001784 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 + " being launched, but already in LRU list");
1786 }
1787
1788 if (andResume) {
1789 // As part of the process of launching, ActivityThread also performs
1790 // a resume.
1791 r.state = ActivityState.RESUMED;
1792 r.icicle = null;
1793 r.haveState = false;
1794 r.stopped = false;
1795 mResumedActivity = r;
1796 r.task.touchActiveTime();
1797 completeResumeLocked(r);
1798 pauseIfSleepingLocked();
1799 } else {
1800 // This activity is not starting in the resumed state... which
1801 // should look like we asked it to pause+stop (but remain visible),
1802 // and it has done so and reported back the current icicle and
1803 // other state.
1804 r.state = ActivityState.STOPPED;
1805 r.stopped = true;
1806 }
1807
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001808 // Launch the new version setup screen if needed. We do this -after-
1809 // launching the initial activity (that is, home), so that it can have
1810 // a chance to initialize itself while in the background, making the
1811 // switch back to it faster and look better.
1812 startSetupActivityLocked();
1813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 return true;
1815 }
1816
1817 private final void startSpecificActivityLocked(HistoryRecord r,
1818 boolean andResume, boolean checkConfig) {
1819 // Is this activity's application already running?
1820 ProcessRecord app = getProcessRecordLocked(r.processName,
1821 r.info.applicationInfo.uid);
1822
1823 if (r.startTime == 0) {
1824 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001825 if (mInitialStartTime == 0) {
1826 mInitialStartTime = r.startTime;
1827 }
1828 } else if (mInitialStartTime == 0) {
1829 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 }
1831
1832 if (app != null && app.thread != null) {
1833 try {
1834 realStartActivityLocked(r, app, andResume, checkConfig);
1835 return;
1836 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001837 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 + r.intent.getComponent().flattenToShortString(), e);
1839 }
1840
1841 // If a dead object exception was thrown -- fall through to
1842 // restart the application.
1843 }
1844
1845 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001846 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 }
1848
1849 private final ProcessRecord startProcessLocked(String processName,
1850 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001851 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1853 // We don't have to do anything more if:
1854 // (1) There is an existing application record; and
1855 // (2) The caller doesn't think it is dead, OR there is no thread
1856 // object attached to it so we know it couldn't have crashed; and
1857 // (3) There is a pid assigned to it, so it is either starting or
1858 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001859 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 + " app=" + app + " knownToBeDead=" + knownToBeDead
1861 + " thread=" + (app != null ? app.thread : null)
1862 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001863 if (app != null && app.pid > 0) {
1864 if (!knownToBeDead || app.thread == null) {
1865 return app;
1866 } else {
1867 // An application record is attached to a previous process,
1868 // clean it up now.
1869 handleAppDiedLocked(app, true);
1870 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 String hostingNameStr = hostingName != null
1874 ? hostingName.flattenToShortString() : null;
1875
1876 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1877 // If we are in the background, then check to see if this process
1878 // is bad. If so, we will just silently fail.
1879 if (mBadProcesses.get(info.processName, info.uid) != null) {
1880 return null;
1881 }
1882 } else {
1883 // When the user is explicitly starting a process, then clear its
1884 // crash count so that we won't make it bad until they see at
1885 // least one crash dialog again, and make the process good again
1886 // if it had been bad.
1887 mProcessCrashTimes.remove(info.processName, info.uid);
1888 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001889 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 info.processName);
1891 mBadProcesses.remove(info.processName, info.uid);
1892 if (app != null) {
1893 app.bad = false;
1894 }
1895 }
1896 }
1897
1898 if (app == null) {
1899 app = newProcessRecordLocked(null, info, processName);
1900 mProcessNames.put(processName, info.uid, app);
1901 } else {
1902 // If this is a new package in the process, add the package to the list
1903 app.addPackage(info.packageName);
1904 }
1905
1906 // If the system is not ready yet, then hold off on starting this
1907 // process until it is.
1908 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001909 && !isAllowedWhileBooting(info)
1910 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911 if (!mProcessesOnHold.contains(app)) {
1912 mProcessesOnHold.add(app);
1913 }
1914 return app;
1915 }
1916
1917 startProcessLocked(app, hostingType, hostingNameStr);
1918 return (app.pid != 0) ? app : null;
1919 }
1920
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001921 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1922 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1923 }
1924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001925 private final void startProcessLocked(ProcessRecord app,
1926 String hostingType, String hostingNameStr) {
1927 if (app.pid > 0 && app.pid != MY_PID) {
1928 synchronized (mPidsSelfLocked) {
1929 mPidsSelfLocked.remove(app.pid);
1930 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1931 }
1932 app.pid = 0;
1933 }
1934
1935 mProcessesOnHold.remove(app);
1936
1937 updateCpuStats();
1938
1939 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1940 mProcDeaths[0] = 0;
1941
1942 try {
1943 int uid = app.info.uid;
1944 int[] gids = null;
1945 try {
1946 gids = mContext.getPackageManager().getPackageGids(
1947 app.info.packageName);
1948 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001949 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001950 }
1951 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1952 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1953 && mTopComponent != null
1954 && app.processName.equals(mTopComponent.getPackageName())) {
1955 uid = 0;
1956 }
1957 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1958 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1959 uid = 0;
1960 }
1961 }
1962 int debugFlags = 0;
1963 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1964 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1965 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001966 // Run the app in safe mode if its manifest requests so or the
1967 // system is booted in safe mode.
1968 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1969 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001970 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1973 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1974 }
1975 if ("1".equals(SystemProperties.get("debug.assert"))) {
1976 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1977 }
1978 int pid = Process.start("android.app.ActivityThread",
1979 mSimpleProcessManagement ? app.processName : null, uid, uid,
1980 gids, debugFlags, null);
1981 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1982 synchronized (bs) {
1983 if (bs.isOnBattery()) {
1984 app.batteryStats.incStartsLocked();
1985 }
1986 }
1987
Doug Zongker2bec3d42009-12-04 12:52:44 -08001988 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001989 app.processName, hostingType,
1990 hostingNameStr != null ? hostingNameStr : "");
1991
1992 if (app.persistent) {
1993 Watchdog.getInstance().processStarted(app, app.processName, pid);
1994 }
1995
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001996 StringBuilder buf = mStringBuilder;
1997 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001998 buf.append("Start proc ");
1999 buf.append(app.processName);
2000 buf.append(" for ");
2001 buf.append(hostingType);
2002 if (hostingNameStr != null) {
2003 buf.append(" ");
2004 buf.append(hostingNameStr);
2005 }
2006 buf.append(": pid=");
2007 buf.append(pid);
2008 buf.append(" uid=");
2009 buf.append(uid);
2010 buf.append(" gids={");
2011 if (gids != null) {
2012 for (int gi=0; gi<gids.length; gi++) {
2013 if (gi != 0) buf.append(", ");
2014 buf.append(gids[gi]);
2015
2016 }
2017 }
2018 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002019 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 if (pid == 0 || pid == MY_PID) {
2021 // Processes are being emulated with threads.
2022 app.pid = MY_PID;
2023 app.removed = false;
2024 mStartingProcesses.add(app);
2025 } else if (pid > 0) {
2026 app.pid = pid;
2027 app.removed = false;
2028 synchronized (mPidsSelfLocked) {
2029 this.mPidsSelfLocked.put(pid, app);
2030 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2031 msg.obj = app;
2032 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2033 }
2034 } else {
2035 app.pid = 0;
2036 RuntimeException e = new RuntimeException(
2037 "Failure starting process " + app.processName
2038 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002039 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 }
2041 } catch (RuntimeException e) {
2042 // XXX do better error recovery.
2043 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002044 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002045 }
2046 }
2047
2048 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2049 if (mPausingActivity != null) {
2050 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002051 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002052 + mPausingActivity, e);
2053 }
2054 HistoryRecord prev = mResumedActivity;
2055 if (prev == null) {
2056 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002057 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002058 resumeTopActivityLocked(null);
2059 return;
2060 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002061 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 mResumedActivity = null;
2063 mPausingActivity = prev;
2064 mLastPausedActivity = prev;
2065 prev.state = ActivityState.PAUSING;
2066 prev.task.touchActiveTime();
2067
2068 updateCpuStats();
2069
2070 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002071 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002073 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002074 System.identityHashCode(prev),
2075 prev.shortComponentName);
2076 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2077 prev.configChangeFlags);
2078 updateUsageStats(prev, false);
2079 } catch (Exception e) {
2080 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002081 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 mPausingActivity = null;
2083 mLastPausedActivity = null;
2084 }
2085 } else {
2086 mPausingActivity = null;
2087 mLastPausedActivity = null;
2088 }
2089
2090 // If we are not going to sleep, we want to ensure the device is
2091 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002092 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 mLaunchingActivity.acquire();
2094 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2095 // To be safe, don't allow the wake lock to be held for too long.
2096 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2097 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2098 }
2099 }
2100
2101
2102 if (mPausingActivity != null) {
2103 // Have the window manager pause its key dispatching until the new
2104 // activity has started. If we're pausing the activity just because
2105 // the screen is being turned off and the UI is sleeping, don't interrupt
2106 // key dispatch; the same activity will pick it up again on wakeup.
2107 if (!uiSleeping) {
2108 prev.pauseKeyDispatchingLocked();
2109 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002110 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002111 }
2112
2113 // Schedule a pause timeout in case the app doesn't respond.
2114 // We don't give it much time because this directly impacts the
2115 // responsiveness seen by the user.
2116 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2117 msg.obj = prev;
2118 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002119 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002120 } else {
2121 // This activity failed to schedule the
2122 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002123 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 resumeTopActivityLocked(null);
2125 }
2126 }
2127
2128 private final void completePauseLocked() {
2129 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002130 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131
2132 if (prev != null) {
2133 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002134 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2136 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002137 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 if (prev.waitingVisible) {
2139 prev.waitingVisible = false;
2140 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002141 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 TAG, "Complete pause, no longer waiting: " + prev);
2143 }
2144 if (prev.configDestroy) {
2145 // The previous is being paused because the configuration
2146 // is changing, which means it is actually stopping...
2147 // To juggle the fact that we are also starting a new
2148 // instance right now, we need to first completely stop
2149 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002150 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 destroyActivityLocked(prev, true);
2152 } else {
2153 mStoppingActivities.add(prev);
2154 if (mStoppingActivities.size() > 3) {
2155 // If we already have a few activities waiting to stop,
2156 // then give up on things going idle and start clearing
2157 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002158 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 Message msg = Message.obtain();
2160 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2161 mHandler.sendMessage(msg);
2162 }
2163 }
2164 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002165 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 prev = null;
2167 }
2168 mPausingActivity = null;
2169 }
2170
Dianne Hackborn55280a92009-05-07 15:53:46 -07002171 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 resumeTopActivityLocked(prev);
2173 } else {
2174 if (mGoingToSleep.isHeld()) {
2175 mGoingToSleep.release();
2176 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002177 if (mShuttingDown) {
2178 notifyAll();
2179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 }
2181
2182 if (prev != null) {
2183 prev.resumeKeyDispatchingLocked();
2184 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002185
2186 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2187 long diff = 0;
2188 synchronized (mProcessStatsThread) {
2189 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2190 }
2191 if (diff > 0) {
2192 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2193 synchronized (bsi) {
2194 BatteryStatsImpl.Uid.Proc ps =
2195 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2196 prev.info.packageName);
2197 if (ps != null) {
2198 ps.addForegroundTimeLocked(diff);
2199 }
2200 }
2201 }
2202 }
2203 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002204 }
2205
2206 /**
2207 * Once we know that we have asked an application to put an activity in
2208 * the resumed state (either by launching it or explicitly telling it),
2209 * this function updates the rest of our state to match that fact.
2210 */
2211 private final void completeResumeLocked(HistoryRecord next) {
2212 next.idle = false;
2213 next.results = null;
2214 next.newIntents = null;
2215
2216 // schedule an idle timeout in case the app doesn't do it for us.
2217 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2218 msg.obj = next;
2219 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2220
2221 if (false) {
2222 // The activity was never told to pause, so just keep
2223 // things going as-is. To maintain our own state,
2224 // we need to emulate it coming back and saying it is
2225 // idle.
2226 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2227 msg.obj = next;
2228 mHandler.sendMessage(msg);
2229 }
2230
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002231 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 next.thumbnail = null;
2234 setFocusedActivityLocked(next);
2235 next.resumeKeyDispatchingLocked();
2236 ensureActivitiesVisibleLocked(null, 0);
2237 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002238 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002239
2240 // Mark the point when the activity is resuming
2241 // TODO: To be more accurate, the mark should be before the onCreate,
2242 // not after the onResume. But for subsequent starts, onResume is fine.
2243 if (next.app != null) {
2244 synchronized (mProcessStatsThread) {
2245 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2246 }
2247 } else {
2248 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 }
2251
2252 /**
2253 * Make sure that all activities that need to be visible (that is, they
2254 * currently can be seen by the user) actually are.
2255 */
2256 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2257 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002258 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 TAG, "ensureActivitiesVisible behind " + top
2260 + " configChanges=0x" + Integer.toHexString(configChanges));
2261
2262 // If the top activity is not fullscreen, then we need to
2263 // make sure any activities under it are now visible.
2264 final int count = mHistory.size();
2265 int i = count-1;
2266 while (mHistory.get(i) != top) {
2267 i--;
2268 }
2269 HistoryRecord r;
2270 boolean behindFullscreen = false;
2271 for (; i>=0; i--) {
2272 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002273 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 TAG, "Make visible? " + r + " finishing=" + r.finishing
2275 + " state=" + r.state);
2276 if (r.finishing) {
2277 continue;
2278 }
2279
2280 final boolean doThisProcess = onlyThisProcess == null
2281 || onlyThisProcess.equals(r.processName);
2282
2283 // First: if this is not the current activity being started, make
2284 // sure it matches the current configuration.
2285 if (r != starting && doThisProcess) {
2286 ensureActivityConfigurationLocked(r, 0);
2287 }
2288
2289 if (r.app == null || r.app.thread == null) {
2290 if (onlyThisProcess == null
2291 || onlyThisProcess.equals(r.processName)) {
2292 // This activity needs to be visible, but isn't even
2293 // running... get it started, but don't resume it
2294 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002295 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296 TAG, "Start and freeze screen for " + r);
2297 if (r != starting) {
2298 r.startFreezingScreenLocked(r.app, configChanges);
2299 }
2300 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002301 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302 TAG, "Starting and making visible: " + r);
2303 mWindowManager.setAppVisibility(r, true);
2304 }
2305 if (r != starting) {
2306 startSpecificActivityLocked(r, false, false);
2307 }
2308 }
2309
2310 } else if (r.visible) {
2311 // If this activity is already visible, then there is nothing
2312 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002313 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314 TAG, "Skipping: already visible at " + r);
2315 r.stopFreezingScreenLocked(false);
2316
2317 } else if (onlyThisProcess == null) {
2318 // This activity is not currently visible, but is running.
2319 // Tell it to become visible.
2320 r.visible = true;
2321 if (r.state != ActivityState.RESUMED && r != starting) {
2322 // If this activity is paused, tell it
2323 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002324 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002325 TAG, "Making visible and scheduling visibility: " + r);
2326 try {
2327 mWindowManager.setAppVisibility(r, true);
2328 r.app.thread.scheduleWindowVisibility(r, true);
2329 r.stopFreezingScreenLocked(false);
2330 } catch (Exception e) {
2331 // Just skip on any failure; we'll make it
2332 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002333 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002334 + r.intent.getComponent(), e);
2335 }
2336 }
2337 }
2338
2339 // Aggregate current change flags.
2340 configChanges |= r.configChangeFlags;
2341
2342 if (r.fullscreen) {
2343 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002344 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002345 TAG, "Stopping: fullscreen at " + r);
2346 behindFullscreen = true;
2347 i--;
2348 break;
2349 }
2350 }
2351
2352 // Now for any activities that aren't visible to the user, make
2353 // sure they no longer are keeping the screen frozen.
2354 while (i >= 0) {
2355 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002356 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002357 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2358 + " state=" + r.state
2359 + " behindFullscreen=" + behindFullscreen);
2360 if (!r.finishing) {
2361 if (behindFullscreen) {
2362 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002363 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002364 TAG, "Making invisible: " + r);
2365 r.visible = false;
2366 try {
2367 mWindowManager.setAppVisibility(r, false);
2368 if ((r.state == ActivityState.STOPPING
2369 || r.state == ActivityState.STOPPED)
2370 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002371 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 TAG, "Scheduling invisibility: " + r);
2373 r.app.thread.scheduleWindowVisibility(r, false);
2374 }
2375 } catch (Exception e) {
2376 // Just skip on any failure; we'll make it
2377 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002378 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 + r.intent.getComponent(), e);
2380 }
2381 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002382 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 TAG, "Already invisible: " + r);
2384 }
2385 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002386 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 TAG, "Now behindFullscreen: " + r);
2388 behindFullscreen = true;
2389 }
2390 }
2391 i--;
2392 }
2393 }
2394
2395 /**
2396 * Version of ensureActivitiesVisible that can easily be called anywhere.
2397 */
2398 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2399 int configChanges) {
2400 HistoryRecord r = topRunningActivityLocked(null);
2401 if (r != null) {
2402 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2403 }
2404 }
2405
2406 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2407 if (resumed) {
2408 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2409 } else {
2410 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2411 }
2412 }
2413
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002414 private boolean startHomeActivityLocked() {
2415 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2416 && mTopAction == null) {
2417 // We are running in factory test mode, but unable to find
2418 // the factory test app, so just sit around displaying the
2419 // error message and don't try to start anything.
2420 return false;
2421 }
2422 Intent intent = new Intent(
2423 mTopAction,
2424 mTopData != null ? Uri.parse(mTopData) : null);
2425 intent.setComponent(mTopComponent);
2426 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2427 intent.addCategory(Intent.CATEGORY_HOME);
2428 }
2429 ActivityInfo aInfo =
2430 intent.resolveActivityInfo(mContext.getPackageManager(),
2431 STOCK_PM_FLAGS);
2432 if (aInfo != null) {
2433 intent.setComponent(new ComponentName(
2434 aInfo.applicationInfo.packageName, aInfo.name));
2435 // Don't do this if the home app is currently being
2436 // instrumented.
2437 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2438 aInfo.applicationInfo.uid);
2439 if (app == null || app.instrumentationClass == null) {
2440 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2441 startActivityLocked(null, intent, null, null, 0, aInfo,
2442 null, null, 0, 0, 0, false, false);
2443 }
2444 }
2445
2446
2447 return true;
2448 }
2449
2450 /**
2451 * Starts the "new version setup screen" if appropriate.
2452 */
2453 private void startSetupActivityLocked() {
2454 // Only do this once per boot.
2455 if (mCheckedForSetup) {
2456 return;
2457 }
2458
2459 // We will show this screen if the current one is a different
2460 // version than the last one shown, and we are not running in
2461 // low-level factory test mode.
2462 final ContentResolver resolver = mContext.getContentResolver();
2463 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2464 Settings.Secure.getInt(resolver,
2465 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2466 mCheckedForSetup = true;
2467
2468 // See if we should be showing the platform update setup UI.
2469 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2470 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2471 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2472
2473 // We don't allow third party apps to replace this.
2474 ResolveInfo ri = null;
2475 for (int i=0; ris != null && i<ris.size(); i++) {
2476 if ((ris.get(i).activityInfo.applicationInfo.flags
2477 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2478 ri = ris.get(i);
2479 break;
2480 }
2481 }
2482
2483 if (ri != null) {
2484 String vers = ri.activityInfo.metaData != null
2485 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2486 : null;
2487 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2488 vers = ri.activityInfo.applicationInfo.metaData.getString(
2489 Intent.METADATA_SETUP_VERSION);
2490 }
2491 String lastVers = Settings.Secure.getString(
2492 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2493 if (vers != null && !vers.equals(lastVers)) {
2494 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2495 intent.setComponent(new ComponentName(
2496 ri.activityInfo.packageName, ri.activityInfo.name));
2497 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2498 null, null, 0, 0, 0, false, false);
2499 }
2500 }
2501 }
2502 }
2503
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002504 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002505 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002506
2507 final int identHash = System.identityHashCode(r);
2508 updateUsageStats(r, true);
2509
2510 int i = mWatchers.beginBroadcast();
2511 while (i > 0) {
2512 i--;
2513 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2514 if (w != null) {
2515 try {
2516 w.activityResuming(identHash);
2517 } catch (RemoteException e) {
2518 }
2519 }
2520 }
2521 mWatchers.finishBroadcast();
2522 }
2523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 /**
2525 * Ensure that the top activity in the stack is resumed.
2526 *
2527 * @param prev The previously resumed activity, for when in the process
2528 * of pausing; can be null to call from elsewhere.
2529 *
2530 * @return Returns true if something is being resumed, or false if
2531 * nothing happened.
2532 */
2533 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2534 // Find the first activity that is not finishing.
2535 HistoryRecord next = topRunningActivityLocked(null);
2536
2537 // Remember how we'll process this pause/resume situation, and ensure
2538 // that the state is reset however we wind up proceeding.
2539 final boolean userLeaving = mUserLeaving;
2540 mUserLeaving = false;
2541
2542 if (next == null) {
2543 // There are no more activities! Let's just start up the
2544 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002545 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 }
2547
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002548 next.delayedResume = false;
2549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 // If the top activity is the resumed one, nothing to do.
2551 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2552 // Make sure we have executed any pending transitions, since there
2553 // should be nothing left to do at this point.
2554 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002555 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002556 return false;
2557 }
2558
2559 // If we are sleeping, and there is no resumed activity, and the top
2560 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002561 if ((mSleeping || mShuttingDown)
2562 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002563 // Make sure we have executed any pending transitions, since there
2564 // should be nothing left to do at this point.
2565 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002566 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 return false;
2568 }
2569
2570 // The activity may be waiting for stop, but that is no longer
2571 // appropriate for it.
2572 mStoppingActivities.remove(next);
2573 mWaitingVisibleActivities.remove(next);
2574
Joe Onorato8a9b2202010-02-26 18:56:32 -08002575 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576
2577 // If we are currently pausing an activity, then don't do anything
2578 // until that is done.
2579 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002580 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 return false;
2582 }
2583
2584 // We need to start pausing the current activity so the top one
2585 // can be resumed...
2586 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002587 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 startPausingLocked(userLeaving, false);
2589 return true;
2590 }
2591
2592 if (prev != null && prev != next) {
2593 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2594 prev.waitingVisible = true;
2595 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002596 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597 TAG, "Resuming top, waiting visible to hide: " + prev);
2598 } else {
2599 // The next activity is already visible, so hide the previous
2600 // activity's windows right now so we can show the new one ASAP.
2601 // We only do this if the previous is finishing, which should mean
2602 // it is on top of the one being resumed so hiding it quickly
2603 // is good. Otherwise, we want to do the normal route of allowing
2604 // the resumed activity to be shown so we can decide if the
2605 // previous should actually be hidden depending on whether the
2606 // new one is found to be full-screen or not.
2607 if (prev.finishing) {
2608 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002609 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 + prev + ", waitingVisible="
2611 + (prev != null ? prev.waitingVisible : null)
2612 + ", nowVisible=" + next.nowVisible);
2613 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002614 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 + prev + ", waitingVisible="
2616 + (prev != null ? prev.waitingVisible : null)
2617 + ", nowVisible=" + next.nowVisible);
2618 }
2619 }
2620 }
2621
2622 // We are starting up the next activity, so tell the window manager
2623 // that the previous one will be hidden soon. This way it can know
2624 // to ignore it when computing the desired screen orientation.
2625 if (prev != null) {
2626 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002627 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002629 if (mNoAnimActivities.contains(prev)) {
2630 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2631 } else {
2632 mWindowManager.prepareAppTransition(prev.task == next.task
2633 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2634 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002636 mWindowManager.setAppWillBeHidden(prev);
2637 mWindowManager.setAppVisibility(prev, false);
2638 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002639 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002641 if (mNoAnimActivities.contains(next)) {
2642 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2643 } else {
2644 mWindowManager.prepareAppTransition(prev.task == next.task
2645 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2646 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2647 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002648 }
2649 if (false) {
2650 mWindowManager.setAppWillBeHidden(prev);
2651 mWindowManager.setAppVisibility(prev, false);
2652 }
2653 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002654 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002656 if (mNoAnimActivities.contains(next)) {
2657 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2658 } else {
2659 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 }
2662
2663 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002664 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665
2666 // This activity is now becoming visible.
2667 mWindowManager.setAppVisibility(next, true);
2668
2669 HistoryRecord lastResumedActivity = mResumedActivity;
2670 ActivityState lastState = next.state;
2671
2672 updateCpuStats();
2673
2674 next.state = ActivityState.RESUMED;
2675 mResumedActivity = next;
2676 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002677 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002678 updateLRUListLocked(next);
2679
2680 // Have the window manager re-evaluate the orientation of
2681 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002682 boolean updated;
2683 synchronized (this) {
2684 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2685 mConfiguration,
2686 next.mayFreezeScreenLocked(next.app) ? next : null);
2687 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002688 next.frozenBeforeDestroy = true;
2689 }
2690 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002692 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693 // The configuration update wasn't able to keep the existing
2694 // instance of the activity, and instead started a new one.
2695 // We should be all done, but let's just make sure our activity
2696 // is still at the top and schedule another run if something
2697 // weird happened.
2698 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002699 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002700 "Activity config changed during resume: " + next
2701 + ", new next: " + nextNext);
2702 if (nextNext != next) {
2703 // Do over!
2704 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2705 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002706 setFocusedActivityLocked(next);
2707 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002709 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710 return true;
2711 }
2712
2713 try {
2714 // Deliver all pending results.
2715 ArrayList a = next.results;
2716 if (a != null) {
2717 final int N = a.size();
2718 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002719 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720 TAG, "Delivering results to " + next
2721 + ": " + a);
2722 next.app.thread.scheduleSendResult(next, a);
2723 }
2724 }
2725
2726 if (next.newIntents != null) {
2727 next.app.thread.scheduleNewIntent(next.newIntents, next);
2728 }
2729
Doug Zongker2bec3d42009-12-04 12:52:44 -08002730 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 System.identityHashCode(next),
2732 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002733
2734 next.app.thread.scheduleResumeActivity(next,
2735 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 pauseIfSleepingLocked();
2738
2739 } catch (Exception e) {
2740 // Whoops, need to restart this activity!
2741 next.state = lastState;
2742 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002743 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744 if (!next.hasBeenLaunched) {
2745 next.hasBeenLaunched = true;
2746 } else {
2747 if (SHOW_APP_STARTING_ICON) {
2748 mWindowManager.setAppStartingWindow(
2749 next, next.packageName, next.theme,
2750 next.nonLocalizedLabel,
2751 next.labelRes, next.icon, null, true);
2752 }
2753 }
2754 startSpecificActivityLocked(next, true, false);
2755 return true;
2756 }
2757
2758 // From this point on, if something goes wrong there is no way
2759 // to recover the activity.
2760 try {
2761 next.visible = true;
2762 completeResumeLocked(next);
2763 } catch (Exception e) {
2764 // If any exception gets thrown, toss away this
2765 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002766 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2768 "resume-exception");
2769 return true;
2770 }
2771
2772 // Didn't need to use the icicle, and it is now out of date.
2773 next.icicle = null;
2774 next.haveState = false;
2775 next.stopped = false;
2776
2777 } else {
2778 // Whoops, need to restart this activity!
2779 if (!next.hasBeenLaunched) {
2780 next.hasBeenLaunched = true;
2781 } else {
2782 if (SHOW_APP_STARTING_ICON) {
2783 mWindowManager.setAppStartingWindow(
2784 next, next.packageName, next.theme,
2785 next.nonLocalizedLabel,
2786 next.labelRes, next.icon, null, true);
2787 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002788 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002789 }
2790 startSpecificActivityLocked(next, true, true);
2791 }
2792
2793 return true;
2794 }
2795
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002796 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2797 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002798 final int NH = mHistory.size();
2799
2800 int addPos = -1;
2801
2802 if (!newTask) {
2803 // If starting in an existing task, find where that is...
2804 HistoryRecord next = null;
2805 boolean startIt = true;
2806 for (int i = NH-1; i >= 0; i--) {
2807 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2808 if (p.finishing) {
2809 continue;
2810 }
2811 if (p.task == r.task) {
2812 // Here it is! Now, if this is not yet visible to the
2813 // user, then just add it without starting; it will
2814 // get started when the user navigates back to it.
2815 addPos = i+1;
2816 if (!startIt) {
2817 mHistory.add(addPos, r);
2818 r.inHistory = true;
2819 r.task.numActivities++;
2820 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2821 r.info.screenOrientation, r.fullscreen);
2822 if (VALIDATE_TOKENS) {
2823 mWindowManager.validateAppTokens(mHistory);
2824 }
2825 return;
2826 }
2827 break;
2828 }
2829 if (p.fullscreen) {
2830 startIt = false;
2831 }
2832 next = p;
2833 }
2834 }
2835
2836 // Place a new activity at top of stack, so it is next to interact
2837 // with the user.
2838 if (addPos < 0) {
2839 addPos = mHistory.size();
2840 }
2841
2842 // If we are not placing the new activity frontmost, we do not want
2843 // to deliver the onUserLeaving callback to the actual frontmost
2844 // activity
2845 if (addPos < NH) {
2846 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002847 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 }
2849
2850 // Slot the activity into the history stack and proceed
2851 mHistory.add(addPos, r);
2852 r.inHistory = true;
2853 r.frontOfTask = newTask;
2854 r.task.numActivities++;
2855 if (NH > 0) {
2856 // We want to show the starting preview window if we are
2857 // switching to a new task, or the next activity's process is
2858 // not currently running.
2859 boolean showStartingIcon = newTask;
2860 ProcessRecord proc = r.app;
2861 if (proc == null) {
2862 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2863 }
2864 if (proc == null || proc.thread == null) {
2865 showStartingIcon = true;
2866 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002867 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002868 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002869 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2870 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2871 mNoAnimActivities.add(r);
2872 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2873 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2874 mNoAnimActivities.remove(r);
2875 } else {
2876 mWindowManager.prepareAppTransition(newTask
2877 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2878 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2879 mNoAnimActivities.remove(r);
2880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002881 mWindowManager.addAppToken(
2882 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2883 boolean doShow = true;
2884 if (newTask) {
2885 // Even though this activity is starting fresh, we still need
2886 // to reset it to make sure we apply affinities to move any
2887 // existing activities from other tasks in to it.
2888 // If the caller has requested that the target task be
2889 // reset, then do so.
2890 if ((r.intent.getFlags()
2891 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2892 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002893 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002894 }
2895 }
2896 if (SHOW_APP_STARTING_ICON && doShow) {
2897 // Figure out if we are transitioning from another activity that is
2898 // "has the same starting icon" as the next one. This allows the
2899 // window manager to keep the previous window it had previously
2900 // created, if it still had one.
2901 HistoryRecord prev = mResumedActivity;
2902 if (prev != null) {
2903 // We don't want to reuse the previous starting preview if:
2904 // (1) The current activity is in a different task.
2905 if (prev.task != r.task) prev = null;
2906 // (2) The current activity is already displayed.
2907 else if (prev.nowVisible) prev = null;
2908 }
2909 mWindowManager.setAppStartingWindow(
2910 r, r.packageName, r.theme, r.nonLocalizedLabel,
2911 r.labelRes, r.icon, prev, showStartingIcon);
2912 }
2913 } else {
2914 // If this is the first activity, don't do any fancy animations,
2915 // because there is nothing for it to animate on top of.
2916 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2917 r.info.screenOrientation, r.fullscreen);
2918 }
2919 if (VALIDATE_TOKENS) {
2920 mWindowManager.validateAppTokens(mHistory);
2921 }
2922
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002923 if (doResume) {
2924 resumeTopActivityLocked(null);
2925 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002926 }
2927
2928 /**
2929 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002930 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2931 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 * an instance of that activity in the stack and, if found, finish all
2933 * activities on top of it and return the instance.
2934 *
2935 * @param newR Description of the new activity being started.
2936 * @return Returns the old activity that should be continue to be used,
2937 * or null if none was found.
2938 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002939 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002940 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002942
2943 // First find the requested task.
2944 while (i > 0) {
2945 i--;
2946 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2947 if (r.task.taskId == taskId) {
2948 i++;
2949 break;
2950 }
2951 }
2952
2953 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 while (i > 0) {
2955 i--;
2956 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2957 if (r.finishing) {
2958 continue;
2959 }
2960 if (r.task.taskId != taskId) {
2961 return null;
2962 }
2963 if (r.realActivity.equals(newR.realActivity)) {
2964 // Here it is! Now finish everything in front...
2965 HistoryRecord ret = r;
2966 if (doClear) {
2967 while (i < (mHistory.size()-1)) {
2968 i++;
2969 r = (HistoryRecord)mHistory.get(i);
2970 if (r.finishing) {
2971 continue;
2972 }
2973 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2974 null, "clear")) {
2975 i--;
2976 }
2977 }
2978 }
2979
2980 // Finally, if this is a normal launch mode (that is, not
2981 // expecting onNewIntent()), then we will finish the current
2982 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002983 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2984 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002986 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 if (index >= 0) {
2988 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2989 null, "clear");
2990 }
2991 return null;
2992 }
2993 }
2994
2995 return ret;
2996 }
2997 }
2998
2999 return null;
3000 }
3001
3002 /**
3003 * Find the activity in the history stack within the given task. Returns
3004 * the index within the history at which it's found, or < 0 if not found.
3005 */
3006 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3007 int i = mHistory.size();
3008 while (i > 0) {
3009 i--;
3010 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3011 if (candidate.task.taskId != task) {
3012 break;
3013 }
3014 if (candidate.realActivity.equals(r.realActivity)) {
3015 return i;
3016 }
3017 }
3018
3019 return -1;
3020 }
3021
3022 /**
3023 * Reorder the history stack so that the activity at the given index is
3024 * brought to the front.
3025 */
3026 private final HistoryRecord moveActivityToFrontLocked(int where) {
3027 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3028 int top = mHistory.size();
3029 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3030 mHistory.add(top, newTop);
3031 oldTop.frontOfTask = false;
3032 newTop.frontOfTask = true;
3033 return newTop;
3034 }
3035
3036 /**
3037 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3038 * method will be called at the proper time.
3039 */
3040 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3041 boolean sent = false;
3042 if (r.state == ActivityState.RESUMED
3043 && r.app != null && r.app.thread != null) {
3044 try {
3045 ArrayList<Intent> ar = new ArrayList<Intent>();
3046 ar.add(new Intent(intent));
3047 r.app.thread.scheduleNewIntent(ar, r);
3048 sent = true;
3049 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003050 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 }
3052 }
3053 if (!sent) {
3054 r.addNewIntentLocked(new Intent(intent));
3055 }
3056 }
3057
3058 private final void logStartActivity(int tag, HistoryRecord r,
3059 TaskRecord task) {
3060 EventLog.writeEvent(tag,
3061 System.identityHashCode(r), task.taskId,
3062 r.shortComponentName, r.intent.getAction(),
3063 r.intent.getType(), r.intent.getDataString(),
3064 r.intent.getFlags());
3065 }
3066
3067 private final int startActivityLocked(IApplicationThread caller,
3068 Intent intent, String resolvedType,
3069 Uri[] grantedUriPermissions,
3070 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3071 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003072 int callingPid, int callingUid, boolean onlyIfNeeded,
3073 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003074 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075
3076 HistoryRecord sourceRecord = null;
3077 HistoryRecord resultRecord = null;
3078 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003079 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003080 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3082 if (index >= 0) {
3083 sourceRecord = (HistoryRecord)mHistory.get(index);
3084 if (requestCode >= 0 && !sourceRecord.finishing) {
3085 resultRecord = sourceRecord;
3086 }
3087 }
3088 }
3089
3090 int launchFlags = intent.getFlags();
3091
3092 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3093 && sourceRecord != null) {
3094 // Transfer the result target from the source activity to the new
3095 // one being started, including any failures.
3096 if (requestCode >= 0) {
3097 return START_FORWARD_AND_REQUEST_CONFLICT;
3098 }
3099 resultRecord = sourceRecord.resultTo;
3100 resultWho = sourceRecord.resultWho;
3101 requestCode = sourceRecord.requestCode;
3102 sourceRecord.resultTo = null;
3103 if (resultRecord != null) {
3104 resultRecord.removeResultsLocked(
3105 sourceRecord, resultWho, requestCode);
3106 }
3107 }
3108
3109 int err = START_SUCCESS;
3110
3111 if (intent.getComponent() == null) {
3112 // We couldn't find a class that can handle the given Intent.
3113 // That's the end of that!
3114 err = START_INTENT_NOT_RESOLVED;
3115 }
3116
3117 if (err == START_SUCCESS && aInfo == null) {
3118 // We couldn't find the specific class specified in the Intent.
3119 // Also the end of the line.
3120 err = START_CLASS_NOT_FOUND;
3121 }
3122
3123 ProcessRecord callerApp = null;
3124 if (err == START_SUCCESS && caller != null) {
3125 callerApp = getRecordForAppLocked(caller);
3126 if (callerApp != null) {
3127 callingPid = callerApp.pid;
3128 callingUid = callerApp.info.uid;
3129 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003130 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003131 + " (pid=" + callingPid + ") when starting: "
3132 + intent.toString());
3133 err = START_PERMISSION_DENIED;
3134 }
3135 }
3136
3137 if (err != START_SUCCESS) {
3138 if (resultRecord != null) {
3139 sendActivityResultLocked(-1,
3140 resultRecord, resultWho, requestCode,
3141 Activity.RESULT_CANCELED, null);
3142 }
3143 return err;
3144 }
3145
3146 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3147 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3148 if (perm != PackageManager.PERMISSION_GRANTED) {
3149 if (resultRecord != null) {
3150 sendActivityResultLocked(-1,
3151 resultRecord, resultWho, requestCode,
3152 Activity.RESULT_CANCELED, null);
3153 }
3154 String msg = "Permission Denial: starting " + intent.toString()
3155 + " from " + callerApp + " (pid=" + callingPid
3156 + ", uid=" + callingUid + ")"
3157 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003158 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 throw new SecurityException(msg);
3160 }
3161
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003162 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 boolean abort = false;
3164 try {
3165 // The Intent we give to the watcher has the extra data
3166 // stripped off, since it can contain private information.
3167 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003168 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003169 aInfo.applicationInfo.packageName);
3170 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003171 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003172 }
3173
3174 if (abort) {
3175 if (resultRecord != null) {
3176 sendActivityResultLocked(-1,
3177 resultRecord, resultWho, requestCode,
3178 Activity.RESULT_CANCELED, null);
3179 }
3180 // We pretend to the caller that it was really started, but
3181 // they will just get a cancel result.
3182 return START_SUCCESS;
3183 }
3184 }
3185
3186 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3187 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003188 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003190 if (mResumedActivity == null
3191 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3192 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3193 PendingActivityLaunch pal = new PendingActivityLaunch();
3194 pal.r = r;
3195 pal.sourceRecord = sourceRecord;
3196 pal.grantedUriPermissions = grantedUriPermissions;
3197 pal.grantedMode = grantedMode;
3198 pal.onlyIfNeeded = onlyIfNeeded;
3199 mPendingActivityLaunches.add(pal);
3200 return START_SWITCHES_CANCELED;
3201 }
3202 }
3203
3204 if (mDidAppSwitch) {
3205 // This is the second allowed switch since we stopped switches,
3206 // so now just generally allow switches. Use case: user presses
3207 // home (switches disabled, switch to home, mDidAppSwitch now true);
3208 // user taps a home icon (coming from home so allowed, we hit here
3209 // and now allow anyone to switch again).
3210 mAppSwitchesAllowedTime = 0;
3211 } else {
3212 mDidAppSwitch = true;
3213 }
3214
3215 doPendingActivityLaunchesLocked(false);
3216
3217 return startActivityUncheckedLocked(r, sourceRecord,
3218 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3219 }
3220
3221 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3222 final int N = mPendingActivityLaunches.size();
3223 if (N <= 0) {
3224 return;
3225 }
3226 for (int i=0; i<N; i++) {
3227 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3228 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3229 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3230 doResume && i == (N-1));
3231 }
3232 mPendingActivityLaunches.clear();
3233 }
3234
3235 private final int startActivityUncheckedLocked(HistoryRecord r,
3236 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3237 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3238 final Intent intent = r.intent;
3239 final int callingUid = r.launchedFromUid;
3240
3241 int launchFlags = intent.getFlags();
3242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003243 // We'll invoke onUserLeaving before onPause only if the launching
3244 // activity did not explicitly state that this is an automated launch.
3245 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003246 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003247 "startActivity() => mUserLeaving=" + mUserLeaving);
3248
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003249 // If the caller has asked not to resume at this point, we make note
3250 // of this in the record so that we can skip it when trying to find
3251 // the top running activity.
3252 if (!doResume) {
3253 r.delayedResume = true;
3254 }
3255
3256 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3257 != 0 ? r : null;
3258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003259 // If the onlyIfNeeded flag is set, then we can do this if the activity
3260 // being launched is the same as the one making the call... or, as
3261 // a special case, if we do not know the caller then we count the
3262 // current top activity as the caller.
3263 if (onlyIfNeeded) {
3264 HistoryRecord checkedCaller = sourceRecord;
3265 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003266 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 }
3268 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3269 // Caller is not the same as launcher, so always needed.
3270 onlyIfNeeded = false;
3271 }
3272 }
3273
3274 if (grantedUriPermissions != null && callingUid > 0) {
3275 for (int i=0; i<grantedUriPermissions.length; i++) {
3276 grantUriPermissionLocked(callingUid, r.packageName,
3277 grantedUriPermissions[i], grantedMode, r);
3278 }
3279 }
3280
3281 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3282 intent, r);
3283
3284 if (sourceRecord == null) {
3285 // This activity is not being started from another... in this
3286 // case we -always- start a new task.
3287 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003288 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 -08003289 + intent);
3290 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3291 }
3292 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3293 // The original activity who is starting us is running as a single
3294 // instance... this new activity it is starting must go on its
3295 // own task.
3296 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3297 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3298 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3299 // The activity being started is a single instance... it always
3300 // gets launched into its own task.
3301 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3302 }
3303
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003304 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 // For whatever reason this activity is being launched into a new
3306 // task... yet the caller has requested a result back. Well, that
3307 // is pretty messed up, so instead immediately send back a cancel
3308 // and let the new task continue launched as normal without a
3309 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003310 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003312 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 Activity.RESULT_CANCELED, null);
3314 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 }
3316
3317 boolean addingToTask = false;
3318 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3319 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3320 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3321 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3322 // If bring to front is requested, and no result is requested, and
3323 // we can find a task that was started with this same
3324 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003325 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003326 // See if there is a task to bring to the front. If this is
3327 // a SINGLE_INSTANCE activity, there can be one and only one
3328 // instance of it in the history, and it is always in its own
3329 // unique task, so we do a special search.
3330 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3331 ? findTaskLocked(intent, r.info)
3332 : findActivityLocked(intent, r.info);
3333 if (taskTop != null) {
3334 if (taskTop.task.intent == null) {
3335 // This task was started because of movement of
3336 // the activity based on affinity... now that we
3337 // are actually launching it, we can assign the
3338 // base intent.
3339 taskTop.task.setIntent(intent, r.info);
3340 }
3341 // If the target task is not in the front, then we need
3342 // to bring it to the front... except... well, with
3343 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3344 // to have the same behavior as if a new instance was
3345 // being started, which means not bringing it to the front
3346 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003347 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 if (curTop.task != taskTop.task) {
3349 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3350 boolean callerAtFront = sourceRecord == null
3351 || curTop.task == sourceRecord.task;
3352 if (callerAtFront) {
3353 // We really do want to push this one into the
3354 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003355 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003356 }
3357 }
3358 // If the caller has requested that the target task be
3359 // reset, then do so.
3360 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3361 taskTop = resetTaskIfNeededLocked(taskTop, r);
3362 }
3363 if (onlyIfNeeded) {
3364 // We don't need to start a new activity, and
3365 // the client said not to do anything if that
3366 // is the case, so this is it! And for paranoia, make
3367 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003368 if (doResume) {
3369 resumeTopActivityLocked(null);
3370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371 return START_RETURN_INTENT_TO_CALLER;
3372 }
3373 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3374 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3375 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3376 // In this situation we want to remove all activities
3377 // from the task up to the one being started. In most
3378 // cases this means we are resetting the task to its
3379 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003380 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003381 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 if (top != null) {
3383 if (top.frontOfTask) {
3384 // Activity aliases may mean we use different
3385 // intents for the top activity, so make sure
3386 // the task now has the identity of the new
3387 // intent.
3388 top.task.setIntent(r.intent, r.info);
3389 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003390 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 deliverNewIntentLocked(top, r.intent);
3392 } else {
3393 // A special case: we need to
3394 // start the activity because it is not currently
3395 // running, and the caller has asked to clear the
3396 // current task to have this activity at the top.
3397 addingToTask = true;
3398 // Now pretend like this activity is being started
3399 // by the top of its task, so it is put in the
3400 // right place.
3401 sourceRecord = taskTop;
3402 }
3403 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3404 // In this case the top activity on the task is the
3405 // same as the one being launched, so we take that
3406 // as a request to bring the task to the foreground.
3407 // If the top activity in the task is the root
3408 // activity, deliver this new intent to it if it
3409 // desires.
3410 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3411 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003412 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003413 if (taskTop.frontOfTask) {
3414 taskTop.task.setIntent(r.intent, r.info);
3415 }
3416 deliverNewIntentLocked(taskTop, r.intent);
3417 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3418 // In this case we are launching the root activity
3419 // of the task, but with a different intent. We
3420 // should start a new instance on top.
3421 addingToTask = true;
3422 sourceRecord = taskTop;
3423 }
3424 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3425 // In this case an activity is being launched in to an
3426 // existing task, without resetting that task. This
3427 // is typically the situation of launching an activity
3428 // from a notification or shortcut. We want to place
3429 // the new activity on top of the current task.
3430 addingToTask = true;
3431 sourceRecord = taskTop;
3432 } else if (!taskTop.task.rootWasReset) {
3433 // In this case we are launching in to an existing task
3434 // that has not yet been started from its front door.
3435 // The current task has been brought to the front.
3436 // Ideally, we'd probably like to place this new task
3437 // at the bottom of its stack, but that's a little hard
3438 // to do with the current organization of the code so
3439 // for now we'll just drop it.
3440 taskTop.task.setIntent(r.intent, r.info);
3441 }
3442 if (!addingToTask) {
3443 // We didn't do anything... but it was needed (a.k.a., client
3444 // don't use that intent!) And for paranoia, make
3445 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003446 if (doResume) {
3447 resumeTopActivityLocked(null);
3448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 return START_TASK_TO_FRONT;
3450 }
3451 }
3452 }
3453 }
3454
3455 //String uri = r.intent.toURI();
3456 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003457 //Slog.i(TAG, "Given intent: " + r.intent);
3458 //Slog.i(TAG, "URI is: " + uri);
3459 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460
3461 if (r.packageName != null) {
3462 // If the activity being launched is the same as the one currently
3463 // at the top, then we need to check if it should only be launched
3464 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003465 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3466 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003467 if (top.realActivity.equals(r.realActivity)) {
3468 if (top.app != null && top.app.thread != null) {
3469 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3470 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3471 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003472 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 // For paranoia, make sure we have correctly
3474 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003475 if (doResume) {
3476 resumeTopActivityLocked(null);
3477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 if (onlyIfNeeded) {
3479 // We don't need to start a new activity, and
3480 // the client said not to do anything if that
3481 // is the case, so this is it!
3482 return START_RETURN_INTENT_TO_CALLER;
3483 }
3484 deliverNewIntentLocked(top, r.intent);
3485 return START_DELIVERED_TO_TOP;
3486 }
3487 }
3488 }
3489 }
3490
3491 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003492 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003493 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003494 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 Activity.RESULT_CANCELED, null);
3496 }
3497 return START_CLASS_NOT_FOUND;
3498 }
3499
3500 boolean newTask = false;
3501
3502 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003503 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3505 // todo: should do better management of integers.
3506 mCurTask++;
3507 if (mCurTask <= 0) {
3508 mCurTask = 1;
3509 }
3510 r.task = new TaskRecord(mCurTask, r.info, intent,
3511 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003512 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 + " in new task " + r.task);
3514 newTask = true;
3515 addRecentTask(r.task);
3516
3517 } else if (sourceRecord != null) {
3518 if (!addingToTask &&
3519 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3520 // In this case, we are adding the activity to an existing
3521 // task, but the caller has asked to clear that task if the
3522 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003523 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003524 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003525 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003526 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003527 deliverNewIntentLocked(top, r.intent);
3528 // For paranoia, make sure we have correctly
3529 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003530 if (doResume) {
3531 resumeTopActivityLocked(null);
3532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 return START_DELIVERED_TO_TOP;
3534 }
3535 } else if (!addingToTask &&
3536 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3537 // In this case, we are launching an activity in our own task
3538 // that may already be running somewhere in the history, and
3539 // we want to shuffle it to the front of the stack if so.
3540 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3541 if (where >= 0) {
3542 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003543 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003544 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003545 if (doResume) {
3546 resumeTopActivityLocked(null);
3547 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 return START_DELIVERED_TO_TOP;
3549 }
3550 }
3551 // An existing activity is starting this new activity, so we want
3552 // to keep the new one in the same task as the one that is starting
3553 // it.
3554 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003555 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 + " in existing task " + r.task);
3557
3558 } else {
3559 // This not being started from an existing activity, and not part
3560 // of a new task... just put it in the top task, though these days
3561 // this case should never happen.
3562 final int N = mHistory.size();
3563 HistoryRecord prev =
3564 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3565 r.task = prev != null
3566 ? prev.task
3567 : new TaskRecord(mCurTask, r.info, intent,
3568 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003569 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 + " in new guessed " + r.task);
3571 }
3572 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003573 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003574 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003575 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003576 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 return START_SUCCESS;
3578 }
3579
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003580 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3581 long thisTime, long totalTime) {
3582 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3583 WaitResult w = mWaitingActivityLaunched.get(i);
3584 w.timeout = timeout;
3585 if (r != null) {
3586 w.who = new ComponentName(r.info.packageName, r.info.name);
3587 }
3588 w.thisTime = thisTime;
3589 w.totalTime = totalTime;
3590 }
3591 notify();
3592 }
3593
3594 void reportActivityVisibleLocked(HistoryRecord r) {
3595 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3596 WaitResult w = mWaitingActivityVisible.get(i);
3597 w.timeout = false;
3598 if (r != null) {
3599 w.who = new ComponentName(r.info.packageName, r.info.name);
3600 }
3601 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3602 w.thisTime = w.totalTime;
3603 }
3604 notify();
3605 }
3606
3607 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3609 int grantedMode, IBinder resultTo,
3610 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003611 boolean debug, WaitResult outResult) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003612 // Refuse possible leaked file descriptors
3613 if (intent != null && intent.hasFileDescriptors()) {
3614 throw new IllegalArgumentException("File descriptors passed in Intent");
3615 }
3616
The Android Open Source Project4df24232009-03-05 14:34:35 -08003617 final boolean componentSpecified = intent.getComponent() != null;
3618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619 // Don't modify the client's object!
3620 intent = new Intent(intent);
3621
3622 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003623 ActivityInfo aInfo;
3624 try {
3625 ResolveInfo rInfo =
3626 ActivityThread.getPackageManager().resolveIntent(
3627 intent, resolvedType,
3628 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003629 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 aInfo = rInfo != null ? rInfo.activityInfo : null;
3631 } catch (RemoteException e) {
3632 aInfo = null;
3633 }
3634
3635 if (aInfo != null) {
3636 // Store the found target back into the intent, because now that
3637 // we have it we never want to do this again. For example, if the
3638 // user navigates back to this point in the history, we should
3639 // always restart the exact same activity.
3640 intent.setComponent(new ComponentName(
3641 aInfo.applicationInfo.packageName, aInfo.name));
3642
3643 // Don't debug things in the system process
3644 if (debug) {
3645 if (!aInfo.processName.equals("system")) {
3646 setDebugApp(aInfo.processName, true, false);
3647 }
3648 }
3649 }
3650
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003651 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003652 int callingPid;
3653 int callingUid;
3654 if (caller == null) {
3655 callingPid = Binder.getCallingPid();
3656 callingUid = Binder.getCallingUid();
3657 } else {
3658 callingPid = callingUid = -1;
3659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 final long origId = Binder.clearCallingIdentity();
3661 int res = startActivityLocked(caller, intent, resolvedType,
3662 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003663 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003664 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003666
3667 if (outResult != null) {
3668 outResult.result = res;
3669 if (res == IActivityManager.START_SUCCESS) {
3670 mWaitingActivityLaunched.add(outResult);
3671 do {
3672 try {
3673 wait();
3674 } catch (InterruptedException e) {
3675 }
3676 } while (!outResult.timeout && outResult.who == null);
3677 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3678 HistoryRecord r = this.topRunningActivityLocked(null);
3679 if (r.nowVisible) {
3680 outResult.timeout = false;
3681 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3682 outResult.totalTime = 0;
3683 outResult.thisTime = 0;
3684 } else {
3685 outResult.thisTime = SystemClock.uptimeMillis();
3686 mWaitingActivityVisible.add(outResult);
3687 do {
3688 try {
3689 wait();
3690 } catch (InterruptedException e) {
3691 }
3692 } while (!outResult.timeout && outResult.who == null);
3693 }
3694 }
3695 }
3696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 return res;
3698 }
3699 }
3700
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003701 public final int startActivity(IApplicationThread caller,
3702 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3703 int grantedMode, IBinder resultTo,
3704 String resultWho, int requestCode, boolean onlyIfNeeded,
3705 boolean debug) {
3706 return startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3707 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, null);
3708 }
3709
3710 public final WaitResult startActivityAndWait(IApplicationThread caller,
3711 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3712 int grantedMode, IBinder resultTo,
3713 String resultWho, int requestCode, boolean onlyIfNeeded,
3714 boolean debug) {
3715 WaitResult res = new WaitResult();
3716 startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3717 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, res);
3718 return res;
3719 }
3720
3721 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003722 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003723 IBinder resultTo, String resultWho, int requestCode,
3724 int flagsMask, int flagsValues) {
3725 // Refuse possible leaked file descriptors
3726 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3727 throw new IllegalArgumentException("File descriptors passed in Intent");
3728 }
3729
3730 IIntentSender sender = intent.getTarget();
3731 if (!(sender instanceof PendingIntentRecord)) {
3732 throw new IllegalArgumentException("Bad PendingIntent object");
3733 }
3734
3735 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003736
3737 synchronized (this) {
3738 // If this is coming from the currently resumed activity, it is
3739 // effectively saying that app switches are allowed at this point.
3740 if (mResumedActivity != null
3741 && mResumedActivity.info.applicationInfo.uid ==
3742 Binder.getCallingUid()) {
3743 mAppSwitchesAllowedTime = 0;
3744 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003745 }
3746
3747 return pir.sendInner(0, fillInIntent, resolvedType,
3748 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3749 }
3750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 public boolean startNextMatchingActivity(IBinder callingActivity,
3752 Intent intent) {
3753 // Refuse possible leaked file descriptors
3754 if (intent != null && intent.hasFileDescriptors() == true) {
3755 throw new IllegalArgumentException("File descriptors passed in Intent");
3756 }
3757
3758 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003759 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 if (index < 0) {
3761 return false;
3762 }
3763 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3764 if (r.app == null || r.app.thread == null) {
3765 // The caller is not running... d'oh!
3766 return false;
3767 }
3768 intent = new Intent(intent);
3769 // The caller is not allowed to change the data.
3770 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3771 // And we are resetting to find the next component...
3772 intent.setComponent(null);
3773
3774 ActivityInfo aInfo = null;
3775 try {
3776 List<ResolveInfo> resolves =
3777 ActivityThread.getPackageManager().queryIntentActivities(
3778 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003779 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780
3781 // Look for the original activity in the list...
3782 final int N = resolves != null ? resolves.size() : 0;
3783 for (int i=0; i<N; i++) {
3784 ResolveInfo rInfo = resolves.get(i);
3785 if (rInfo.activityInfo.packageName.equals(r.packageName)
3786 && rInfo.activityInfo.name.equals(r.info.name)) {
3787 // We found the current one... the next matching is
3788 // after it.
3789 i++;
3790 if (i<N) {
3791 aInfo = resolves.get(i).activityInfo;
3792 }
3793 break;
3794 }
3795 }
3796 } catch (RemoteException e) {
3797 }
3798
3799 if (aInfo == null) {
3800 // Nobody who is next!
3801 return false;
3802 }
3803
3804 intent.setComponent(new ComponentName(
3805 aInfo.applicationInfo.packageName, aInfo.name));
3806 intent.setFlags(intent.getFlags()&~(
3807 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3808 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3809 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3810 Intent.FLAG_ACTIVITY_NEW_TASK));
3811
3812 // Okay now we need to start the new activity, replacing the
3813 // currently running activity. This is a little tricky because
3814 // we want to start the new one as if the current one is finished,
3815 // but not finish the current one first so that there is no flicker.
3816 // And thus...
3817 final boolean wasFinishing = r.finishing;
3818 r.finishing = true;
3819
3820 // Propagate reply information over to the new activity.
3821 final HistoryRecord resultTo = r.resultTo;
3822 final String resultWho = r.resultWho;
3823 final int requestCode = r.requestCode;
3824 r.resultTo = null;
3825 if (resultTo != null) {
3826 resultTo.removeResultsLocked(r, resultWho, requestCode);
3827 }
3828
3829 final long origId = Binder.clearCallingIdentity();
3830 // XXX we are not dealing with propagating grantedUriPermissions...
3831 // those are not yet exposed to user code, so there is no need.
3832 int res = startActivityLocked(r.app.thread, intent,
3833 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003834 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 Binder.restoreCallingIdentity(origId);
3836
3837 r.finishing = wasFinishing;
3838 if (res != START_SUCCESS) {
3839 return false;
3840 }
3841 return true;
3842 }
3843 }
3844
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003845 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 Intent intent, String resolvedType, IBinder resultTo,
3847 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003848
3849 // This is so super not safe, that only the system (or okay root)
3850 // can do it.
3851 final int callingUid = Binder.getCallingUid();
3852 if (callingUid != 0 && callingUid != Process.myUid()) {
3853 throw new SecurityException(
3854 "startActivityInPackage only available to the system");
3855 }
3856
The Android Open Source Project4df24232009-03-05 14:34:35 -08003857 final boolean componentSpecified = intent.getComponent() != null;
3858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 // Don't modify the client's object!
3860 intent = new Intent(intent);
3861
3862 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 ActivityInfo aInfo;
3864 try {
3865 ResolveInfo rInfo =
3866 ActivityThread.getPackageManager().resolveIntent(
3867 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003868 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003869 aInfo = rInfo != null ? rInfo.activityInfo : null;
3870 } catch (RemoteException e) {
3871 aInfo = null;
3872 }
3873
3874 if (aInfo != null) {
3875 // Store the found target back into the intent, because now that
3876 // we have it we never want to do this again. For example, if the
3877 // user navigates back to this point in the history, we should
3878 // always restart the exact same activity.
3879 intent.setComponent(new ComponentName(
3880 aInfo.applicationInfo.packageName, aInfo.name));
3881 }
3882
3883 synchronized(this) {
3884 return startActivityLocked(null, intent, resolvedType,
3885 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003886 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003887 }
3888 }
3889
3890 private final void addRecentTask(TaskRecord task) {
3891 // Remove any existing entries that are the same kind of task.
3892 int N = mRecentTasks.size();
3893 for (int i=0; i<N; i++) {
3894 TaskRecord tr = mRecentTasks.get(i);
3895 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3896 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3897 mRecentTasks.remove(i);
3898 i--;
3899 N--;
3900 if (task.intent == null) {
3901 // If the new recent task we are adding is not fully
3902 // specified, then replace it with the existing recent task.
3903 task = tr;
3904 }
3905 }
3906 }
3907 if (N >= MAX_RECENT_TASKS) {
3908 mRecentTasks.remove(N-1);
3909 }
3910 mRecentTasks.add(0, task);
3911 }
3912
3913 public void setRequestedOrientation(IBinder token,
3914 int requestedOrientation) {
3915 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003916 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 if (index < 0) {
3918 return;
3919 }
3920 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3921 final long origId = Binder.clearCallingIdentity();
3922 mWindowManager.setAppOrientation(r, requestedOrientation);
3923 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003924 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 r.mayFreezeScreenLocked(r.app) ? r : null);
3926 if (config != null) {
3927 r.frozenBeforeDestroy = true;
3928 if (!updateConfigurationLocked(config, r)) {
3929 resumeTopActivityLocked(null);
3930 }
3931 }
3932 Binder.restoreCallingIdentity(origId);
3933 }
3934 }
3935
3936 public int getRequestedOrientation(IBinder token) {
3937 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003938 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003939 if (index < 0) {
3940 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3941 }
3942 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3943 return mWindowManager.getAppOrientation(r);
3944 }
3945 }
3946
3947 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003948 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003949 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3950 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3951 if (!r.finishing) {
3952 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3953 "no-history");
3954 }
3955 } else if (r.app != null && r.app.thread != null) {
3956 if (mFocusedActivity == r) {
3957 setFocusedActivityLocked(topRunningActivityLocked(null));
3958 }
3959 r.resumeKeyDispatchingLocked();
3960 try {
3961 r.stopped = false;
3962 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003963 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 TAG, "Stopping visible=" + r.visible + " for " + r);
3965 if (!r.visible) {
3966 mWindowManager.setAppVisibility(r, false);
3967 }
3968 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3969 } catch (Exception e) {
3970 // Maybe just ignore exceptions here... if the process
3971 // has crashed, our death notification will clean things
3972 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003973 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 // Just in case, assume it to be stopped.
3975 r.stopped = true;
3976 r.state = ActivityState.STOPPED;
3977 if (r.configDestroy) {
3978 destroyActivityLocked(r, true);
3979 }
3980 }
3981 }
3982 }
3983
3984 /**
3985 * @return Returns true if the activity is being finished, false if for
3986 * some reason it is being left as-is.
3987 */
3988 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3989 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003990 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003991 TAG, "Finishing activity: token=" + token
3992 + ", result=" + resultCode + ", data=" + resultData);
3993
Dianne Hackborn75b03852009-06-12 15:43:26 -07003994 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 if (index < 0) {
3996 return false;
3997 }
3998 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3999
4000 // Is this the last activity left?
4001 boolean lastActivity = true;
4002 for (int i=mHistory.size()-1; i>=0; i--) {
4003 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4004 if (!p.finishing && p != r) {
4005 lastActivity = false;
4006 break;
4007 }
4008 }
4009
4010 // If this is the last activity, but it is the home activity, then
4011 // just don't finish it.
4012 if (lastActivity) {
4013 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4014 return false;
4015 }
4016 }
4017
4018 finishActivityLocked(r, index, resultCode, resultData, reason);
4019 return true;
4020 }
4021
4022 /**
4023 * @return Returns true if this activity has been removed from the history
4024 * list, or false if it is still in the list and will be removed later.
4025 */
4026 private final boolean finishActivityLocked(HistoryRecord r, int index,
4027 int resultCode, Intent resultData, String reason) {
4028 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004029 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 return false;
4031 }
4032
4033 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004034 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035 System.identityHashCode(r),
4036 r.task.taskId, r.shortComponentName, reason);
4037 r.task.numActivities--;
4038 if (r.frontOfTask && index < (mHistory.size()-1)) {
4039 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4040 if (next.task == r.task) {
4041 next.frontOfTask = true;
4042 }
4043 }
4044
4045 r.pauseKeyDispatchingLocked();
4046 if (mFocusedActivity == r) {
4047 setFocusedActivityLocked(topRunningActivityLocked(null));
4048 }
4049
4050 // send the result
4051 HistoryRecord resultTo = r.resultTo;
4052 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004053 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004054 + " who=" + r.resultWho + " req=" + r.requestCode
4055 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004056 if (r.info.applicationInfo.uid > 0) {
4057 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4058 r.packageName, resultData, r);
4059 }
4060 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4061 resultData);
4062 r.resultTo = null;
4063 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004064 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004065
4066 // Make sure this HistoryRecord is not holding on to other resources,
4067 // because clients have remote IPC references to this object so we
4068 // can't assume that will go away and want to avoid circular IPC refs.
4069 r.results = null;
4070 r.pendingResults = null;
4071 r.newIntents = null;
4072 r.icicle = null;
4073
4074 if (mPendingThumbnails.size() > 0) {
4075 // There are clients waiting to receive thumbnails so, in case
4076 // this is an activity that someone is waiting for, add it
4077 // to the pending list so we can correctly update the clients.
4078 mCancelledThumbnails.add(r);
4079 }
4080
4081 if (mResumedActivity == r) {
4082 boolean endTask = index <= 0
4083 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004084 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085 "Prepare close transition: finishing " + r);
4086 mWindowManager.prepareAppTransition(endTask
4087 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4088 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4089
4090 // Tell window manager to prepare for this one to be removed.
4091 mWindowManager.setAppVisibility(r, false);
4092
4093 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004094 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4095 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004096 startPausingLocked(false, false);
4097 }
4098
4099 } else if (r.state != ActivityState.PAUSING) {
4100 // If the activity is PAUSING, we will complete the finish once
4101 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004102 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004103 return finishCurrentActivityLocked(r, index,
4104 FINISH_AFTER_PAUSE) == null;
4105 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004106 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 }
4108
4109 return false;
4110 }
4111
4112 private static final int FINISH_IMMEDIATELY = 0;
4113 private static final int FINISH_AFTER_PAUSE = 1;
4114 private static final int FINISH_AFTER_VISIBLE = 2;
4115
4116 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4117 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004118 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004119 if (index < 0) {
4120 return null;
4121 }
4122
4123 return finishCurrentActivityLocked(r, index, mode);
4124 }
4125
4126 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4127 int index, int mode) {
4128 // First things first: if this activity is currently visible,
4129 // and the resumed activity is not yet visible, then hold off on
4130 // finishing until the resumed one becomes visible.
4131 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4132 if (!mStoppingActivities.contains(r)) {
4133 mStoppingActivities.add(r);
4134 if (mStoppingActivities.size() > 3) {
4135 // If we already have a few activities waiting to stop,
4136 // then give up on things going idle and start clearing
4137 // them out.
4138 Message msg = Message.obtain();
4139 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4140 mHandler.sendMessage(msg);
4141 }
4142 }
4143 r.state = ActivityState.STOPPING;
4144 updateOomAdjLocked();
4145 return r;
4146 }
4147
4148 // make sure the record is cleaned out of other places.
4149 mStoppingActivities.remove(r);
4150 mWaitingVisibleActivities.remove(r);
4151 if (mResumedActivity == r) {
4152 mResumedActivity = null;
4153 }
4154 final ActivityState prevState = r.state;
4155 r.state = ActivityState.FINISHING;
4156
4157 if (mode == FINISH_IMMEDIATELY
4158 || prevState == ActivityState.STOPPED
4159 || prevState == ActivityState.INITIALIZING) {
4160 // If this activity is already stopped, we can just finish
4161 // it right now.
4162 return destroyActivityLocked(r, true) ? null : r;
4163 } else {
4164 // Need to go through the full pause cycle to get this
4165 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004166 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004167 mFinishingActivities.add(r);
4168 resumeTopActivityLocked(null);
4169 }
4170 return r;
4171 }
4172
4173 /**
4174 * This is the internal entry point for handling Activity.finish().
4175 *
4176 * @param token The Binder token referencing the Activity we want to finish.
4177 * @param resultCode Result code, if any, from this Activity.
4178 * @param resultData Result data (Intent), if any, from this Activity.
4179 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004180 * @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 -08004181 */
4182 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4183 // Refuse possible leaked file descriptors
4184 if (resultData != null && resultData.hasFileDescriptors() == true) {
4185 throw new IllegalArgumentException("File descriptors passed in Intent");
4186 }
4187
4188 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004189 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 // Find the first activity that is not finishing.
4191 HistoryRecord next = topRunningActivityLocked(token, 0);
4192 if (next != null) {
4193 // ask watcher if this is allowed
4194 boolean resumeOK = true;
4195 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004196 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004198 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004199 }
4200
4201 if (!resumeOK) {
4202 return false;
4203 }
4204 }
4205 }
4206 final long origId = Binder.clearCallingIdentity();
4207 boolean res = requestFinishActivityLocked(token, resultCode,
4208 resultData, "app-request");
4209 Binder.restoreCallingIdentity(origId);
4210 return res;
4211 }
4212 }
4213
4214 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4215 String resultWho, int requestCode, int resultCode, Intent data) {
4216
4217 if (callingUid > 0) {
4218 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4219 data, r);
4220 }
4221
Joe Onorato8a9b2202010-02-26 18:56:32 -08004222 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004223 + " : who=" + resultWho + " req=" + requestCode
4224 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4226 try {
4227 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4228 list.add(new ResultInfo(resultWho, requestCode,
4229 resultCode, data));
4230 r.app.thread.scheduleSendResult(r, list);
4231 return;
4232 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004233 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 }
4235 }
4236
4237 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4238 }
4239
4240 public final void finishSubActivity(IBinder token, String resultWho,
4241 int requestCode) {
4242 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004243 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004244 if (index < 0) {
4245 return;
4246 }
4247 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4248
4249 final long origId = Binder.clearCallingIdentity();
4250
4251 int i;
4252 for (i=mHistory.size()-1; i>=0; i--) {
4253 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4254 if (r.resultTo == self && r.requestCode == requestCode) {
4255 if ((r.resultWho == null && resultWho == null) ||
4256 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4257 finishActivityLocked(r, i,
4258 Activity.RESULT_CANCELED, null, "request-sub");
4259 }
4260 }
4261 }
4262
4263 Binder.restoreCallingIdentity(origId);
4264 }
4265 }
4266
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004267 public void overridePendingTransition(IBinder token, String packageName,
4268 int enterAnim, int exitAnim) {
4269 synchronized(this) {
4270 int index = indexOfTokenLocked(token);
4271 if (index < 0) {
4272 return;
4273 }
4274 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4275
4276 final long origId = Binder.clearCallingIdentity();
4277
4278 if (self.state == ActivityState.RESUMED
4279 || self.state == ActivityState.PAUSING) {
4280 mWindowManager.overridePendingAppTransition(packageName,
4281 enterAnim, exitAnim);
4282 }
4283
4284 Binder.restoreCallingIdentity(origId);
4285 }
4286 }
4287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004288 /**
4289 * Perform clean-up of service connections in an activity record.
4290 */
4291 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4292 // Throw away any services that have been bound by this activity.
4293 if (r.connections != null) {
4294 Iterator<ConnectionRecord> it = r.connections.iterator();
4295 while (it.hasNext()) {
4296 ConnectionRecord c = it.next();
4297 removeConnectionLocked(c, null, r);
4298 }
4299 r.connections = null;
4300 }
4301 }
4302
4303 /**
4304 * Perform the common clean-up of an activity record. This is called both
4305 * as part of destroyActivityLocked() (when destroying the client-side
4306 * representation) and cleaning things up as a result of its hosting
4307 * processing going away, in which case there is no remaining client-side
4308 * state to destroy so only the cleanup here is needed.
4309 */
4310 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4311 if (mResumedActivity == r) {
4312 mResumedActivity = null;
4313 }
4314 if (mFocusedActivity == r) {
4315 mFocusedActivity = null;
4316 }
4317
4318 r.configDestroy = false;
4319 r.frozenBeforeDestroy = false;
4320
4321 // Make sure this record is no longer in the pending finishes list.
4322 // This could happen, for example, if we are trimming activities
4323 // down to the max limit while they are still waiting to finish.
4324 mFinishingActivities.remove(r);
4325 mWaitingVisibleActivities.remove(r);
4326
4327 // Remove any pending results.
4328 if (r.finishing && r.pendingResults != null) {
4329 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4330 PendingIntentRecord rec = apr.get();
4331 if (rec != null) {
4332 cancelIntentSenderLocked(rec, false);
4333 }
4334 }
4335 r.pendingResults = null;
4336 }
4337
4338 if (cleanServices) {
4339 cleanUpActivityServicesLocked(r);
4340 }
4341
4342 if (mPendingThumbnails.size() > 0) {
4343 // There are clients waiting to receive thumbnails so, in case
4344 // this is an activity that someone is waiting for, add it
4345 // to the pending list so we can correctly update the clients.
4346 mCancelledThumbnails.add(r);
4347 }
4348
4349 // Get rid of any pending idle timeouts.
4350 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4351 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4352 }
4353
4354 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4355 if (r.state != ActivityState.DESTROYED) {
4356 mHistory.remove(r);
4357 r.inHistory = false;
4358 r.state = ActivityState.DESTROYED;
4359 mWindowManager.removeAppToken(r);
4360 if (VALIDATE_TOKENS) {
4361 mWindowManager.validateAppTokens(mHistory);
4362 }
4363 cleanUpActivityServicesLocked(r);
4364 removeActivityUriPermissionsLocked(r);
4365 }
4366 }
4367
4368 /**
4369 * Destroy the current CLIENT SIDE instance of an activity. This may be
4370 * called both when actually finishing an activity, or when performing
4371 * a configuration switch where we destroy the current client-side object
4372 * but then create a new client-side object for this same HistoryRecord.
4373 */
4374 private final boolean destroyActivityLocked(HistoryRecord r,
4375 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004376 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004377 TAG, "Removing activity: token=" + r
4378 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004379 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 System.identityHashCode(r),
4381 r.task.taskId, r.shortComponentName);
4382
4383 boolean removedFromHistory = false;
4384
4385 cleanUpActivityLocked(r, false);
4386
Dianne Hackborn03abb812010-01-04 18:43:19 -08004387 final boolean hadApp = r.app != null;
4388
4389 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004390 if (removeFromApp) {
4391 int idx = r.app.activities.indexOf(r);
4392 if (idx >= 0) {
4393 r.app.activities.remove(idx);
4394 }
4395 if (r.persistent) {
4396 decPersistentCountLocked(r.app);
4397 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004398 if (r.app.activities.size() == 0) {
4399 // No longer have activities, so update location in
4400 // LRU list.
4401 updateLruProcessLocked(r.app, true, false);
4402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 }
4404
4405 boolean skipDestroy = false;
4406
4407 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004408 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004409 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4410 r.configChangeFlags);
4411 } catch (Exception e) {
4412 // We can just ignore exceptions here... if the process
4413 // has crashed, our death notification will clean things
4414 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004415 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416 if (r.finishing) {
4417 removeActivityFromHistoryLocked(r);
4418 removedFromHistory = true;
4419 skipDestroy = true;
4420 }
4421 }
4422
4423 r.app = null;
4424 r.nowVisible = false;
4425
4426 if (r.finishing && !skipDestroy) {
4427 r.state = ActivityState.DESTROYING;
4428 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4429 msg.obj = r;
4430 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4431 } else {
4432 r.state = ActivityState.DESTROYED;
4433 }
4434 } else {
4435 // remove this record from the history.
4436 if (r.finishing) {
4437 removeActivityFromHistoryLocked(r);
4438 removedFromHistory = true;
4439 } else {
4440 r.state = ActivityState.DESTROYED;
4441 }
4442 }
4443
4444 r.configChangeFlags = 0;
4445
Dianne Hackborn03abb812010-01-04 18:43:19 -08004446 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004447 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004448 }
4449
4450 return removedFromHistory;
4451 }
4452
Dianne Hackborn03abb812010-01-04 18:43:19 -08004453 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004454 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004455 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 TAG, "Removing app " + app + " from list " + list
4457 + " with " + i + " entries");
4458 while (i > 0) {
4459 i--;
4460 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004461 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004462 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4463 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004464 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 list.remove(i);
4466 }
4467 }
4468 }
4469
4470 /**
4471 * Main function for removing an existing process from the activity manager
4472 * as a result of that process going away. Clears out all connections
4473 * to the process.
4474 */
4475 private final void handleAppDiedLocked(ProcessRecord app,
4476 boolean restarting) {
4477 cleanUpApplicationRecordLocked(app, restarting, -1);
4478 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004479 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 }
4481
4482 // Just in case...
4483 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004484 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 mPausingActivity = null;
4486 }
4487 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4488 mLastPausedActivity = null;
4489 }
4490
4491 // Remove this application's activities from active lists.
4492 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4493 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4494 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4495 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4496
4497 boolean atTop = true;
4498 boolean hasVisibleActivities = false;
4499
4500 // Clean out the history list.
4501 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004502 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 TAG, "Removing app " + app + " from history with " + i + " entries");
4504 while (i > 0) {
4505 i--;
4506 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004507 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4509 if (r.app == app) {
4510 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004511 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 TAG, "Removing this entry! frozen=" + r.haveState
4513 + " finishing=" + r.finishing);
4514 mHistory.remove(i);
4515
4516 r.inHistory = false;
4517 mWindowManager.removeAppToken(r);
4518 if (VALIDATE_TOKENS) {
4519 mWindowManager.validateAppTokens(mHistory);
4520 }
4521 removeActivityUriPermissionsLocked(r);
4522
4523 } else {
4524 // We have the current state for this activity, so
4525 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004526 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 TAG, "Keeping entry, setting app to null");
4528 if (r.visible) {
4529 hasVisibleActivities = true;
4530 }
4531 r.app = null;
4532 r.nowVisible = false;
4533 if (!r.haveState) {
4534 r.icicle = null;
4535 }
4536 }
4537
4538 cleanUpActivityLocked(r, true);
4539 r.state = ActivityState.STOPPED;
4540 }
4541 atTop = false;
4542 }
4543
4544 app.activities.clear();
4545
4546 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004547 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004548 + " running instrumentation " + app.instrumentationClass);
4549 Bundle info = new Bundle();
4550 info.putString("shortMsg", "Process crashed.");
4551 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4552 }
4553
4554 if (!restarting) {
4555 if (!resumeTopActivityLocked(null)) {
4556 // If there was nothing to resume, and we are not already
4557 // restarting this process, but there is a visible activity that
4558 // is hosted by the process... then make sure all visible
4559 // activities are running, taking care of restarting this
4560 // process.
4561 if (hasVisibleActivities) {
4562 ensureActivitiesVisibleLocked(null, 0);
4563 }
4564 }
4565 }
4566 }
4567
4568 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4569 IBinder threadBinder = thread.asBinder();
4570
4571 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004572 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4573 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004574 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4575 return i;
4576 }
4577 }
4578 return -1;
4579 }
4580
4581 private final ProcessRecord getRecordForAppLocked(
4582 IApplicationThread thread) {
4583 if (thread == null) {
4584 return null;
4585 }
4586
4587 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004588 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004589 }
4590
4591 private final void appDiedLocked(ProcessRecord app, int pid,
4592 IApplicationThread thread) {
4593
4594 mProcDeaths[0]++;
4595
Magnus Edlund7bb25812010-02-24 15:45:06 +01004596 // Clean up already done if the process has been re-started.
4597 if (app.pid == pid && app.thread != null &&
4598 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004599 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004600 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004601 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004602 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 TAG, "Dying app: " + app + ", pid: " + pid
4604 + ", thread: " + thread.asBinder());
4605 boolean doLowMem = app.instrumentationClass == null;
4606 handleAppDiedLocked(app, false);
4607
4608 if (doLowMem) {
4609 // If there are no longer any background processes running,
4610 // and the app that died was not running instrumentation,
4611 // then tell everyone we are now low on memory.
4612 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004613 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4614 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004615 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4616 haveBg = true;
4617 break;
4618 }
4619 }
4620
4621 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004622 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004623 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004624 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004625 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4626 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004627 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004628 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4629 // The low memory report is overriding any current
4630 // state for a GC request. Make sure to do
4631 // visible/foreground processes first.
4632 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4633 rec.lastRequestedGc = 0;
4634 } else {
4635 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004636 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004637 rec.reportLowMemory = true;
4638 rec.lastLowMemory = now;
4639 mProcessesToGc.remove(rec);
4640 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 }
4642 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004643 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 }
4645 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004646 } else if (app.pid != pid) {
4647 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004648 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004649 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004650 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004651 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004652 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 + thread.asBinder());
4654 }
4655 }
4656
Dan Egnor42471dd2010-01-07 17:25:22 -08004657 /**
4658 * If a stack trace dump file is configured, dump process stack traces.
4659 * @param pids of dalvik VM processes to dump stack traces for
4660 * @return file containing stack traces, or null if no dump file is configured
4661 */
4662 private static File dumpStackTraces(ArrayList<Integer> pids) {
4663 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4664 if (tracesPath == null || tracesPath.length() == 0) {
4665 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004667
4668 File tracesFile = new File(tracesPath);
4669 try {
4670 File tracesDir = tracesFile.getParentFile();
4671 if (!tracesDir.exists()) tracesFile.mkdirs();
4672 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4673
4674 if (tracesFile.exists()) tracesFile.delete();
4675 tracesFile.createNewFile();
4676 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4677 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004678 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004679 return null;
4680 }
4681
4682 // Use a FileObserver to detect when traces finish writing.
4683 // The order of traces is considered important to maintain for legibility.
4684 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4685 public synchronized void onEvent(int event, String path) { notify(); }
4686 };
4687
4688 try {
4689 observer.startWatching();
4690 int num = pids.size();
4691 for (int i = 0; i < num; i++) {
4692 synchronized (observer) {
4693 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4694 observer.wait(200); // Wait for write-close, give up after 200msec
4695 }
4696 }
4697 } catch (InterruptedException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004698 Slog.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004699 } finally {
4700 observer.stopWatching();
4701 }
4702
4703 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004704 }
4705
Dan Egnor42471dd2010-01-07 17:25:22 -08004706 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4707 HistoryRecord parent, final String annotation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004708 if (app.notResponding || app.crashing) {
4709 return;
4710 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004713 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4714 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715
Dan Egnor42471dd2010-01-07 17:25:22 -08004716 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4717 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4718 pids.add(app.pid);
4719
4720 int parentPid = app.pid;
4721 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4722 if (parentPid != app.pid) pids.add(parentPid);
4723
4724 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4725
4726 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4727 ProcessRecord r = mLruProcesses.get(i);
4728 if (r != null && r.thread != null) {
4729 int pid = r.pid;
4730 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004731 }
4732 }
4733
Dan Egnor42471dd2010-01-07 17:25:22 -08004734 File tracesFile = dumpStackTraces(pids);
4735
4736 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004737 StringBuilder info = mStringBuilder;
4738 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004739 info.append("ANR in ").append(app.processName);
4740 if (activity != null && activity.shortComponentName != null) {
4741 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004742 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004743 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004744 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004745 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004747 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004748 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750
Dan Egnor42471dd2010-01-07 17:25:22 -08004751 String cpuInfo = null;
4752 if (MONITOR_CPU_USAGE) {
4753 updateCpuStatsNow();
4754 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4755 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 }
4757
Joe Onorato8a9b2202010-02-26 18:56:32 -08004758 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004759 if (tracesFile == null) {
4760 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4761 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4762 }
4763
4764 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4765
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004766 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004768 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4769 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004771 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4772 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 }
4774 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004775 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004776 }
4777 }
4778
Dan Egnor42471dd2010-01-07 17:25:22 -08004779 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4780 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4781 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4782 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4783 Process.killProcess(app.pid);
4784 return;
4785 }
4786
4787 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 makeAppNotRespondingLocked(app,
4789 activity != null ? activity.shortComponentName : null,
4790 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004791 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004792
4793 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004794 Message msg = Message.obtain();
4795 HashMap map = new HashMap();
4796 msg.what = SHOW_NOT_RESPONDING_MSG;
4797 msg.obj = map;
4798 map.put("app", app);
4799 if (activity != null) {
4800 map.put("activity", activity);
4801 }
4802
4803 mHandler.sendMessage(msg);
4804 return;
4805 }
4806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004807 private final void decPersistentCountLocked(ProcessRecord app)
4808 {
4809 app.persistentActivities--;
4810 if (app.persistentActivities > 0) {
4811 // Still more of 'em...
4812 return;
4813 }
4814 if (app.persistent) {
4815 // Ah, but the application itself is persistent. Whatever!
4816 return;
4817 }
4818
4819 // App is no longer persistent... make sure it and the ones
4820 // following it in the LRU list have the correc oom_adj.
4821 updateOomAdjLocked();
4822 }
4823
4824 public void setPersistent(IBinder token, boolean isPersistent) {
4825 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4826 != PackageManager.PERMISSION_GRANTED) {
4827 String msg = "Permission Denial: setPersistent() from pid="
4828 + Binder.getCallingPid()
4829 + ", uid=" + Binder.getCallingUid()
4830 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004831 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 throw new SecurityException(msg);
4833 }
4834
4835 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004836 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837 if (index < 0) {
4838 return;
4839 }
4840 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4841 ProcessRecord app = r.app;
4842
Joe Onorato8a9b2202010-02-26 18:56:32 -08004843 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844 TAG, "Setting persistence " + isPersistent + ": " + r);
4845
4846 if (isPersistent) {
4847 if (r.persistent) {
4848 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004849 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004850 return;
4851 }
4852 r.persistent = true;
4853 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004854 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 if (app.persistentActivities > 1) {
4856 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004857 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 return;
4859 }
4860 if (app.persistent) {
4861 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004862 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 return;
4864 }
4865
4866 // App is now persistent... make sure it and the ones
4867 // following it now have the correct oom_adj.
4868 final long origId = Binder.clearCallingIdentity();
4869 updateOomAdjLocked();
4870 Binder.restoreCallingIdentity(origId);
4871
4872 } else {
4873 if (!r.persistent) {
4874 // Okay okay, I heard you already!
4875 return;
4876 }
4877 r.persistent = false;
4878 final long origId = Binder.clearCallingIdentity();
4879 decPersistentCountLocked(app);
4880 Binder.restoreCallingIdentity(origId);
4881
4882 }
4883 }
4884 }
4885
4886 public boolean clearApplicationUserData(final String packageName,
4887 final IPackageDataObserver observer) {
4888 int uid = Binder.getCallingUid();
4889 int pid = Binder.getCallingPid();
4890 long callingId = Binder.clearCallingIdentity();
4891 try {
4892 IPackageManager pm = ActivityThread.getPackageManager();
4893 int pkgUid = -1;
4894 synchronized(this) {
4895 try {
4896 pkgUid = pm.getPackageUid(packageName);
4897 } catch (RemoteException e) {
4898 }
4899 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004900 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004901 return false;
4902 }
4903 if (uid == pkgUid || checkComponentPermission(
4904 android.Manifest.permission.CLEAR_APP_USER_DATA,
4905 pid, uid, -1)
4906 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004907 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 } else {
4909 throw new SecurityException(pid+" does not have permission:"+
4910 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4911 "for process:"+packageName);
4912 }
4913 }
4914
4915 try {
4916 //clear application user data
4917 pm.clearApplicationUserData(packageName, observer);
4918 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4919 Uri.fromParts("package", packageName, null));
4920 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4921 broadcastIntentLocked(null, null, intent,
4922 null, null, 0, null, null, null,
4923 false, false, MY_PID, Process.SYSTEM_UID);
4924 } catch (RemoteException e) {
4925 }
4926 } finally {
4927 Binder.restoreCallingIdentity(callingId);
4928 }
4929 return true;
4930 }
4931
Dianne Hackborn03abb812010-01-04 18:43:19 -08004932 public void killBackgroundProcesses(final String packageName) {
4933 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4934 != PackageManager.PERMISSION_GRANTED &&
4935 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4936 != PackageManager.PERMISSION_GRANTED) {
4937 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004938 + Binder.getCallingPid()
4939 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004940 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004941 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 throw new SecurityException(msg);
4943 }
4944
4945 long callingId = Binder.clearCallingIdentity();
4946 try {
4947 IPackageManager pm = ActivityThread.getPackageManager();
4948 int pkgUid = -1;
4949 synchronized(this) {
4950 try {
4951 pkgUid = pm.getPackageUid(packageName);
4952 } catch (RemoteException e) {
4953 }
4954 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004955 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004956 return;
4957 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004958 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004959 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004960 }
4961 } finally {
4962 Binder.restoreCallingIdentity(callingId);
4963 }
4964 }
4965
4966 public void forceStopPackage(final String packageName) {
4967 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4968 != PackageManager.PERMISSION_GRANTED) {
4969 String msg = "Permission Denial: forceStopPackage() from pid="
4970 + Binder.getCallingPid()
4971 + ", uid=" + Binder.getCallingUid()
4972 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004973 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004974 throw new SecurityException(msg);
4975 }
4976
4977 long callingId = Binder.clearCallingIdentity();
4978 try {
4979 IPackageManager pm = ActivityThread.getPackageManager();
4980 int pkgUid = -1;
4981 synchronized(this) {
4982 try {
4983 pkgUid = pm.getPackageUid(packageName);
4984 } catch (RemoteException e) {
4985 }
4986 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004987 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004988 return;
4989 }
4990 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004991 }
4992 } finally {
4993 Binder.restoreCallingIdentity(callingId);
4994 }
4995 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004996
4997 /*
4998 * The pkg name and uid have to be specified.
4999 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5000 */
5001 public void killApplicationWithUid(String pkg, int uid) {
5002 if (pkg == null) {
5003 return;
5004 }
5005 // Make sure the uid is valid.
5006 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005007 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005008 return;
5009 }
5010 int callerUid = Binder.getCallingUid();
5011 // Only the system server can kill an application
5012 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005013 // Post an aysnc message to kill the application
5014 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5015 msg.arg1 = uid;
5016 msg.arg2 = 0;
5017 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005018 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005019 } else {
5020 throw new SecurityException(callerUid + " cannot kill pkg: " +
5021 pkg);
5022 }
5023 }
5024
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005025 public void closeSystemDialogs(String reason) {
5026 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5027 if (reason != null) {
5028 intent.putExtra("reason", reason);
5029 }
5030
5031 final int uid = Binder.getCallingUid();
5032 final long origId = Binder.clearCallingIdentity();
5033 synchronized (this) {
5034 int i = mWatchers.beginBroadcast();
5035 while (i > 0) {
5036 i--;
5037 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5038 if (w != null) {
5039 try {
5040 w.closingSystemDialogs(reason);
5041 } catch (RemoteException e) {
5042 }
5043 }
5044 }
5045 mWatchers.finishBroadcast();
5046
Dianne Hackbornffa42482009-09-23 22:20:11 -07005047 mWindowManager.closeSystemDialogs(reason);
5048
5049 for (i=mHistory.size()-1; i>=0; i--) {
5050 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5051 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5052 finishActivityLocked(r, i,
5053 Activity.RESULT_CANCELED, null, "close-sys");
5054 }
5055 }
5056
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005057 broadcastIntentLocked(null, null, intent, null,
5058 null, 0, null, null, null, false, false, -1, uid);
5059 }
5060 Binder.restoreCallingIdentity(origId);
5061 }
5062
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005063 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005064 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005065 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5066 for (int i=pids.length-1; i>=0; i--) {
5067 infos[i] = new Debug.MemoryInfo();
5068 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005069 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005070 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005071 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005072
5073 public void killApplicationProcess(String processName, int uid) {
5074 if (processName == null) {
5075 return;
5076 }
5077
5078 int callerUid = Binder.getCallingUid();
5079 // Only the system server can kill an application
5080 if (callerUid == Process.SYSTEM_UID) {
5081 synchronized (this) {
5082 ProcessRecord app = getProcessRecordLocked(processName, uid);
5083 if (app != null) {
5084 try {
5085 app.thread.scheduleSuicide();
5086 } catch (RemoteException e) {
5087 // If the other end already died, then our work here is done.
5088 }
5089 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005090 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005091 + processName + " / " + uid);
5092 }
5093 }
5094 } else {
5095 throw new SecurityException(callerUid + " cannot kill app process: " +
5096 processName);
5097 }
5098 }
5099
Dianne Hackborn03abb812010-01-04 18:43:19 -08005100 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005101 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5103 Uri.fromParts("package", packageName, null));
5104 intent.putExtra(Intent.EXTRA_UID, uid);
5105 broadcastIntentLocked(null, null, intent,
5106 null, null, 0, null, null, null,
5107 false, false, MY_PID, Process.SYSTEM_UID);
5108 }
5109
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005110 private final boolean killPackageProcessesLocked(String packageName, int uid,
5111 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005112 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113
Dianne Hackborn03abb812010-01-04 18:43:19 -08005114 // Remove all processes this package may have touched: all with the
5115 // same UID (except for the system or root user), and all whose name
5116 // matches the package name.
5117 final String procNamePrefix = packageName + ":";
5118 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5119 final int NA = apps.size();
5120 for (int ia=0; ia<NA; ia++) {
5121 ProcessRecord app = apps.valueAt(ia);
5122 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005123 if (doit) {
5124 procs.add(app);
5125 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005126 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5127 || app.processName.equals(packageName)
5128 || app.processName.startsWith(procNamePrefix)) {
5129 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005130 if (!doit) {
5131 return true;
5132 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005133 app.removed = true;
5134 procs.add(app);
5135 }
5136 }
5137 }
5138 }
5139
5140 int N = procs.size();
5141 for (int i=0; i<N; i++) {
5142 removeProcessLocked(procs.get(i), callerWillRestart);
5143 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005144 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005145 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005146
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005147 private final boolean forceStopPackageLocked(String name, int uid,
5148 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 int i, N;
5150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 if (uid < 0) {
5152 try {
5153 uid = ActivityThread.getPackageManager().getPackageUid(name);
5154 } catch (RemoteException e) {
5155 }
5156 }
5157
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005158 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005159 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005160
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005161 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5162 while (badApps.hasNext()) {
5163 SparseArray<Long> ba = badApps.next();
5164 if (ba.get(uid) != null) {
5165 badApps.remove();
5166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005167 }
5168 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005169
5170 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5171 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172
5173 for (i=mHistory.size()-1; i>=0; i--) {
5174 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5175 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005176 if (!doit) {
5177 return true;
5178 }
5179 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005180 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 if (r.app != null) {
5182 r.app.removed = true;
5183 }
5184 r.app = null;
5185 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5186 }
5187 }
5188
5189 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5190 for (ServiceRecord service : mServices.values()) {
5191 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005192 if (!doit) {
5193 return true;
5194 }
5195 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005196 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 if (service.app != null) {
5198 service.app.removed = true;
5199 }
5200 service.app = null;
5201 services.add(service);
5202 }
5203 }
5204
5205 N = services.size();
5206 for (i=0; i<N; i++) {
5207 bringDownServiceLocked(services.get(i), true);
5208 }
5209
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005210 if (doit) {
5211 if (purgeCache) {
5212 AttributeCache ac = AttributeCache.instance();
5213 if (ac != null) {
5214 ac.removePackage(name);
5215 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005216 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005217 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005218 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005219
5220 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005221 }
5222
5223 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5224 final String name = app.processName;
5225 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005226 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005227 TAG, "Force removing process " + app + " (" + name
5228 + "/" + uid + ")");
5229
5230 mProcessNames.remove(name, uid);
5231 boolean needRestart = false;
5232 if (app.pid > 0 && app.pid != MY_PID) {
5233 int pid = app.pid;
5234 synchronized (mPidsSelfLocked) {
5235 mPidsSelfLocked.remove(pid);
5236 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5237 }
5238 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005239 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 Process.killProcess(pid);
5241
5242 if (app.persistent) {
5243 if (!callerWillRestart) {
5244 addAppLocked(app.info);
5245 } else {
5246 needRestart = true;
5247 }
5248 }
5249 } else {
5250 mRemovedProcesses.add(app);
5251 }
5252
5253 return needRestart;
5254 }
5255
5256 private final void processStartTimedOutLocked(ProcessRecord app) {
5257 final int pid = app.pid;
5258 boolean gone = false;
5259 synchronized (mPidsSelfLocked) {
5260 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5261 if (knownApp != null && knownApp.thread == null) {
5262 mPidsSelfLocked.remove(pid);
5263 gone = true;
5264 }
5265 }
5266
5267 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005268 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005269 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005270 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005272 // Take care of any launching providers waiting for this process.
5273 checkAppInLaunchingProvidersLocked(app, true);
5274 // Take care of any services that are waiting for the process.
5275 for (int i=0; i<mPendingServices.size(); i++) {
5276 ServiceRecord sr = mPendingServices.get(i);
5277 if (app.info.uid == sr.appInfo.uid
5278 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005279 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005280 mPendingServices.remove(i);
5281 i--;
5282 bringDownServiceLocked(sr, true);
5283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005285 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005286 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005287 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005288 try {
5289 IBackupManager bm = IBackupManager.Stub.asInterface(
5290 ServiceManager.getService(Context.BACKUP_SERVICE));
5291 bm.agentDisconnected(app.info.packageName);
5292 } catch (RemoteException e) {
5293 // Can't happen; the backup manager is local
5294 }
5295 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005296 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005297 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005298 mPendingBroadcast = null;
5299 scheduleBroadcastsLocked();
5300 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005302 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005303 }
5304 }
5305
5306 private final boolean attachApplicationLocked(IApplicationThread thread,
5307 int pid) {
5308
5309 // Find the application record that is being attached... either via
5310 // the pid if we are running in multiple processes, or just pull the
5311 // next app record if we are emulating process with anonymous threads.
5312 ProcessRecord app;
5313 if (pid != MY_PID && pid >= 0) {
5314 synchronized (mPidsSelfLocked) {
5315 app = mPidsSelfLocked.get(pid);
5316 }
5317 } else if (mStartingProcesses.size() > 0) {
5318 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005319 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 } else {
5321 app = null;
5322 }
5323
5324 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005325 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005327 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 if (pid > 0 && pid != MY_PID) {
5329 Process.killProcess(pid);
5330 } else {
5331 try {
5332 thread.scheduleExit();
5333 } catch (Exception e) {
5334 // Ignore exceptions.
5335 }
5336 }
5337 return false;
5338 }
5339
5340 // If this application record is still attached to a previous
5341 // process, clean it up now.
5342 if (app.thread != null) {
5343 handleAppDiedLocked(app, true);
5344 }
5345
5346 // Tell the process all about itself.
5347
Joe Onorato8a9b2202010-02-26 18:56:32 -08005348 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 TAG, "Binding process pid " + pid + " to record " + app);
5350
5351 String processName = app.processName;
5352 try {
5353 thread.asBinder().linkToDeath(new AppDeathRecipient(
5354 app, pid, thread), 0);
5355 } catch (RemoteException e) {
5356 app.resetPackageList();
5357 startProcessLocked(app, "link fail", processName);
5358 return false;
5359 }
5360
Doug Zongker2bec3d42009-12-04 12:52:44 -08005361 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005362
5363 app.thread = thread;
5364 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005365 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5366 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005367 app.forcingToForeground = null;
5368 app.foregroundServices = false;
5369 app.debugging = false;
5370
5371 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5372
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005373 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5374 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005376 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005377 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005378 }
5379
Joe Onorato8a9b2202010-02-26 18:56:32 -08005380 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005381 TAG, "New app record " + app
5382 + " thread=" + thread.asBinder() + " pid=" + pid);
5383 try {
5384 int testMode = IApplicationThread.DEBUG_OFF;
5385 if (mDebugApp != null && mDebugApp.equals(processName)) {
5386 testMode = mWaitForDebugger
5387 ? IApplicationThread.DEBUG_WAIT
5388 : IApplicationThread.DEBUG_ON;
5389 app.debugging = true;
5390 if (mDebugTransient) {
5391 mDebugApp = mOrigDebugApp;
5392 mWaitForDebugger = mOrigWaitForDebugger;
5393 }
5394 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005395
Christopher Tate181fafa2009-05-14 11:12:14 -07005396 // If the app is being launched for restore or full backup, set it up specially
5397 boolean isRestrictedBackupMode = false;
5398 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5399 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5400 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5401 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005402
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005403 ensurePackageDexOpt(app.instrumentationInfo != null
5404 ? app.instrumentationInfo.packageName
5405 : app.info.packageName);
5406 if (app.instrumentationClass != null) {
5407 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005408 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005409 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005410 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005411 thread.bindApplication(processName, app.instrumentationInfo != null
5412 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005413 app.instrumentationClass, app.instrumentationProfileFile,
5414 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005415 isRestrictedBackupMode || !normalMode,
5416 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005417 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005418 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005419 } catch (Exception e) {
5420 // todo: Yikes! What should we do? For now we will try to
5421 // start another process, but that could easily get us in
5422 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005423 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424
5425 app.resetPackageList();
5426 startProcessLocked(app, "bind fail", processName);
5427 return false;
5428 }
5429
5430 // Remove this record from the list of starting applications.
5431 mPersistentStartingProcesses.remove(app);
5432 mProcessesOnHold.remove(app);
5433
5434 boolean badApp = false;
5435 boolean didSomething = false;
5436
5437 // See if the top visible activity is waiting to run in this process...
5438 HistoryRecord hr = topRunningActivityLocked(null);
5439 if (hr != null) {
5440 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5441 && processName.equals(hr.processName)) {
5442 try {
5443 if (realStartActivityLocked(hr, app, true, true)) {
5444 didSomething = true;
5445 }
5446 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005447 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005448 + hr.intent.getComponent().flattenToShortString(), e);
5449 badApp = true;
5450 }
5451 } else {
5452 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5453 }
5454 }
5455
5456 // Find any services that should be running in this process...
5457 if (!badApp && mPendingServices.size() > 0) {
5458 ServiceRecord sr = null;
5459 try {
5460 for (int i=0; i<mPendingServices.size(); i++) {
5461 sr = mPendingServices.get(i);
5462 if (app.info.uid != sr.appInfo.uid
5463 || !processName.equals(sr.processName)) {
5464 continue;
5465 }
5466
5467 mPendingServices.remove(i);
5468 i--;
5469 realStartServiceLocked(sr, app);
5470 didSomething = true;
5471 }
5472 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005473 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 + sr.shortName, e);
5475 badApp = true;
5476 }
5477 }
5478
5479 // Check if the next broadcast receiver is in this process...
5480 BroadcastRecord br = mPendingBroadcast;
5481 if (!badApp && br != null && br.curApp == app) {
5482 try {
5483 mPendingBroadcast = null;
5484 processCurBroadcastLocked(br, app);
5485 didSomething = true;
5486 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005487 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 + br.curComponent.flattenToShortString(), e);
5489 badApp = true;
5490 logBroadcastReceiverDiscard(br);
5491 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5492 br.resultExtras, br.resultAbort, true);
5493 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005494 // We need to reset the state if we fails to start the receiver.
5495 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005496 }
5497 }
5498
Christopher Tate181fafa2009-05-14 11:12:14 -07005499 // Check whether the next backup agent is in this process...
5500 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005501 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005502 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005503 try {
5504 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5505 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005506 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005507 e.printStackTrace();
5508 }
5509 }
5510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 if (badApp) {
5512 // todo: Also need to kill application to deal with all
5513 // kinds of exceptions.
5514 handleAppDiedLocked(app, false);
5515 return false;
5516 }
5517
5518 if (!didSomething) {
5519 updateOomAdjLocked();
5520 }
5521
5522 return true;
5523 }
5524
5525 public final void attachApplication(IApplicationThread thread) {
5526 synchronized (this) {
5527 int callingPid = Binder.getCallingPid();
5528 final long origId = Binder.clearCallingIdentity();
5529 attachApplicationLocked(thread, callingPid);
5530 Binder.restoreCallingIdentity(origId);
5531 }
5532 }
5533
Dianne Hackborne88846e2009-09-30 21:34:25 -07005534 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005536 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005537 Binder.restoreCallingIdentity(origId);
5538 }
5539
5540 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5541 boolean remove) {
5542 int N = mStoppingActivities.size();
5543 if (N <= 0) return null;
5544
5545 ArrayList<HistoryRecord> stops = null;
5546
5547 final boolean nowVisible = mResumedActivity != null
5548 && mResumedActivity.nowVisible
5549 && !mResumedActivity.waitingVisible;
5550 for (int i=0; i<N; i++) {
5551 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005552 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005553 + nowVisible + " waitingVisible=" + s.waitingVisible
5554 + " finishing=" + s.finishing);
5555 if (s.waitingVisible && nowVisible) {
5556 mWaitingVisibleActivities.remove(s);
5557 s.waitingVisible = false;
5558 if (s.finishing) {
5559 // If this activity is finishing, it is sitting on top of
5560 // everyone else but we now know it is no longer needed...
5561 // so get rid of it. Otherwise, we need to go through the
5562 // normal flow and hide it once we determine that it is
5563 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005564 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 mWindowManager.setAppVisibility(s, false);
5566 }
5567 }
5568 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005569 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005570 if (stops == null) {
5571 stops = new ArrayList<HistoryRecord>();
5572 }
5573 stops.add(s);
5574 mStoppingActivities.remove(i);
5575 N--;
5576 i--;
5577 }
5578 }
5579
5580 return stops;
5581 }
5582
5583 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005584 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005585 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 mWindowManager.enableScreenAfterBoot();
5587 }
5588
Dianne Hackborne88846e2009-09-30 21:34:25 -07005589 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5590 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005591 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005592
5593 ArrayList<HistoryRecord> stops = null;
5594 ArrayList<HistoryRecord> finishes = null;
5595 ArrayList<HistoryRecord> thumbnails = null;
5596 int NS = 0;
5597 int NF = 0;
5598 int NT = 0;
5599 IApplicationThread sendThumbnail = null;
5600 boolean booting = false;
5601 boolean enableScreen = false;
5602
5603 synchronized (this) {
5604 if (token != null) {
5605 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5606 }
5607
5608 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005609 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005610 if (index >= 0) {
5611 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5612
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005613 if (fromTimeout) {
5614 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5615 }
5616
Dianne Hackborne88846e2009-09-30 21:34:25 -07005617 // This is a hack to semi-deal with a race condition
5618 // in the client where it can be constructed with a
5619 // newer configuration from when we asked it to launch.
5620 // We'll update with whatever configuration it now says
5621 // it used to launch.
5622 if (config != null) {
5623 r.configuration = config;
5624 }
5625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005626 // No longer need to keep the device awake.
5627 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5628 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5629 mLaunchingActivity.release();
5630 }
5631
5632 // We are now idle. If someone is waiting for a thumbnail from
5633 // us, we can now deliver.
5634 r.idle = true;
5635 scheduleAppGcsLocked();
5636 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5637 sendThumbnail = r.app.thread;
5638 r.thumbnailNeeded = false;
5639 }
5640
5641 // If this activity is fullscreen, set up to hide those under it.
5642
Joe Onorato8a9b2202010-02-26 18:56:32 -08005643 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005644 ensureActivitiesVisibleLocked(null, 0);
5645
Joe Onorato8a9b2202010-02-26 18:56:32 -08005646 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 if (!mBooted && !fromTimeout) {
5648 mBooted = true;
5649 enableScreen = true;
5650 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005651
5652 } else if (fromTimeout) {
5653 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005654 }
5655
5656 // Atomically retrieve all of the other things to do.
5657 stops = processStoppingActivitiesLocked(true);
5658 NS = stops != null ? stops.size() : 0;
5659 if ((NF=mFinishingActivities.size()) > 0) {
5660 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5661 mFinishingActivities.clear();
5662 }
5663 if ((NT=mCancelledThumbnails.size()) > 0) {
5664 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5665 mCancelledThumbnails.clear();
5666 }
5667
5668 booting = mBooting;
5669 mBooting = false;
5670 }
5671
5672 int i;
5673
5674 // Send thumbnail if requested.
5675 if (sendThumbnail != null) {
5676 try {
5677 sendThumbnail.requestThumbnail(token);
5678 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005679 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005680 sendPendingThumbnail(null, token, null, null, true);
5681 }
5682 }
5683
5684 // Stop any activities that are scheduled to do so but have been
5685 // waiting for the next one to start.
5686 for (i=0; i<NS; i++) {
5687 HistoryRecord r = (HistoryRecord)stops.get(i);
5688 synchronized (this) {
5689 if (r.finishing) {
5690 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5691 } else {
5692 stopActivityLocked(r);
5693 }
5694 }
5695 }
5696
5697 // Finish any activities that are scheduled to do so but have been
5698 // waiting for the next one to start.
5699 for (i=0; i<NF; i++) {
5700 HistoryRecord r = (HistoryRecord)finishes.get(i);
5701 synchronized (this) {
5702 destroyActivityLocked(r, true);
5703 }
5704 }
5705
5706 // Report back to any thumbnail receivers.
5707 for (i=0; i<NT; i++) {
5708 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5709 sendPendingThumbnail(r, null, null, null, true);
5710 }
5711
5712 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005713 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 }
5715
5716 trimApplications();
5717 //dump();
5718 //mWindowManager.dump();
5719
5720 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005721 enableScreenAfterBoot();
5722 }
5723 }
5724
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005725 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005726 IntentFilter pkgFilter = new IntentFilter();
5727 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5728 pkgFilter.addDataScheme("package");
5729 mContext.registerReceiver(new BroadcastReceiver() {
5730 @Override
5731 public void onReceive(Context context, Intent intent) {
5732 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5733 if (pkgs != null) {
5734 for (String pkg : pkgs) {
5735 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5736 setResultCode(Activity.RESULT_OK);
5737 return;
5738 }
5739 }
5740 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005741 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005742 }, pkgFilter);
5743
5744 synchronized (this) {
5745 // Ensure that any processes we had put on hold are now started
5746 // up.
5747 final int NP = mProcessesOnHold.size();
5748 if (NP > 0) {
5749 ArrayList<ProcessRecord> procs =
5750 new ArrayList<ProcessRecord>(mProcessesOnHold);
5751 for (int ip=0; ip<NP; ip++) {
5752 this.startProcessLocked(procs.get(ip), "on-hold", null);
5753 }
5754 }
5755
5756 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5757 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005758 broadcastIntentLocked(null, null,
5759 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5760 null, null, 0, null, null,
5761 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5762 false, false, MY_PID, Process.SYSTEM_UID);
5763 }
5764 }
5765 }
5766
5767 final void ensureBootCompleted() {
5768 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005769 boolean enableScreen;
5770 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005771 booting = mBooting;
5772 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005773 enableScreen = !mBooted;
5774 mBooted = true;
5775 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005776
5777 if (booting) {
5778 finishBooting();
5779 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005780
5781 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005782 enableScreenAfterBoot();
5783 }
5784 }
5785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 public final void activityPaused(IBinder token, Bundle icicle) {
5787 // Refuse possible leaked file descriptors
5788 if (icicle != null && icicle.hasFileDescriptors()) {
5789 throw new IllegalArgumentException("File descriptors passed in Bundle");
5790 }
5791
5792 final long origId = Binder.clearCallingIdentity();
5793 activityPaused(token, icicle, false);
5794 Binder.restoreCallingIdentity(origId);
5795 }
5796
5797 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005798 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005799 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5800 + ", timeout=" + timeout);
5801
5802 HistoryRecord r = null;
5803
5804 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005805 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 if (index >= 0) {
5807 r = (HistoryRecord)mHistory.get(index);
5808 if (!timeout) {
5809 r.icicle = icicle;
5810 r.haveState = true;
5811 }
5812 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5813 if (mPausingActivity == r) {
5814 r.state = ActivityState.PAUSED;
5815 completePauseLocked();
5816 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005817 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818 System.identityHashCode(r), r.shortComponentName,
5819 mPausingActivity != null
5820 ? mPausingActivity.shortComponentName : "(none)");
5821 }
5822 }
5823 }
5824 }
5825
5826 public final void activityStopped(IBinder token, Bitmap thumbnail,
5827 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005828 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005829 TAG, "Activity stopped: token=" + token);
5830
5831 HistoryRecord r = null;
5832
5833 final long origId = Binder.clearCallingIdentity();
5834
5835 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005836 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005837 if (index >= 0) {
5838 r = (HistoryRecord)mHistory.get(index);
5839 r.thumbnail = thumbnail;
5840 r.description = description;
5841 r.stopped = true;
5842 r.state = ActivityState.STOPPED;
5843 if (!r.finishing) {
5844 if (r.configDestroy) {
5845 destroyActivityLocked(r, true);
5846 resumeTopActivityLocked(null);
5847 }
5848 }
5849 }
5850 }
5851
5852 if (r != null) {
5853 sendPendingThumbnail(r, null, null, null, false);
5854 }
5855
5856 trimApplications();
5857
5858 Binder.restoreCallingIdentity(origId);
5859 }
5860
5861 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005862 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 synchronized (this) {
5864 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5865
Dianne Hackborn75b03852009-06-12 15:43:26 -07005866 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005867 if (index >= 0) {
5868 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5869 if (r.state == ActivityState.DESTROYING) {
5870 final long origId = Binder.clearCallingIdentity();
5871 removeActivityFromHistoryLocked(r);
5872 Binder.restoreCallingIdentity(origId);
5873 }
5874 }
5875 }
5876 }
5877
5878 public String getCallingPackage(IBinder token) {
5879 synchronized (this) {
5880 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005881 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005882 }
5883 }
5884
5885 public ComponentName getCallingActivity(IBinder token) {
5886 synchronized (this) {
5887 HistoryRecord r = getCallingRecordLocked(token);
5888 return r != null ? r.intent.getComponent() : null;
5889 }
5890 }
5891
5892 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005893 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005894 if (index >= 0) {
5895 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5896 if (r != null) {
5897 return r.resultTo;
5898 }
5899 }
5900 return null;
5901 }
5902
5903 public ComponentName getActivityClassForToken(IBinder token) {
5904 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005905 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005906 if (index >= 0) {
5907 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5908 return r.intent.getComponent();
5909 }
5910 return null;
5911 }
5912 }
5913
5914 public String getPackageForToken(IBinder token) {
5915 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005916 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005917 if (index >= 0) {
5918 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5919 return r.packageName;
5920 }
5921 return null;
5922 }
5923 }
5924
5925 public IIntentSender getIntentSender(int type,
5926 String packageName, IBinder token, String resultWho,
5927 int requestCode, Intent intent, String resolvedType, int flags) {
5928 // Refuse possible leaked file descriptors
5929 if (intent != null && intent.hasFileDescriptors() == true) {
5930 throw new IllegalArgumentException("File descriptors passed in Intent");
5931 }
5932
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005933 if (type == INTENT_SENDER_BROADCAST) {
5934 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5935 throw new IllegalArgumentException(
5936 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5937 }
5938 }
5939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005940 synchronized(this) {
5941 int callingUid = Binder.getCallingUid();
5942 try {
5943 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5944 Process.supportsProcesses()) {
5945 int uid = ActivityThread.getPackageManager()
5946 .getPackageUid(packageName);
5947 if (uid != Binder.getCallingUid()) {
5948 String msg = "Permission Denial: getIntentSender() from pid="
5949 + Binder.getCallingPid()
5950 + ", uid=" + Binder.getCallingUid()
5951 + ", (need uid=" + uid + ")"
5952 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005953 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005954 throw new SecurityException(msg);
5955 }
5956 }
5957 } catch (RemoteException e) {
5958 throw new SecurityException(e);
5959 }
5960 HistoryRecord activity = null;
5961 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005962 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005963 if (index < 0) {
5964 return null;
5965 }
5966 activity = (HistoryRecord)mHistory.get(index);
5967 if (activity.finishing) {
5968 return null;
5969 }
5970 }
5971
5972 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5973 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5974 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5975 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5976 |PendingIntent.FLAG_UPDATE_CURRENT);
5977
5978 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5979 type, packageName, activity, resultWho,
5980 requestCode, intent, resolvedType, flags);
5981 WeakReference<PendingIntentRecord> ref;
5982 ref = mIntentSenderRecords.get(key);
5983 PendingIntentRecord rec = ref != null ? ref.get() : null;
5984 if (rec != null) {
5985 if (!cancelCurrent) {
5986 if (updateCurrent) {
5987 rec.key.requestIntent.replaceExtras(intent);
5988 }
5989 return rec;
5990 }
5991 rec.canceled = true;
5992 mIntentSenderRecords.remove(key);
5993 }
5994 if (noCreate) {
5995 return rec;
5996 }
5997 rec = new PendingIntentRecord(this, key, callingUid);
5998 mIntentSenderRecords.put(key, rec.ref);
5999 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6000 if (activity.pendingResults == null) {
6001 activity.pendingResults
6002 = new HashSet<WeakReference<PendingIntentRecord>>();
6003 }
6004 activity.pendingResults.add(rec.ref);
6005 }
6006 return rec;
6007 }
6008 }
6009
6010 public void cancelIntentSender(IIntentSender sender) {
6011 if (!(sender instanceof PendingIntentRecord)) {
6012 return;
6013 }
6014 synchronized(this) {
6015 PendingIntentRecord rec = (PendingIntentRecord)sender;
6016 try {
6017 int uid = ActivityThread.getPackageManager()
6018 .getPackageUid(rec.key.packageName);
6019 if (uid != Binder.getCallingUid()) {
6020 String msg = "Permission Denial: cancelIntentSender() from pid="
6021 + Binder.getCallingPid()
6022 + ", uid=" + Binder.getCallingUid()
6023 + " is not allowed to cancel packges "
6024 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006025 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006026 throw new SecurityException(msg);
6027 }
6028 } catch (RemoteException e) {
6029 throw new SecurityException(e);
6030 }
6031 cancelIntentSenderLocked(rec, true);
6032 }
6033 }
6034
6035 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6036 rec.canceled = true;
6037 mIntentSenderRecords.remove(rec.key);
6038 if (cleanActivity && rec.key.activity != null) {
6039 rec.key.activity.pendingResults.remove(rec.ref);
6040 }
6041 }
6042
6043 public String getPackageForIntentSender(IIntentSender pendingResult) {
6044 if (!(pendingResult instanceof PendingIntentRecord)) {
6045 return null;
6046 }
6047 synchronized(this) {
6048 try {
6049 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6050 return res.key.packageName;
6051 } catch (ClassCastException e) {
6052 }
6053 }
6054 return null;
6055 }
6056
6057 public void setProcessLimit(int max) {
6058 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6059 "setProcessLimit()");
6060 mProcessLimit = max;
6061 }
6062
6063 public int getProcessLimit() {
6064 return mProcessLimit;
6065 }
6066
6067 void foregroundTokenDied(ForegroundToken token) {
6068 synchronized (ActivityManagerService.this) {
6069 synchronized (mPidsSelfLocked) {
6070 ForegroundToken cur
6071 = mForegroundProcesses.get(token.pid);
6072 if (cur != token) {
6073 return;
6074 }
6075 mForegroundProcesses.remove(token.pid);
6076 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6077 if (pr == null) {
6078 return;
6079 }
6080 pr.forcingToForeground = null;
6081 pr.foregroundServices = false;
6082 }
6083 updateOomAdjLocked();
6084 }
6085 }
6086
6087 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6088 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6089 "setProcessForeground()");
6090 synchronized(this) {
6091 boolean changed = false;
6092
6093 synchronized (mPidsSelfLocked) {
6094 ProcessRecord pr = mPidsSelfLocked.get(pid);
6095 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006096 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006097 return;
6098 }
6099 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6100 if (oldToken != null) {
6101 oldToken.token.unlinkToDeath(oldToken, 0);
6102 mForegroundProcesses.remove(pid);
6103 pr.forcingToForeground = null;
6104 changed = true;
6105 }
6106 if (isForeground && token != null) {
6107 ForegroundToken newToken = new ForegroundToken() {
6108 public void binderDied() {
6109 foregroundTokenDied(this);
6110 }
6111 };
6112 newToken.pid = pid;
6113 newToken.token = token;
6114 try {
6115 token.linkToDeath(newToken, 0);
6116 mForegroundProcesses.put(pid, newToken);
6117 pr.forcingToForeground = token;
6118 changed = true;
6119 } catch (RemoteException e) {
6120 // If the process died while doing this, we will later
6121 // do the cleanup with the process death link.
6122 }
6123 }
6124 }
6125
6126 if (changed) {
6127 updateOomAdjLocked();
6128 }
6129 }
6130 }
6131
6132 // =========================================================
6133 // PERMISSIONS
6134 // =========================================================
6135
6136 static class PermissionController extends IPermissionController.Stub {
6137 ActivityManagerService mActivityManagerService;
6138 PermissionController(ActivityManagerService activityManagerService) {
6139 mActivityManagerService = activityManagerService;
6140 }
6141
6142 public boolean checkPermission(String permission, int pid, int uid) {
6143 return mActivityManagerService.checkPermission(permission, pid,
6144 uid) == PackageManager.PERMISSION_GRANTED;
6145 }
6146 }
6147
6148 /**
6149 * This can be called with or without the global lock held.
6150 */
6151 int checkComponentPermission(String permission, int pid, int uid,
6152 int reqUid) {
6153 // We might be performing an operation on behalf of an indirect binder
6154 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6155 // client identity accordingly before proceeding.
6156 Identity tlsIdentity = sCallerIdentity.get();
6157 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006158 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006159 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6160 uid = tlsIdentity.uid;
6161 pid = tlsIdentity.pid;
6162 }
6163
6164 // Root, system server and our own process get to do everything.
6165 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6166 !Process.supportsProcesses()) {
6167 return PackageManager.PERMISSION_GRANTED;
6168 }
6169 // If the target requires a specific UID, always fail for others.
6170 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006171 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006172 return PackageManager.PERMISSION_DENIED;
6173 }
6174 if (permission == null) {
6175 return PackageManager.PERMISSION_GRANTED;
6176 }
6177 try {
6178 return ActivityThread.getPackageManager()
6179 .checkUidPermission(permission, uid);
6180 } catch (RemoteException e) {
6181 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006182 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006183 }
6184 return PackageManager.PERMISSION_DENIED;
6185 }
6186
6187 /**
6188 * As the only public entry point for permissions checking, this method
6189 * can enforce the semantic that requesting a check on a null global
6190 * permission is automatically denied. (Internally a null permission
6191 * string is used when calling {@link #checkComponentPermission} in cases
6192 * when only uid-based security is needed.)
6193 *
6194 * This can be called with or without the global lock held.
6195 */
6196 public int checkPermission(String permission, int pid, int uid) {
6197 if (permission == null) {
6198 return PackageManager.PERMISSION_DENIED;
6199 }
6200 return checkComponentPermission(permission, pid, uid, -1);
6201 }
6202
6203 /**
6204 * Binder IPC calls go through the public entry point.
6205 * This can be called with or without the global lock held.
6206 */
6207 int checkCallingPermission(String permission) {
6208 return checkPermission(permission,
6209 Binder.getCallingPid(),
6210 Binder.getCallingUid());
6211 }
6212
6213 /**
6214 * This can be called with or without the global lock held.
6215 */
6216 void enforceCallingPermission(String permission, String func) {
6217 if (checkCallingPermission(permission)
6218 == PackageManager.PERMISSION_GRANTED) {
6219 return;
6220 }
6221
6222 String msg = "Permission Denial: " + func + " from pid="
6223 + Binder.getCallingPid()
6224 + ", uid=" + Binder.getCallingUid()
6225 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006226 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006227 throw new SecurityException(msg);
6228 }
6229
6230 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6231 ProviderInfo pi, int uid, int modeFlags) {
6232 try {
6233 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6234 if ((pi.readPermission != null) &&
6235 (pm.checkUidPermission(pi.readPermission, uid)
6236 != PackageManager.PERMISSION_GRANTED)) {
6237 return false;
6238 }
6239 }
6240 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6241 if ((pi.writePermission != null) &&
6242 (pm.checkUidPermission(pi.writePermission, uid)
6243 != PackageManager.PERMISSION_GRANTED)) {
6244 return false;
6245 }
6246 }
6247 return true;
6248 } catch (RemoteException e) {
6249 return false;
6250 }
6251 }
6252
6253 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6254 int modeFlags) {
6255 // Root gets to do everything.
6256 if (uid == 0 || !Process.supportsProcesses()) {
6257 return true;
6258 }
6259 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6260 if (perms == null) return false;
6261 UriPermission perm = perms.get(uri);
6262 if (perm == null) return false;
6263 return (modeFlags&perm.modeFlags) == modeFlags;
6264 }
6265
6266 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6267 // Another redirected-binder-call permissions check as in
6268 // {@link checkComponentPermission}.
6269 Identity tlsIdentity = sCallerIdentity.get();
6270 if (tlsIdentity != null) {
6271 uid = tlsIdentity.uid;
6272 pid = tlsIdentity.pid;
6273 }
6274
6275 // Our own process gets to do everything.
6276 if (pid == MY_PID) {
6277 return PackageManager.PERMISSION_GRANTED;
6278 }
6279 synchronized(this) {
6280 return checkUriPermissionLocked(uri, uid, modeFlags)
6281 ? PackageManager.PERMISSION_GRANTED
6282 : PackageManager.PERMISSION_DENIED;
6283 }
6284 }
6285
6286 private void grantUriPermissionLocked(int callingUid,
6287 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6288 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6289 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6290 if (modeFlags == 0) {
6291 return;
6292 }
6293
Joe Onorato8a9b2202010-02-26 18:56:32 -08006294 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006295 "Requested grant " + targetPkg + " permission to " + uri);
6296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006297 final IPackageManager pm = ActivityThread.getPackageManager();
6298
6299 // If this is not a content: uri, we can't do anything with it.
6300 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006301 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006302 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006303 return;
6304 }
6305
6306 String name = uri.getAuthority();
6307 ProviderInfo pi = null;
6308 ContentProviderRecord cpr
6309 = (ContentProviderRecord)mProvidersByName.get(name);
6310 if (cpr != null) {
6311 pi = cpr.info;
6312 } else {
6313 try {
6314 pi = pm.resolveContentProvider(name,
6315 PackageManager.GET_URI_PERMISSION_PATTERNS);
6316 } catch (RemoteException ex) {
6317 }
6318 }
6319 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006320 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006321 return;
6322 }
6323
6324 int targetUid;
6325 try {
6326 targetUid = pm.getPackageUid(targetPkg);
6327 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006328 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006329 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006330 return;
6331 }
6332 } catch (RemoteException ex) {
6333 return;
6334 }
6335
6336 // First... does the target actually need this permission?
6337 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6338 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006339 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006340 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006341 return;
6342 }
6343
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006344 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006345 if (!pi.grantUriPermissions) {
6346 throw new SecurityException("Provider " + pi.packageName
6347 + "/" + pi.name
6348 + " does not allow granting of Uri permissions (uri "
6349 + uri + ")");
6350 }
6351 if (pi.uriPermissionPatterns != null) {
6352 final int N = pi.uriPermissionPatterns.length;
6353 boolean allowed = false;
6354 for (int i=0; i<N; i++) {
6355 if (pi.uriPermissionPatterns[i] != null
6356 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6357 allowed = true;
6358 break;
6359 }
6360 }
6361 if (!allowed) {
6362 throw new SecurityException("Provider " + pi.packageName
6363 + "/" + pi.name
6364 + " does not allow granting of permission to path of Uri "
6365 + uri);
6366 }
6367 }
6368
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006369 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006370 // this uri?
6371 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6372 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6373 throw new SecurityException("Uid " + callingUid
6374 + " does not have permission to uri " + uri);
6375 }
6376 }
6377
6378 // Okay! So here we are: the caller has the assumed permission
6379 // to the uri, and the target doesn't. Let's now give this to
6380 // the target.
6381
Joe Onorato8a9b2202010-02-26 18:56:32 -08006382 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006383 "Granting " + targetPkg + " permission to " + uri);
6384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006385 HashMap<Uri, UriPermission> targetUris
6386 = mGrantedUriPermissions.get(targetUid);
6387 if (targetUris == null) {
6388 targetUris = new HashMap<Uri, UriPermission>();
6389 mGrantedUriPermissions.put(targetUid, targetUris);
6390 }
6391
6392 UriPermission perm = targetUris.get(uri);
6393 if (perm == null) {
6394 perm = new UriPermission(targetUid, uri);
6395 targetUris.put(uri, perm);
6396
6397 }
6398 perm.modeFlags |= modeFlags;
6399 if (activity == null) {
6400 perm.globalModeFlags |= modeFlags;
6401 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6402 perm.readActivities.add(activity);
6403 if (activity.readUriPermissions == null) {
6404 activity.readUriPermissions = new HashSet<UriPermission>();
6405 }
6406 activity.readUriPermissions.add(perm);
6407 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6408 perm.writeActivities.add(activity);
6409 if (activity.writeUriPermissions == null) {
6410 activity.writeUriPermissions = new HashSet<UriPermission>();
6411 }
6412 activity.writeUriPermissions.add(perm);
6413 }
6414 }
6415
6416 private void grantUriPermissionFromIntentLocked(int callingUid,
6417 String targetPkg, Intent intent, HistoryRecord activity) {
6418 if (intent == null) {
6419 return;
6420 }
6421 Uri data = intent.getData();
6422 if (data == null) {
6423 return;
6424 }
6425 grantUriPermissionLocked(callingUid, targetPkg, data,
6426 intent.getFlags(), activity);
6427 }
6428
6429 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6430 Uri uri, int modeFlags) {
6431 synchronized(this) {
6432 final ProcessRecord r = getRecordForAppLocked(caller);
6433 if (r == null) {
6434 throw new SecurityException("Unable to find app for caller "
6435 + caller
6436 + " when granting permission to uri " + uri);
6437 }
6438 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006439 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 return;
6441 }
6442 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006443 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006444 return;
6445 }
6446
6447 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6448 null);
6449 }
6450 }
6451
6452 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6453 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6454 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6455 HashMap<Uri, UriPermission> perms
6456 = mGrantedUriPermissions.get(perm.uid);
6457 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006458 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006459 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006460 perms.remove(perm.uri);
6461 if (perms.size() == 0) {
6462 mGrantedUriPermissions.remove(perm.uid);
6463 }
6464 }
6465 }
6466 }
6467
6468 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6469 if (activity.readUriPermissions != null) {
6470 for (UriPermission perm : activity.readUriPermissions) {
6471 perm.readActivities.remove(activity);
6472 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6473 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6474 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6475 removeUriPermissionIfNeededLocked(perm);
6476 }
6477 }
6478 }
6479 if (activity.writeUriPermissions != null) {
6480 for (UriPermission perm : activity.writeUriPermissions) {
6481 perm.writeActivities.remove(activity);
6482 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6483 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6484 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6485 removeUriPermissionIfNeededLocked(perm);
6486 }
6487 }
6488 }
6489 }
6490
6491 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6492 int modeFlags) {
6493 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6494 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6495 if (modeFlags == 0) {
6496 return;
6497 }
6498
Joe Onorato8a9b2202010-02-26 18:56:32 -08006499 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006500 "Revoking all granted permissions to " + uri);
6501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006502 final IPackageManager pm = ActivityThread.getPackageManager();
6503
6504 final String authority = uri.getAuthority();
6505 ProviderInfo pi = null;
6506 ContentProviderRecord cpr
6507 = (ContentProviderRecord)mProvidersByName.get(authority);
6508 if (cpr != null) {
6509 pi = cpr.info;
6510 } else {
6511 try {
6512 pi = pm.resolveContentProvider(authority,
6513 PackageManager.GET_URI_PERMISSION_PATTERNS);
6514 } catch (RemoteException ex) {
6515 }
6516 }
6517 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006518 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 return;
6520 }
6521
6522 // Does the caller have this permission on the URI?
6523 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6524 // Right now, if you are not the original owner of the permission,
6525 // you are not allowed to revoke it.
6526 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6527 throw new SecurityException("Uid " + callingUid
6528 + " does not have permission to uri " + uri);
6529 //}
6530 }
6531
6532 // Go through all of the permissions and remove any that match.
6533 final List<String> SEGMENTS = uri.getPathSegments();
6534 if (SEGMENTS != null) {
6535 final int NS = SEGMENTS.size();
6536 int N = mGrantedUriPermissions.size();
6537 for (int i=0; i<N; i++) {
6538 HashMap<Uri, UriPermission> perms
6539 = mGrantedUriPermissions.valueAt(i);
6540 Iterator<UriPermission> it = perms.values().iterator();
6541 toploop:
6542 while (it.hasNext()) {
6543 UriPermission perm = it.next();
6544 Uri targetUri = perm.uri;
6545 if (!authority.equals(targetUri.getAuthority())) {
6546 continue;
6547 }
6548 List<String> targetSegments = targetUri.getPathSegments();
6549 if (targetSegments == null) {
6550 continue;
6551 }
6552 if (targetSegments.size() < NS) {
6553 continue;
6554 }
6555 for (int j=0; j<NS; j++) {
6556 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6557 continue toploop;
6558 }
6559 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006560 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006561 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006562 perm.clearModes(modeFlags);
6563 if (perm.modeFlags == 0) {
6564 it.remove();
6565 }
6566 }
6567 if (perms.size() == 0) {
6568 mGrantedUriPermissions.remove(
6569 mGrantedUriPermissions.keyAt(i));
6570 N--;
6571 i--;
6572 }
6573 }
6574 }
6575 }
6576
6577 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6578 int modeFlags) {
6579 synchronized(this) {
6580 final ProcessRecord r = getRecordForAppLocked(caller);
6581 if (r == null) {
6582 throw new SecurityException("Unable to find app for caller "
6583 + caller
6584 + " when revoking permission to uri " + uri);
6585 }
6586 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006587 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006588 return;
6589 }
6590
6591 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6592 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6593 if (modeFlags == 0) {
6594 return;
6595 }
6596
6597 final IPackageManager pm = ActivityThread.getPackageManager();
6598
6599 final String authority = uri.getAuthority();
6600 ProviderInfo pi = null;
6601 ContentProviderRecord cpr
6602 = (ContentProviderRecord)mProvidersByName.get(authority);
6603 if (cpr != null) {
6604 pi = cpr.info;
6605 } else {
6606 try {
6607 pi = pm.resolveContentProvider(authority,
6608 PackageManager.GET_URI_PERMISSION_PATTERNS);
6609 } catch (RemoteException ex) {
6610 }
6611 }
6612 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006613 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006614 return;
6615 }
6616
6617 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6618 }
6619 }
6620
6621 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6622 synchronized (this) {
6623 ProcessRecord app =
6624 who != null ? getRecordForAppLocked(who) : null;
6625 if (app == null) return;
6626
6627 Message msg = Message.obtain();
6628 msg.what = WAIT_FOR_DEBUGGER_MSG;
6629 msg.obj = app;
6630 msg.arg1 = waiting ? 1 : 0;
6631 mHandler.sendMessage(msg);
6632 }
6633 }
6634
6635 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6636 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006637 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006638 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006639 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006640 }
6641
6642 // =========================================================
6643 // TASK MANAGEMENT
6644 // =========================================================
6645
6646 public List getTasks(int maxNum, int flags,
6647 IThumbnailReceiver receiver) {
6648 ArrayList list = new ArrayList();
6649
6650 PendingThumbnailsRecord pending = null;
6651 IApplicationThread topThumbnail = null;
6652 HistoryRecord topRecord = null;
6653
6654 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006655 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006656 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6657 + ", receiver=" + receiver);
6658
6659 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6660 != PackageManager.PERMISSION_GRANTED) {
6661 if (receiver != null) {
6662 // If the caller wants to wait for pending thumbnails,
6663 // it ain't gonna get them.
6664 try {
6665 receiver.finished();
6666 } catch (RemoteException ex) {
6667 }
6668 }
6669 String msg = "Permission Denial: getTasks() from pid="
6670 + Binder.getCallingPid()
6671 + ", uid=" + Binder.getCallingUid()
6672 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006673 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006674 throw new SecurityException(msg);
6675 }
6676
6677 int pos = mHistory.size()-1;
6678 HistoryRecord next =
6679 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6680 HistoryRecord top = null;
6681 CharSequence topDescription = null;
6682 TaskRecord curTask = null;
6683 int numActivities = 0;
6684 int numRunning = 0;
6685 while (pos >= 0 && maxNum > 0) {
6686 final HistoryRecord r = next;
6687 pos--;
6688 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6689
6690 // Initialize state for next task if needed.
6691 if (top == null ||
6692 (top.state == ActivityState.INITIALIZING
6693 && top.task == r.task)) {
6694 top = r;
6695 topDescription = r.description;
6696 curTask = r.task;
6697 numActivities = numRunning = 0;
6698 }
6699
6700 // Add 'r' into the current task.
6701 numActivities++;
6702 if (r.app != null && r.app.thread != null) {
6703 numRunning++;
6704 }
6705 if (topDescription == null) {
6706 topDescription = r.description;
6707 }
6708
Joe Onorato8a9b2202010-02-26 18:56:32 -08006709 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006710 TAG, r.intent.getComponent().flattenToShortString()
6711 + ": task=" + r.task);
6712
6713 // If the next one is a different task, generate a new
6714 // TaskInfo entry for what we have.
6715 if (next == null || next.task != curTask) {
6716 ActivityManager.RunningTaskInfo ci
6717 = new ActivityManager.RunningTaskInfo();
6718 ci.id = curTask.taskId;
6719 ci.baseActivity = r.intent.getComponent();
6720 ci.topActivity = top.intent.getComponent();
6721 ci.thumbnail = top.thumbnail;
6722 ci.description = topDescription;
6723 ci.numActivities = numActivities;
6724 ci.numRunning = numRunning;
6725 //System.out.println(
6726 // "#" + maxNum + ": " + " descr=" + ci.description);
6727 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006728 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006729 TAG, "State=" + top.state + "Idle=" + top.idle
6730 + " app=" + top.app
6731 + " thr=" + (top.app != null ? top.app.thread : null));
6732 if (top.state == ActivityState.RESUMED
6733 || top.state == ActivityState.PAUSING) {
6734 if (top.idle && top.app != null
6735 && top.app.thread != null) {
6736 topRecord = top;
6737 topThumbnail = top.app.thread;
6738 } else {
6739 top.thumbnailNeeded = true;
6740 }
6741 }
6742 if (pending == null) {
6743 pending = new PendingThumbnailsRecord(receiver);
6744 }
6745 pending.pendingRecords.add(top);
6746 }
6747 list.add(ci);
6748 maxNum--;
6749 top = null;
6750 }
6751 }
6752
6753 if (pending != null) {
6754 mPendingThumbnails.add(pending);
6755 }
6756 }
6757
Joe Onorato8a9b2202010-02-26 18:56:32 -08006758 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006759
6760 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006761 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006762 try {
6763 topThumbnail.requestThumbnail(topRecord);
6764 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006765 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006766 sendPendingThumbnail(null, topRecord, null, null, true);
6767 }
6768 }
6769
6770 if (pending == null && receiver != null) {
6771 // In this case all thumbnails were available and the client
6772 // is being asked to be told when the remaining ones come in...
6773 // which is unusually, since the top-most currently running
6774 // activity should never have a canned thumbnail! Oh well.
6775 try {
6776 receiver.finished();
6777 } catch (RemoteException ex) {
6778 }
6779 }
6780
6781 return list;
6782 }
6783
6784 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6785 int flags) {
6786 synchronized (this) {
6787 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6788 "getRecentTasks()");
6789
6790 final int N = mRecentTasks.size();
6791 ArrayList<ActivityManager.RecentTaskInfo> res
6792 = new ArrayList<ActivityManager.RecentTaskInfo>(
6793 maxNum < N ? maxNum : N);
6794 for (int i=0; i<N && maxNum > 0; i++) {
6795 TaskRecord tr = mRecentTasks.get(i);
6796 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6797 || (tr.intent == null)
6798 || ((tr.intent.getFlags()
6799 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6800 ActivityManager.RecentTaskInfo rti
6801 = new ActivityManager.RecentTaskInfo();
6802 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6803 rti.baseIntent = new Intent(
6804 tr.intent != null ? tr.intent : tr.affinityIntent);
6805 rti.origActivity = tr.origActivity;
6806 res.add(rti);
6807 maxNum--;
6808 }
6809 }
6810 return res;
6811 }
6812 }
6813
6814 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6815 int j;
6816 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6817 TaskRecord jt = startTask;
6818
6819 // First look backwards
6820 for (j=startIndex-1; j>=0; j--) {
6821 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6822 if (r.task != jt) {
6823 jt = r.task;
6824 if (affinity.equals(jt.affinity)) {
6825 return j;
6826 }
6827 }
6828 }
6829
6830 // Now look forwards
6831 final int N = mHistory.size();
6832 jt = startTask;
6833 for (j=startIndex+1; j<N; j++) {
6834 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6835 if (r.task != jt) {
6836 if (affinity.equals(jt.affinity)) {
6837 return j;
6838 }
6839 jt = r.task;
6840 }
6841 }
6842
6843 // Might it be at the top?
6844 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6845 return N-1;
6846 }
6847
6848 return -1;
6849 }
6850
6851 /**
6852 * Perform a reset of the given task, if needed as part of launching it.
6853 * Returns the new HistoryRecord at the top of the task.
6854 */
6855 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6856 HistoryRecord newActivity) {
6857 boolean forceReset = (newActivity.info.flags
6858 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6859 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6860 if ((newActivity.info.flags
6861 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6862 forceReset = true;
6863 }
6864 }
6865
6866 final TaskRecord task = taskTop.task;
6867
6868 // We are going to move through the history list so that we can look
6869 // at each activity 'target' with 'below' either the interesting
6870 // activity immediately below it in the stack or null.
6871 HistoryRecord target = null;
6872 int targetI = 0;
6873 int taskTopI = -1;
6874 int replyChainEnd = -1;
6875 int lastReparentPos = -1;
6876 for (int i=mHistory.size()-1; i>=-1; i--) {
6877 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6878
6879 if (below != null && below.finishing) {
6880 continue;
6881 }
6882 if (target == null) {
6883 target = below;
6884 targetI = i;
6885 // If we were in the middle of a reply chain before this
6886 // task, it doesn't appear like the root of the chain wants
6887 // anything interesting, so drop it.
6888 replyChainEnd = -1;
6889 continue;
6890 }
6891
6892 final int flags = target.info.flags;
6893
6894 final boolean finishOnTaskLaunch =
6895 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6896 final boolean allowTaskReparenting =
6897 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6898
6899 if (target.task == task) {
6900 // We are inside of the task being reset... we'll either
6901 // finish this activity, push it out for another task,
6902 // or leave it as-is. We only do this
6903 // for activities that are not the root of the task (since
6904 // if we finish the root, we may no longer have the task!).
6905 if (taskTopI < 0) {
6906 taskTopI = targetI;
6907 }
6908 if (below != null && below.task == task) {
6909 final boolean clearWhenTaskReset =
6910 (target.intent.getFlags()
6911 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006912 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006913 // If this activity is sending a reply to a previous
6914 // activity, we can't do anything with it now until
6915 // we reach the start of the reply chain.
6916 // XXX note that we are assuming the result is always
6917 // to the previous activity, which is almost always
6918 // the case but we really shouldn't count on.
6919 if (replyChainEnd < 0) {
6920 replyChainEnd = targetI;
6921 }
Ed Heyl73798232009-03-24 21:32:21 -07006922 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006923 && target.taskAffinity != null
6924 && !target.taskAffinity.equals(task.affinity)) {
6925 // If this activity has an affinity for another
6926 // task, then we need to move it out of here. We will
6927 // move it as far out of the way as possible, to the
6928 // bottom of the activity stack. This also keeps it
6929 // correctly ordered with any activities we previously
6930 // moved.
6931 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6932 if (target.taskAffinity != null
6933 && target.taskAffinity.equals(p.task.affinity)) {
6934 // If the activity currently at the bottom has the
6935 // same task affinity as the one we are moving,
6936 // then merge it into the same task.
6937 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006938 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006939 + " out to bottom task " + p.task);
6940 } else {
6941 mCurTask++;
6942 if (mCurTask <= 0) {
6943 mCurTask = 1;
6944 }
6945 target.task = new TaskRecord(mCurTask, target.info, null,
6946 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6947 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006948 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006949 + " out to new task " + target.task);
6950 }
6951 mWindowManager.setAppGroupId(target, task.taskId);
6952 if (replyChainEnd < 0) {
6953 replyChainEnd = targetI;
6954 }
6955 int dstPos = 0;
6956 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6957 p = (HistoryRecord)mHistory.get(srcPos);
6958 if (p.finishing) {
6959 continue;
6960 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006961 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006962 + " out to target's task " + target.task);
6963 task.numActivities--;
6964 p.task = target.task;
6965 target.task.numActivities++;
6966 mHistory.remove(srcPos);
6967 mHistory.add(dstPos, p);
6968 mWindowManager.moveAppToken(dstPos, p);
6969 mWindowManager.setAppGroupId(p, p.task.taskId);
6970 dstPos++;
6971 if (VALIDATE_TOKENS) {
6972 mWindowManager.validateAppTokens(mHistory);
6973 }
6974 i++;
6975 }
6976 if (taskTop == p) {
6977 taskTop = below;
6978 }
6979 if (taskTopI == replyChainEnd) {
6980 taskTopI = -1;
6981 }
6982 replyChainEnd = -1;
6983 addRecentTask(target.task);
6984 } else if (forceReset || finishOnTaskLaunch
6985 || clearWhenTaskReset) {
6986 // If the activity should just be removed -- either
6987 // because it asks for it, or the task should be
6988 // cleared -- then finish it and anything that is
6989 // part of its reply chain.
6990 if (clearWhenTaskReset) {
6991 // In this case, we want to finish this activity
6992 // and everything above it, so be sneaky and pretend
6993 // like these are all in the reply chain.
6994 replyChainEnd = targetI+1;
6995 while (replyChainEnd < mHistory.size() &&
6996 ((HistoryRecord)mHistory.get(
6997 replyChainEnd)).task == task) {
6998 replyChainEnd++;
6999 }
7000 replyChainEnd--;
7001 } else if (replyChainEnd < 0) {
7002 replyChainEnd = targetI;
7003 }
7004 HistoryRecord p = null;
7005 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7006 p = (HistoryRecord)mHistory.get(srcPos);
7007 if (p.finishing) {
7008 continue;
7009 }
7010 if (finishActivityLocked(p, srcPos,
7011 Activity.RESULT_CANCELED, null, "reset")) {
7012 replyChainEnd--;
7013 srcPos--;
7014 }
7015 }
7016 if (taskTop == p) {
7017 taskTop = below;
7018 }
7019 if (taskTopI == replyChainEnd) {
7020 taskTopI = -1;
7021 }
7022 replyChainEnd = -1;
7023 } else {
7024 // If we were in the middle of a chain, well the
7025 // activity that started it all doesn't want anything
7026 // special, so leave it all as-is.
7027 replyChainEnd = -1;
7028 }
7029 } else {
7030 // Reached the bottom of the task -- any reply chain
7031 // should be left as-is.
7032 replyChainEnd = -1;
7033 }
7034
7035 } else if (target.resultTo != null) {
7036 // If this activity is sending a reply to a previous
7037 // activity, we can't do anything with it now until
7038 // we reach the start of the reply chain.
7039 // XXX note that we are assuming the result is always
7040 // to the previous activity, which is almost always
7041 // the case but we really shouldn't count on.
7042 if (replyChainEnd < 0) {
7043 replyChainEnd = targetI;
7044 }
7045
7046 } else if (taskTopI >= 0 && allowTaskReparenting
7047 && task.affinity != null
7048 && task.affinity.equals(target.taskAffinity)) {
7049 // We are inside of another task... if this activity has
7050 // an affinity for our task, then either remove it if we are
7051 // clearing or move it over to our task. Note that
7052 // we currently punt on the case where we are resetting a
7053 // task that is not at the top but who has activities above
7054 // with an affinity to it... this is really not a normal
7055 // case, and we will need to later pull that task to the front
7056 // and usually at that point we will do the reset and pick
7057 // up those remaining activities. (This only happens if
7058 // someone starts an activity in a new task from an activity
7059 // in a task that is not currently on top.)
7060 if (forceReset || finishOnTaskLaunch) {
7061 if (replyChainEnd < 0) {
7062 replyChainEnd = targetI;
7063 }
7064 HistoryRecord p = null;
7065 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7066 p = (HistoryRecord)mHistory.get(srcPos);
7067 if (p.finishing) {
7068 continue;
7069 }
7070 if (finishActivityLocked(p, srcPos,
7071 Activity.RESULT_CANCELED, null, "reset")) {
7072 taskTopI--;
7073 lastReparentPos--;
7074 replyChainEnd--;
7075 srcPos--;
7076 }
7077 }
7078 replyChainEnd = -1;
7079 } else {
7080 if (replyChainEnd < 0) {
7081 replyChainEnd = targetI;
7082 }
7083 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7084 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7085 if (p.finishing) {
7086 continue;
7087 }
7088 if (lastReparentPos < 0) {
7089 lastReparentPos = taskTopI;
7090 taskTop = p;
7091 } else {
7092 lastReparentPos--;
7093 }
7094 mHistory.remove(srcPos);
7095 p.task.numActivities--;
7096 p.task = task;
7097 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007098 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007099 + " in to resetting task " + task);
7100 task.numActivities++;
7101 mWindowManager.moveAppToken(lastReparentPos, p);
7102 mWindowManager.setAppGroupId(p, p.task.taskId);
7103 if (VALIDATE_TOKENS) {
7104 mWindowManager.validateAppTokens(mHistory);
7105 }
7106 }
7107 replyChainEnd = -1;
7108
7109 // Now we've moved it in to place... but what if this is
7110 // a singleTop activity and we have put it on top of another
7111 // instance of the same activity? Then we drop the instance
7112 // below so it remains singleTop.
7113 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7114 for (int j=lastReparentPos-1; j>=0; j--) {
7115 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7116 if (p.finishing) {
7117 continue;
7118 }
7119 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7120 if (finishActivityLocked(p, j,
7121 Activity.RESULT_CANCELED, null, "replace")) {
7122 taskTopI--;
7123 lastReparentPos--;
7124 }
7125 }
7126 }
7127 }
7128 }
7129 }
7130
7131 target = below;
7132 targetI = i;
7133 }
7134
7135 return taskTop;
7136 }
7137
7138 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007139 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 */
7141 public void moveTaskToFront(int task) {
7142 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7143 "moveTaskToFront()");
7144
7145 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007146 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7147 Binder.getCallingUid(), "Task to front")) {
7148 return;
7149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007150 final long origId = Binder.clearCallingIdentity();
7151 try {
7152 int N = mRecentTasks.size();
7153 for (int i=0; i<N; i++) {
7154 TaskRecord tr = mRecentTasks.get(i);
7155 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007156 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007157 return;
7158 }
7159 }
7160 for (int i=mHistory.size()-1; i>=0; i--) {
7161 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7162 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007163 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007164 return;
7165 }
7166 }
7167 } finally {
7168 Binder.restoreCallingIdentity(origId);
7169 }
7170 }
7171 }
7172
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007173 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007174 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007175
7176 final int task = tr.taskId;
7177 int top = mHistory.size()-1;
7178
7179 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7180 // nothing to do!
7181 return;
7182 }
7183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007184 ArrayList moved = new ArrayList();
7185
7186 // Applying the affinities may have removed entries from the history,
7187 // so get the size again.
7188 top = mHistory.size()-1;
7189 int pos = top;
7190
7191 // Shift all activities with this task up to the top
7192 // of the stack, keeping them in the same internal order.
7193 while (pos >= 0) {
7194 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007195 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007196 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7197 boolean first = true;
7198 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007199 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007200 mHistory.remove(pos);
7201 mHistory.add(top, r);
7202 moved.add(0, r);
7203 top--;
7204 if (first) {
7205 addRecentTask(r.task);
7206 first = false;
7207 }
7208 }
7209 pos--;
7210 }
7211
Joe Onorato8a9b2202010-02-26 18:56:32 -08007212 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007213 "Prepare to front transition: task=" + tr);
7214 if (reason != null &&
7215 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7216 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7217 HistoryRecord r = topRunningActivityLocked(null);
7218 if (r != null) {
7219 mNoAnimActivities.add(r);
7220 }
7221 } else {
7222 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7223 }
7224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225 mWindowManager.moveAppTokensToTop(moved);
7226 if (VALIDATE_TOKENS) {
7227 mWindowManager.validateAppTokens(mHistory);
7228 }
7229
7230 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007231 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 }
7233
7234 private final void finishTaskMove(int task) {
7235 resumeTopActivityLocked(null);
7236 }
7237
7238 public void moveTaskToBack(int task) {
7239 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7240 "moveTaskToBack()");
7241
7242 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007243 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7244 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7245 Binder.getCallingUid(), "Task to back")) {
7246 return;
7247 }
7248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007249 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007250 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 Binder.restoreCallingIdentity(origId);
7252 }
7253 }
7254
7255 /**
7256 * Moves an activity, and all of the other activities within the same task, to the bottom
7257 * of the history stack. The activity's order within the task is unchanged.
7258 *
7259 * @param token A reference to the activity we wish to move
7260 * @param nonRoot If false then this only works if the activity is the root
7261 * of a task; if true it will work for any activity in a task.
7262 * @return Returns true if the move completed, false if not.
7263 */
7264 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7265 synchronized(this) {
7266 final long origId = Binder.clearCallingIdentity();
7267 int taskId = getTaskForActivityLocked(token, !nonRoot);
7268 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007269 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007270 }
7271 Binder.restoreCallingIdentity(origId);
7272 }
7273 return false;
7274 }
7275
7276 /**
7277 * Worker method for rearranging history stack. Implements the function of moving all
7278 * activities for a specific task (gathering them if disjoint) into a single group at the
7279 * bottom of the stack.
7280 *
7281 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7282 * to premeptively cancel the move.
7283 *
7284 * @param task The taskId to collect and move to the bottom.
7285 * @return Returns true if the move completed, false if not.
7286 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007287 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007288 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007289
7290 // If we have a watcher, preflight the move before committing to it. First check
7291 // for *other* available tasks, but if none are available, then try again allowing the
7292 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007293 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007294 HistoryRecord next = topRunningActivityLocked(null, task);
7295 if (next == null) {
7296 next = topRunningActivityLocked(null, 0);
7297 }
7298 if (next != null) {
7299 // ask watcher if this is allowed
7300 boolean moveOK = true;
7301 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007302 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007303 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007304 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007305 }
7306 if (!moveOK) {
7307 return false;
7308 }
7309 }
7310 }
7311
7312 ArrayList moved = new ArrayList();
7313
Joe Onorato8a9b2202010-02-26 18:56:32 -08007314 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007315 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316
7317 final int N = mHistory.size();
7318 int bottom = 0;
7319 int pos = 0;
7320
7321 // Shift all activities with this task down to the bottom
7322 // of the stack, keeping them in the same internal order.
7323 while (pos < N) {
7324 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007325 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7327 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007328 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 mHistory.remove(pos);
7330 mHistory.add(bottom, r);
7331 moved.add(r);
7332 bottom++;
7333 }
7334 pos++;
7335 }
7336
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007337 if (reason != null &&
7338 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7339 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7340 HistoryRecord r = topRunningActivityLocked(null);
7341 if (r != null) {
7342 mNoAnimActivities.add(r);
7343 }
7344 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007345 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007347 mWindowManager.moveAppTokensToBottom(moved);
7348 if (VALIDATE_TOKENS) {
7349 mWindowManager.validateAppTokens(mHistory);
7350 }
7351
7352 finishTaskMove(task);
7353 return true;
7354 }
7355
7356 public void moveTaskBackwards(int task) {
7357 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7358 "moveTaskBackwards()");
7359
7360 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007361 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7362 Binder.getCallingUid(), "Task backwards")) {
7363 return;
7364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365 final long origId = Binder.clearCallingIdentity();
7366 moveTaskBackwardsLocked(task);
7367 Binder.restoreCallingIdentity(origId);
7368 }
7369 }
7370
7371 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007372 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007373 }
7374
7375 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7376 synchronized(this) {
7377 return getTaskForActivityLocked(token, onlyRoot);
7378 }
7379 }
7380
7381 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7382 final int N = mHistory.size();
7383 TaskRecord lastTask = null;
7384 for (int i=0; i<N; i++) {
7385 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7386 if (r == token) {
7387 if (!onlyRoot || lastTask != r.task) {
7388 return r.task.taskId;
7389 }
7390 return -1;
7391 }
7392 lastTask = r.task;
7393 }
7394
7395 return -1;
7396 }
7397
7398 /**
7399 * Returns the top activity in any existing task matching the given
7400 * Intent. Returns null if no such task is found.
7401 */
7402 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7403 ComponentName cls = intent.getComponent();
7404 if (info.targetActivity != null) {
7405 cls = new ComponentName(info.packageName, info.targetActivity);
7406 }
7407
7408 TaskRecord cp = null;
7409
7410 final int N = mHistory.size();
7411 for (int i=(N-1); i>=0; i--) {
7412 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7413 if (!r.finishing && r.task != cp
7414 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7415 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007416 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417 // + "/aff=" + r.task.affinity + " to new cls="
7418 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7419 if (r.task.affinity != null) {
7420 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007421 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007422 return r;
7423 }
7424 } else if (r.task.intent != null
7425 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007426 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007428 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007429 return r;
7430 } else if (r.task.affinityIntent != null
7431 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007432 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007434 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007435 return r;
7436 }
7437 }
7438 }
7439
7440 return null;
7441 }
7442
7443 /**
7444 * Returns the first activity (starting from the top of the stack) that
7445 * is the same as the given activity. Returns null if no such activity
7446 * is found.
7447 */
7448 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7449 ComponentName cls = intent.getComponent();
7450 if (info.targetActivity != null) {
7451 cls = new ComponentName(info.packageName, info.targetActivity);
7452 }
7453
7454 final int N = mHistory.size();
7455 for (int i=(N-1); i>=0; i--) {
7456 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7457 if (!r.finishing) {
7458 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007459 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007460 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007461 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007462 return r;
7463 }
7464 }
7465 }
7466
7467 return null;
7468 }
7469
7470 public void finishOtherInstances(IBinder token, ComponentName className) {
7471 synchronized(this) {
7472 final long origId = Binder.clearCallingIdentity();
7473
7474 int N = mHistory.size();
7475 TaskRecord lastTask = null;
7476 for (int i=0; i<N; i++) {
7477 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7478 if (r.realActivity.equals(className)
7479 && r != token && lastTask != r.task) {
7480 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7481 null, "others")) {
7482 i--;
7483 N--;
7484 }
7485 }
7486 lastTask = r.task;
7487 }
7488
7489 Binder.restoreCallingIdentity(origId);
7490 }
7491 }
7492
7493 // =========================================================
7494 // THUMBNAILS
7495 // =========================================================
7496
7497 public void reportThumbnail(IBinder token,
7498 Bitmap thumbnail, CharSequence description) {
7499 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7500 final long origId = Binder.clearCallingIdentity();
7501 sendPendingThumbnail(null, token, thumbnail, description, true);
7502 Binder.restoreCallingIdentity(origId);
7503 }
7504
7505 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7506 Bitmap thumbnail, CharSequence description, boolean always) {
7507 TaskRecord task = null;
7508 ArrayList receivers = null;
7509
7510 //System.out.println("Send pending thumbnail: " + r);
7511
7512 synchronized(this) {
7513 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007514 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 if (index < 0) {
7516 return;
7517 }
7518 r = (HistoryRecord)mHistory.get(index);
7519 }
7520 if (thumbnail == null) {
7521 thumbnail = r.thumbnail;
7522 description = r.description;
7523 }
7524 if (thumbnail == null && !always) {
7525 // If there is no thumbnail, and this entry is not actually
7526 // going away, then abort for now and pick up the next
7527 // thumbnail we get.
7528 return;
7529 }
7530 task = r.task;
7531
7532 int N = mPendingThumbnails.size();
7533 int i=0;
7534 while (i<N) {
7535 PendingThumbnailsRecord pr =
7536 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7537 //System.out.println("Looking in " + pr.pendingRecords);
7538 if (pr.pendingRecords.remove(r)) {
7539 if (receivers == null) {
7540 receivers = new ArrayList();
7541 }
7542 receivers.add(pr);
7543 if (pr.pendingRecords.size() == 0) {
7544 pr.finished = true;
7545 mPendingThumbnails.remove(i);
7546 N--;
7547 continue;
7548 }
7549 }
7550 i++;
7551 }
7552 }
7553
7554 if (receivers != null) {
7555 final int N = receivers.size();
7556 for (int i=0; i<N; i++) {
7557 try {
7558 PendingThumbnailsRecord pr =
7559 (PendingThumbnailsRecord)receivers.get(i);
7560 pr.receiver.newThumbnail(
7561 task != null ? task.taskId : -1, thumbnail, description);
7562 if (pr.finished) {
7563 pr.receiver.finished();
7564 }
7565 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007566 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007567 }
7568 }
7569 }
7570 }
7571
7572 // =========================================================
7573 // CONTENT PROVIDERS
7574 // =========================================================
7575
7576 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7577 List providers = null;
7578 try {
7579 providers = ActivityThread.getPackageManager().
7580 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007581 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007582 } catch (RemoteException ex) {
7583 }
7584 if (providers != null) {
7585 final int N = providers.size();
7586 for (int i=0; i<N; i++) {
7587 ProviderInfo cpi =
7588 (ProviderInfo)providers.get(i);
7589 ContentProviderRecord cpr =
7590 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7591 if (cpr == null) {
7592 cpr = new ContentProviderRecord(cpi, app.info);
7593 mProvidersByClass.put(cpi.name, cpr);
7594 }
7595 app.pubProviders.put(cpi.name, cpr);
7596 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007597 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007598 }
7599 }
7600 return providers;
7601 }
7602
7603 private final String checkContentProviderPermissionLocked(
7604 ProviderInfo cpi, ProcessRecord r, int mode) {
7605 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7606 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7607 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7608 cpi.exported ? -1 : cpi.applicationInfo.uid)
7609 == PackageManager.PERMISSION_GRANTED
7610 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7611 return null;
7612 }
7613 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7614 cpi.exported ? -1 : cpi.applicationInfo.uid)
7615 == PackageManager.PERMISSION_GRANTED) {
7616 return null;
7617 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007618
7619 PathPermission[] pps = cpi.pathPermissions;
7620 if (pps != null) {
7621 int i = pps.length;
7622 while (i > 0) {
7623 i--;
7624 PathPermission pp = pps[i];
7625 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7626 cpi.exported ? -1 : cpi.applicationInfo.uid)
7627 == PackageManager.PERMISSION_GRANTED
7628 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7629 return null;
7630 }
7631 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7632 cpi.exported ? -1 : cpi.applicationInfo.uid)
7633 == PackageManager.PERMISSION_GRANTED) {
7634 return null;
7635 }
7636 }
7637 }
7638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007639 String msg = "Permission Denial: opening provider " + cpi.name
7640 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7641 + ", uid=" + callingUid + ") requires "
7642 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007643 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007644 return msg;
7645 }
7646
7647 private final ContentProviderHolder getContentProviderImpl(
7648 IApplicationThread caller, String name) {
7649 ContentProviderRecord cpr;
7650 ProviderInfo cpi = null;
7651
7652 synchronized(this) {
7653 ProcessRecord r = null;
7654 if (caller != null) {
7655 r = getRecordForAppLocked(caller);
7656 if (r == null) {
7657 throw new SecurityException(
7658 "Unable to find app for caller " + caller
7659 + " (pid=" + Binder.getCallingPid()
7660 + ") when getting content provider " + name);
7661 }
7662 }
7663
7664 // First check if this content provider has been published...
7665 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7666 if (cpr != null) {
7667 cpi = cpr.info;
7668 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7669 return new ContentProviderHolder(cpi,
7670 cpi.readPermission != null
7671 ? cpi.readPermission : cpi.writePermission);
7672 }
7673
7674 if (r != null && cpr.canRunHere(r)) {
7675 // This provider has been published or is in the process
7676 // of being published... but it is also allowed to run
7677 // in the caller's process, so don't make a connection
7678 // and just let the caller instantiate its own instance.
7679 if (cpr.provider != null) {
7680 // don't give caller the provider object, it needs
7681 // to make its own.
7682 cpr = new ContentProviderRecord(cpr);
7683 }
7684 return cpr;
7685 }
7686
7687 final long origId = Binder.clearCallingIdentity();
7688
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007689 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690 // return it right away.
7691 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007692 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007693 "Adding provider requested by "
7694 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007695 + cpr.info.processName);
7696 Integer cnt = r.conProviders.get(cpr);
7697 if (cnt == null) {
7698 r.conProviders.put(cpr, new Integer(1));
7699 } else {
7700 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7701 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702 cpr.clients.add(r);
7703 } else {
7704 cpr.externals++;
7705 }
7706
7707 if (cpr.app != null) {
7708 updateOomAdjLocked(cpr.app);
7709 }
7710
7711 Binder.restoreCallingIdentity(origId);
7712
7713 } else {
7714 try {
7715 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007716 resolveContentProvider(name,
7717 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718 } catch (RemoteException ex) {
7719 }
7720 if (cpi == null) {
7721 return null;
7722 }
7723
7724 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7725 return new ContentProviderHolder(cpi,
7726 cpi.readPermission != null
7727 ? cpi.readPermission : cpi.writePermission);
7728 }
7729
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007730 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7731 && !cpi.processName.equals("system")) {
7732 // If this content provider does not run in the system
7733 // process, and the system is not yet ready to run other
7734 // processes, then fail fast instead of hanging.
7735 throw new IllegalArgumentException(
7736 "Attempt to launch content provider before system ready");
7737 }
7738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007739 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7740 final boolean firstClass = cpr == null;
7741 if (firstClass) {
7742 try {
7743 ApplicationInfo ai =
7744 ActivityThread.getPackageManager().
7745 getApplicationInfo(
7746 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007747 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007748 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007749 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 + cpi.name);
7751 return null;
7752 }
7753 cpr = new ContentProviderRecord(cpi, ai);
7754 } catch (RemoteException ex) {
7755 // pm is in same process, this will never happen.
7756 }
7757 }
7758
7759 if (r != null && cpr.canRunHere(r)) {
7760 // If this is a multiprocess provider, then just return its
7761 // info and allow the caller to instantiate it. Only do
7762 // this if the provider is the same user as the caller's
7763 // process, or can run as root (so can be in any process).
7764 return cpr;
7765 }
7766
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007767 if (DEBUG_PROVIDER) {
7768 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007769 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007770 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 }
7772
7773 // This is single process, and our app is now connecting to it.
7774 // See if we are already in the process of launching this
7775 // provider.
7776 final int N = mLaunchingProviders.size();
7777 int i;
7778 for (i=0; i<N; i++) {
7779 if (mLaunchingProviders.get(i) == cpr) {
7780 break;
7781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 }
7783
7784 // If the provider is not already being launched, then get it
7785 // started.
7786 if (i >= N) {
7787 final long origId = Binder.clearCallingIdentity();
7788 ProcessRecord proc = startProcessLocked(cpi.processName,
7789 cpr.appInfo, false, 0, "content provider",
7790 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007791 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007793 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 + cpi.applicationInfo.packageName + "/"
7795 + cpi.applicationInfo.uid + " for provider "
7796 + name + ": process is bad");
7797 return null;
7798 }
7799 cpr.launchingApp = proc;
7800 mLaunchingProviders.add(cpr);
7801 Binder.restoreCallingIdentity(origId);
7802 }
7803
7804 // Make sure the provider is published (the same provider class
7805 // may be published under multiple names).
7806 if (firstClass) {
7807 mProvidersByClass.put(cpi.name, cpr);
7808 }
7809 mProvidersByName.put(name, cpr);
7810
7811 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007812 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007813 "Adding provider requested by "
7814 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007815 + cpr.info.processName);
7816 Integer cnt = r.conProviders.get(cpr);
7817 if (cnt == null) {
7818 r.conProviders.put(cpr, new Integer(1));
7819 } else {
7820 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007822 cpr.clients.add(r);
7823 } else {
7824 cpr.externals++;
7825 }
7826 }
7827 }
7828
7829 // Wait for the provider to be published...
7830 synchronized (cpr) {
7831 while (cpr.provider == null) {
7832 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007833 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007834 + cpi.applicationInfo.packageName + "/"
7835 + cpi.applicationInfo.uid + " for provider "
7836 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007837 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 cpi.applicationInfo.packageName,
7839 cpi.applicationInfo.uid, name);
7840 return null;
7841 }
7842 try {
7843 cpr.wait();
7844 } catch (InterruptedException ex) {
7845 }
7846 }
7847 }
7848 return cpr;
7849 }
7850
7851 public final ContentProviderHolder getContentProvider(
7852 IApplicationThread caller, String name) {
7853 if (caller == null) {
7854 String msg = "null IApplicationThread when getting content provider "
7855 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007856 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007857 throw new SecurityException(msg);
7858 }
7859
7860 return getContentProviderImpl(caller, name);
7861 }
7862
7863 private ContentProviderHolder getContentProviderExternal(String name) {
7864 return getContentProviderImpl(null, name);
7865 }
7866
7867 /**
7868 * Drop a content provider from a ProcessRecord's bookkeeping
7869 * @param cpr
7870 */
7871 public void removeContentProvider(IApplicationThread caller, String name) {
7872 synchronized (this) {
7873 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7874 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007875 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007876 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007877 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007878 return;
7879 }
7880 final ProcessRecord r = getRecordForAppLocked(caller);
7881 if (r == null) {
7882 throw new SecurityException(
7883 "Unable to find app for caller " + caller +
7884 " when removing content provider " + name);
7885 }
7886 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007887 ContentProviderRecord localCpr = (ContentProviderRecord)
7888 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007889 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007890 + r.info.processName + " from process "
7891 + localCpr.appInfo.processName);
7892 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007893 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007894 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007895 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007896 return;
7897 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007898 Integer cnt = r.conProviders.get(localCpr);
7899 if (cnt == null || cnt.intValue() <= 1) {
7900 localCpr.clients.remove(r);
7901 r.conProviders.remove(localCpr);
7902 } else {
7903 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007905 }
7906 updateOomAdjLocked();
7907 }
7908 }
7909
7910 private void removeContentProviderExternal(String name) {
7911 synchronized (this) {
7912 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7913 if(cpr == null) {
7914 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007915 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007916 return;
7917 }
7918
7919 //update content provider record entry info
7920 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7921 localCpr.externals--;
7922 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007923 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007924 }
7925 updateOomAdjLocked();
7926 }
7927 }
7928
7929 public final void publishContentProviders(IApplicationThread caller,
7930 List<ContentProviderHolder> providers) {
7931 if (providers == null) {
7932 return;
7933 }
7934
7935 synchronized(this) {
7936 final ProcessRecord r = getRecordForAppLocked(caller);
7937 if (r == null) {
7938 throw new SecurityException(
7939 "Unable to find app for caller " + caller
7940 + " (pid=" + Binder.getCallingPid()
7941 + ") when publishing content providers");
7942 }
7943
7944 final long origId = Binder.clearCallingIdentity();
7945
7946 final int N = providers.size();
7947 for (int i=0; i<N; i++) {
7948 ContentProviderHolder src = providers.get(i);
7949 if (src == null || src.info == null || src.provider == null) {
7950 continue;
7951 }
7952 ContentProviderRecord dst =
7953 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7954 if (dst != null) {
7955 mProvidersByClass.put(dst.info.name, dst);
7956 String names[] = dst.info.authority.split(";");
7957 for (int j = 0; j < names.length; j++) {
7958 mProvidersByName.put(names[j], dst);
7959 }
7960
7961 int NL = mLaunchingProviders.size();
7962 int j;
7963 for (j=0; j<NL; j++) {
7964 if (mLaunchingProviders.get(j) == dst) {
7965 mLaunchingProviders.remove(j);
7966 j--;
7967 NL--;
7968 }
7969 }
7970 synchronized (dst) {
7971 dst.provider = src.provider;
7972 dst.app = r;
7973 dst.notifyAll();
7974 }
7975 updateOomAdjLocked(r);
7976 }
7977 }
7978
7979 Binder.restoreCallingIdentity(origId);
7980 }
7981 }
7982
7983 public static final void installSystemProviders() {
7984 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7985 List providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007986 if (providers != null) {
7987 for (int i=providers.size()-1; i>=0; i--) {
7988 ProviderInfo pi = (ProviderInfo)providers.get(i);
7989 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007990 Slog.w(TAG, "Not installing system proc provider " + pi.name
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007991 + ": not system .apk");
7992 providers.remove(i);
7993 }
7994 }
7995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007996 mSystemThread.installSystemProviders(providers);
7997 }
7998
7999 // =========================================================
8000 // GLOBAL MANAGEMENT
8001 // =========================================================
8002
8003 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8004 ApplicationInfo info, String customProcess) {
8005 String proc = customProcess != null ? customProcess : info.processName;
8006 BatteryStatsImpl.Uid.Proc ps = null;
8007 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8008 synchronized (stats) {
8009 ps = stats.getProcessStatsLocked(info.uid, proc);
8010 }
8011 return new ProcessRecord(ps, thread, info, proc);
8012 }
8013
8014 final ProcessRecord addAppLocked(ApplicationInfo info) {
8015 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8016
8017 if (app == null) {
8018 app = newProcessRecordLocked(null, info, null);
8019 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008020 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 }
8022
8023 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8024 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8025 app.persistent = true;
8026 app.maxAdj = CORE_SERVER_ADJ;
8027 }
8028 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8029 mPersistentStartingProcesses.add(app);
8030 startProcessLocked(app, "added application", app.processName);
8031 }
8032
8033 return app;
8034 }
8035
8036 public void unhandledBack() {
8037 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8038 "unhandledBack()");
8039
8040 synchronized(this) {
8041 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008042 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008043 TAG, "Performing unhandledBack(): stack size = " + count);
8044 if (count > 1) {
8045 final long origId = Binder.clearCallingIdentity();
8046 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8047 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8048 Binder.restoreCallingIdentity(origId);
8049 }
8050 }
8051 }
8052
8053 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8054 String name = uri.getAuthority();
8055 ContentProviderHolder cph = getContentProviderExternal(name);
8056 ParcelFileDescriptor pfd = null;
8057 if (cph != null) {
8058 // We record the binder invoker's uid in thread-local storage before
8059 // going to the content provider to open the file. Later, in the code
8060 // that handles all permissions checks, we look for this uid and use
8061 // that rather than the Activity Manager's own uid. The effect is that
8062 // we do the check against the caller's permissions even though it looks
8063 // to the content provider like the Activity Manager itself is making
8064 // the request.
8065 sCallerIdentity.set(new Identity(
8066 Binder.getCallingPid(), Binder.getCallingUid()));
8067 try {
8068 pfd = cph.provider.openFile(uri, "r");
8069 } catch (FileNotFoundException e) {
8070 // do nothing; pfd will be returned null
8071 } finally {
8072 // Ensure that whatever happens, we clean up the identity state
8073 sCallerIdentity.remove();
8074 }
8075
8076 // We've got the fd now, so we're done with the provider.
8077 removeContentProviderExternal(name);
8078 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008079 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008080 }
8081 return pfd;
8082 }
8083
8084 public void goingToSleep() {
8085 synchronized(this) {
8086 mSleeping = true;
8087 mWindowManager.setEventDispatching(false);
8088
8089 if (mResumedActivity != null) {
8090 pauseIfSleepingLocked();
8091 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008092 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008093 }
8094 }
8095 }
8096
Dianne Hackborn55280a92009-05-07 15:53:46 -07008097 public boolean shutdown(int timeout) {
8098 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8099 != PackageManager.PERMISSION_GRANTED) {
8100 throw new SecurityException("Requires permission "
8101 + android.Manifest.permission.SHUTDOWN);
8102 }
8103
8104 boolean timedout = false;
8105
8106 synchronized(this) {
8107 mShuttingDown = true;
8108 mWindowManager.setEventDispatching(false);
8109
8110 if (mResumedActivity != null) {
8111 pauseIfSleepingLocked();
8112 final long endTime = System.currentTimeMillis() + timeout;
8113 while (mResumedActivity != null || mPausingActivity != null) {
8114 long delay = endTime - System.currentTimeMillis();
8115 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008116 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008117 timedout = true;
8118 break;
8119 }
8120 try {
8121 this.wait();
8122 } catch (InterruptedException e) {
8123 }
8124 }
8125 }
8126 }
8127
8128 mUsageStatsService.shutdown();
8129 mBatteryStatsService.shutdown();
8130
8131 return timedout;
8132 }
8133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008134 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008135 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008136 if (!mGoingToSleep.isHeld()) {
8137 mGoingToSleep.acquire();
8138 if (mLaunchingActivity.isHeld()) {
8139 mLaunchingActivity.release();
8140 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8141 }
8142 }
8143
8144 // If we are not currently pausing an activity, get the current
8145 // one to pause. If we are pausing one, we will just let that stuff
8146 // run and release the wake lock when all done.
8147 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008148 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8149 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008150 startPausingLocked(false, true);
8151 }
8152 }
8153 }
8154
8155 public void wakingUp() {
8156 synchronized(this) {
8157 if (mGoingToSleep.isHeld()) {
8158 mGoingToSleep.release();
8159 }
8160 mWindowManager.setEventDispatching(true);
8161 mSleeping = false;
8162 resumeTopActivityLocked(null);
8163 }
8164 }
8165
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008166 public void stopAppSwitches() {
8167 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8168 != PackageManager.PERMISSION_GRANTED) {
8169 throw new SecurityException("Requires permission "
8170 + android.Manifest.permission.STOP_APP_SWITCHES);
8171 }
8172
8173 synchronized(this) {
8174 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8175 + APP_SWITCH_DELAY_TIME;
8176 mDidAppSwitch = false;
8177 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8178 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8179 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8180 }
8181 }
8182
8183 public void resumeAppSwitches() {
8184 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8185 != PackageManager.PERMISSION_GRANTED) {
8186 throw new SecurityException("Requires permission "
8187 + android.Manifest.permission.STOP_APP_SWITCHES);
8188 }
8189
8190 synchronized(this) {
8191 // Note that we don't execute any pending app switches... we will
8192 // let those wait until either the timeout, or the next start
8193 // activity request.
8194 mAppSwitchesAllowedTime = 0;
8195 }
8196 }
8197
8198 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8199 String name) {
8200 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8201 return true;
8202 }
8203
8204 final int perm = checkComponentPermission(
8205 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8206 callingUid, -1);
8207 if (perm == PackageManager.PERMISSION_GRANTED) {
8208 return true;
8209 }
8210
Joe Onorato8a9b2202010-02-26 18:56:32 -08008211 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008212 return false;
8213 }
8214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008215 public void setDebugApp(String packageName, boolean waitForDebugger,
8216 boolean persistent) {
8217 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8218 "setDebugApp()");
8219
8220 // Note that this is not really thread safe if there are multiple
8221 // callers into it at the same time, but that's not a situation we
8222 // care about.
8223 if (persistent) {
8224 final ContentResolver resolver = mContext.getContentResolver();
8225 Settings.System.putString(
8226 resolver, Settings.System.DEBUG_APP,
8227 packageName);
8228 Settings.System.putInt(
8229 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8230 waitForDebugger ? 1 : 0);
8231 }
8232
8233 synchronized (this) {
8234 if (!persistent) {
8235 mOrigDebugApp = mDebugApp;
8236 mOrigWaitForDebugger = mWaitForDebugger;
8237 }
8238 mDebugApp = packageName;
8239 mWaitForDebugger = waitForDebugger;
8240 mDebugTransient = !persistent;
8241 if (packageName != null) {
8242 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008243 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008244 Binder.restoreCallingIdentity(origId);
8245 }
8246 }
8247 }
8248
8249 public void setAlwaysFinish(boolean enabled) {
8250 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8251 "setAlwaysFinish()");
8252
8253 Settings.System.putInt(
8254 mContext.getContentResolver(),
8255 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8256
8257 synchronized (this) {
8258 mAlwaysFinishActivities = enabled;
8259 }
8260 }
8261
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008262 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008263 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008264 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008265 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008266 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008267 }
8268 }
8269
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008270 public boolean isUserAMonkey() {
8271 // For now the fact that there is a controller implies
8272 // we have a monkey.
8273 synchronized (this) {
8274 return mController != null;
8275 }
8276 }
8277
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008278 public void registerActivityWatcher(IActivityWatcher watcher) {
8279 mWatchers.register(watcher);
8280 }
8281
8282 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8283 mWatchers.unregister(watcher);
8284 }
8285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008286 public final void enterSafeMode() {
8287 synchronized(this) {
8288 // It only makes sense to do this before the system is ready
8289 // and started launching other packages.
8290 if (!mSystemReady) {
8291 try {
8292 ActivityThread.getPackageManager().enterSafeMode();
8293 } catch (RemoteException e) {
8294 }
8295
8296 View v = LayoutInflater.from(mContext).inflate(
8297 com.android.internal.R.layout.safe_mode, null);
8298 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8299 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8300 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8301 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8302 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8303 lp.format = v.getBackground().getOpacity();
8304 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8305 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8306 ((WindowManager)mContext.getSystemService(
8307 Context.WINDOW_SERVICE)).addView(v, lp);
8308 }
8309 }
8310 }
8311
8312 public void noteWakeupAlarm(IIntentSender sender) {
8313 if (!(sender instanceof PendingIntentRecord)) {
8314 return;
8315 }
8316 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8317 synchronized (stats) {
8318 if (mBatteryStatsService.isOnBattery()) {
8319 mBatteryStatsService.enforceCallingPermission();
8320 PendingIntentRecord rec = (PendingIntentRecord)sender;
8321 int MY_UID = Binder.getCallingUid();
8322 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8323 BatteryStatsImpl.Uid.Pkg pkg =
8324 stats.getPackageStatsLocked(uid, rec.key.packageName);
8325 pkg.incWakeupsLocked();
8326 }
8327 }
8328 }
8329
8330 public boolean killPidsForMemory(int[] pids) {
8331 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8332 throw new SecurityException("killPidsForMemory only available to the system");
8333 }
8334
8335 // XXX Note: don't acquire main activity lock here, because the window
8336 // manager calls in with its locks held.
8337
8338 boolean killed = false;
8339 synchronized (mPidsSelfLocked) {
8340 int[] types = new int[pids.length];
8341 int worstType = 0;
8342 for (int i=0; i<pids.length; i++) {
8343 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8344 if (proc != null) {
8345 int type = proc.setAdj;
8346 types[i] = type;
8347 if (type > worstType) {
8348 worstType = type;
8349 }
8350 }
8351 }
8352
8353 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8354 // then constrain it so we will kill all hidden procs.
8355 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8356 worstType = HIDDEN_APP_MIN_ADJ;
8357 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008358 Slog.w(TAG, "Killing processes for memory at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008359 for (int i=0; i<pids.length; i++) {
8360 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8361 if (proc == null) {
8362 continue;
8363 }
8364 int adj = proc.setAdj;
8365 if (adj >= worstType) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008366 Slog.w(TAG, "Killing for memory: " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008367 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008368 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008369 proc.processName, adj);
8370 killed = true;
8371 Process.killProcess(pids[i]);
8372 }
8373 }
8374 }
8375 return killed;
8376 }
8377
8378 public void reportPss(IApplicationThread caller, int pss) {
8379 Watchdog.PssRequestor req;
8380 String name;
8381 ProcessRecord callerApp;
8382 synchronized (this) {
8383 if (caller == null) {
8384 return;
8385 }
8386 callerApp = getRecordForAppLocked(caller);
8387 if (callerApp == null) {
8388 return;
8389 }
8390 callerApp.lastPss = pss;
8391 req = callerApp;
8392 name = callerApp.processName;
8393 }
8394 Watchdog.getInstance().reportPss(req, name, pss);
8395 if (!callerApp.persistent) {
8396 removeRequestedPss(callerApp);
8397 }
8398 }
8399
8400 public void requestPss(Runnable completeCallback) {
8401 ArrayList<ProcessRecord> procs;
8402 synchronized (this) {
8403 mRequestPssCallback = completeCallback;
8404 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008405 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8406 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008407 if (!proc.persistent) {
8408 mRequestPssList.add(proc);
8409 }
8410 }
8411 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8412 }
8413
8414 int oldPri = Process.getThreadPriority(Process.myTid());
8415 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8416 for (int i=procs.size()-1; i>=0; i--) {
8417 ProcessRecord proc = procs.get(i);
8418 proc.lastPss = 0;
8419 proc.requestPss();
8420 }
8421 Process.setThreadPriority(oldPri);
8422 }
8423
8424 void removeRequestedPss(ProcessRecord proc) {
8425 Runnable callback = null;
8426 synchronized (this) {
8427 if (mRequestPssList.remove(proc)) {
8428 if (mRequestPssList.size() == 0) {
8429 callback = mRequestPssCallback;
8430 mRequestPssCallback = null;
8431 }
8432 }
8433 }
8434
8435 if (callback != null) {
8436 callback.run();
8437 }
8438 }
8439
8440 public void collectPss(Watchdog.PssStats stats) {
8441 stats.mEmptyPss = 0;
8442 stats.mEmptyCount = 0;
8443 stats.mBackgroundPss = 0;
8444 stats.mBackgroundCount = 0;
8445 stats.mServicePss = 0;
8446 stats.mServiceCount = 0;
8447 stats.mVisiblePss = 0;
8448 stats.mVisibleCount = 0;
8449 stats.mForegroundPss = 0;
8450 stats.mForegroundCount = 0;
8451 stats.mNoPssCount = 0;
8452 synchronized (this) {
8453 int i;
8454 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8455 ? mProcDeaths.length : stats.mProcDeaths.length;
8456 int aggr = 0;
8457 for (i=0; i<NPD; i++) {
8458 aggr += mProcDeaths[i];
8459 stats.mProcDeaths[i] = aggr;
8460 }
8461 while (i<stats.mProcDeaths.length) {
8462 stats.mProcDeaths[i] = 0;
8463 i++;
8464 }
8465
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008466 for (i=mLruProcesses.size()-1; i>=0; i--) {
8467 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008468 if (proc.persistent) {
8469 continue;
8470 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008471 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008472 if (proc.lastPss == 0) {
8473 stats.mNoPssCount++;
8474 continue;
8475 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008476 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8477 if (proc.empty) {
8478 stats.mEmptyPss += proc.lastPss;
8479 stats.mEmptyCount++;
8480 } else {
8481 stats.mBackgroundPss += proc.lastPss;
8482 stats.mBackgroundCount++;
8483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008484 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8485 stats.mVisiblePss += proc.lastPss;
8486 stats.mVisibleCount++;
8487 } else {
8488 stats.mForegroundPss += proc.lastPss;
8489 stats.mForegroundCount++;
8490 }
8491 }
8492 }
8493 }
8494
8495 public final void startRunning(String pkg, String cls, String action,
8496 String data) {
8497 synchronized(this) {
8498 if (mStartRunning) {
8499 return;
8500 }
8501 mStartRunning = true;
8502 mTopComponent = pkg != null && cls != null
8503 ? new ComponentName(pkg, cls) : null;
8504 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8505 mTopData = data;
8506 if (!mSystemReady) {
8507 return;
8508 }
8509 }
8510
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008511 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008512 }
8513
8514 private void retrieveSettings() {
8515 final ContentResolver resolver = mContext.getContentResolver();
8516 String debugApp = Settings.System.getString(
8517 resolver, Settings.System.DEBUG_APP);
8518 boolean waitForDebugger = Settings.System.getInt(
8519 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8520 boolean alwaysFinishActivities = Settings.System.getInt(
8521 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8522
8523 Configuration configuration = new Configuration();
8524 Settings.System.getConfiguration(resolver, configuration);
8525
8526 synchronized (this) {
8527 mDebugApp = mOrigDebugApp = debugApp;
8528 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8529 mAlwaysFinishActivities = alwaysFinishActivities;
8530 // This happens before any activities are started, so we can
8531 // change mConfiguration in-place.
8532 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008533 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008534 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008535 }
8536 }
8537
8538 public boolean testIsSystemReady() {
8539 // no need to synchronize(this) just to read & return the value
8540 return mSystemReady;
8541 }
8542
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008543 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008544 // In the simulator, startRunning will never have been called, which
8545 // normally sets a few crucial variables. Do it here instead.
8546 if (!Process.supportsProcesses()) {
8547 mStartRunning = true;
8548 mTopAction = Intent.ACTION_MAIN;
8549 }
8550
8551 synchronized(this) {
8552 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008553 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 return;
8555 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008556
8557 // Check to see if there are any update receivers to run.
8558 if (!mDidUpdate) {
8559 if (mWaitingUpdate) {
8560 return;
8561 }
8562 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8563 List<ResolveInfo> ris = null;
8564 try {
8565 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8566 intent, null, 0);
8567 } catch (RemoteException e) {
8568 }
8569 if (ris != null) {
8570 for (int i=ris.size()-1; i>=0; i--) {
8571 if ((ris.get(i).activityInfo.applicationInfo.flags
8572 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8573 ris.remove(i);
8574 }
8575 }
8576 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8577 for (int i=0; i<ris.size(); i++) {
8578 ActivityInfo ai = ris.get(i).activityInfo;
8579 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8580 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008581 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008582 finisher = new IIntentReceiver.Stub() {
8583 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008584 String data, Bundle extras, boolean ordered,
8585 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008586 throws RemoteException {
8587 synchronized (ActivityManagerService.this) {
8588 mDidUpdate = true;
8589 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008590 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008591 }
8592 };
8593 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008594 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008595 broadcastIntentLocked(null, null, intent, null, finisher,
8596 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008597 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008598 mWaitingUpdate = true;
8599 }
8600 }
8601 }
8602 if (mWaitingUpdate) {
8603 return;
8604 }
8605 mDidUpdate = true;
8606 }
8607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008608 mSystemReady = true;
8609 if (!mStartRunning) {
8610 return;
8611 }
8612 }
8613
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008614 ArrayList<ProcessRecord> procsToKill = null;
8615 synchronized(mPidsSelfLocked) {
8616 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8617 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8618 if (!isAllowedWhileBooting(proc.info)){
8619 if (procsToKill == null) {
8620 procsToKill = new ArrayList<ProcessRecord>();
8621 }
8622 procsToKill.add(proc);
8623 }
8624 }
8625 }
8626
8627 if (procsToKill != null) {
8628 synchronized(this) {
8629 for (int i=procsToKill.size()-1; i>=0; i--) {
8630 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008631 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008632 removeProcessLocked(proc, true);
8633 }
8634 }
8635 }
8636
Joe Onorato8a9b2202010-02-26 18:56:32 -08008637 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008638 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 SystemClock.uptimeMillis());
8640
8641 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008642 // Make sure we have no pre-ready processes sitting around.
8643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8645 ResolveInfo ri = mContext.getPackageManager()
8646 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008647 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008648 CharSequence errorMsg = null;
8649 if (ri != null) {
8650 ActivityInfo ai = ri.activityInfo;
8651 ApplicationInfo app = ai.applicationInfo;
8652 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8653 mTopAction = Intent.ACTION_FACTORY_TEST;
8654 mTopData = null;
8655 mTopComponent = new ComponentName(app.packageName,
8656 ai.name);
8657 } else {
8658 errorMsg = mContext.getResources().getText(
8659 com.android.internal.R.string.factorytest_not_system);
8660 }
8661 } else {
8662 errorMsg = mContext.getResources().getText(
8663 com.android.internal.R.string.factorytest_no_action);
8664 }
8665 if (errorMsg != null) {
8666 mTopAction = null;
8667 mTopData = null;
8668 mTopComponent = null;
8669 Message msg = Message.obtain();
8670 msg.what = SHOW_FACTORY_ERROR_MSG;
8671 msg.getData().putCharSequence("msg", errorMsg);
8672 mHandler.sendMessage(msg);
8673 }
8674 }
8675 }
8676
8677 retrieveSettings();
8678
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008679 if (goingCallback != null) goingCallback.run();
8680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008681 synchronized (this) {
8682 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8683 try {
8684 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008685 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008686 if (apps != null) {
8687 int N = apps.size();
8688 int i;
8689 for (i=0; i<N; i++) {
8690 ApplicationInfo info
8691 = (ApplicationInfo)apps.get(i);
8692 if (info != null &&
8693 !info.packageName.equals("android")) {
8694 addAppLocked(info);
8695 }
8696 }
8697 }
8698 } catch (RemoteException ex) {
8699 // pm is in same process, this will never happen.
8700 }
8701 }
8702
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008703 // Start up initial activity.
8704 mBooting = true;
8705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008706 try {
8707 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8708 Message msg = Message.obtain();
8709 msg.what = SHOW_UID_ERROR_MSG;
8710 mHandler.sendMessage(msg);
8711 }
8712 } catch (RemoteException e) {
8713 }
8714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008715 resumeTopActivityLocked(null);
8716 }
8717 }
8718
Dan Egnorb7f03672009-12-09 16:22:32 -08008719 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008720 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008721 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008722 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008723 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008724 startAppProblemLocked(app);
8725 app.stopFreezingAllLocked();
8726 return handleAppCrashLocked(app);
8727 }
8728
Dan Egnorb7f03672009-12-09 16:22:32 -08008729 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008730 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008731 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008732 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008733 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8734 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008735 startAppProblemLocked(app);
8736 app.stopFreezingAllLocked();
8737 }
8738
8739 /**
8740 * Generate a process error record, suitable for attachment to a ProcessRecord.
8741 *
8742 * @param app The ProcessRecord in which the error occurred.
8743 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8744 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008745 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008746 * @param shortMsg Short message describing the crash.
8747 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008748 * @param stackTrace Full crash stack trace, may be null.
8749 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008750 * @return Returns a fully-formed AppErrorStateInfo record.
8751 */
8752 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008753 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008754 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008756 report.condition = condition;
8757 report.processName = app.processName;
8758 report.pid = app.pid;
8759 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008760 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008761 report.shortMsg = shortMsg;
8762 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008763 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008764
8765 return report;
8766 }
8767
Dan Egnor42471dd2010-01-07 17:25:22 -08008768 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008769 synchronized (this) {
8770 app.crashing = false;
8771 app.crashingReport = null;
8772 app.notResponding = false;
8773 app.notRespondingReport = null;
8774 if (app.anrDialog == fromDialog) {
8775 app.anrDialog = null;
8776 }
8777 if (app.waitDialog == fromDialog) {
8778 app.waitDialog = null;
8779 }
8780 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008781 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008782 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008783 + app.processName
8784 + " (pid=" + app.pid + ") at user's request");
8785 Process.killProcess(app.pid);
8786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008787 }
8788 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008789
Dan Egnorb7f03672009-12-09 16:22:32 -08008790 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008791 long now = SystemClock.uptimeMillis();
8792
8793 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8794 app.info.uid);
8795 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8796 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008797 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008798 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008799 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008800 app.info.processName, app.info.uid);
8801 killServicesLocked(app, false);
8802 for (int i=mHistory.size()-1; i>=0; i--) {
8803 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8804 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008805 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008806 + r.intent.getComponent().flattenToShortString());
8807 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8808 }
8809 }
8810 if (!app.persistent) {
8811 // We don't want to start this process again until the user
8812 // explicitly does so... but for persistent process, we really
8813 // need to keep it running. If a persistent process is actually
8814 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008815 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 app.info.processName);
8817 mBadProcesses.put(app.info.processName, app.info.uid, now);
8818 app.bad = true;
8819 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8820 app.removed = true;
8821 removeProcessLocked(app, false);
8822 return false;
8823 }
8824 }
8825
8826 // Bump up the crash count of any services currently running in the proc.
8827 if (app.services.size() != 0) {
8828 // Any services running in the application need to be placed
8829 // back in the pending list.
8830 Iterator it = app.services.iterator();
8831 while (it.hasNext()) {
8832 ServiceRecord sr = (ServiceRecord)it.next();
8833 sr.crashCount++;
8834 }
8835 }
8836
8837 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8838 return true;
8839 }
8840
8841 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008842 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8843 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008844 skipCurrentReceiverLocked(app);
8845 }
8846
8847 void skipCurrentReceiverLocked(ProcessRecord app) {
8848 boolean reschedule = false;
8849 BroadcastRecord r = app.curReceiver;
8850 if (r != null) {
8851 // The current broadcast is waiting for this app's receiver
8852 // to be finished. Looks like that's not going to happen, so
8853 // let the broadcast continue.
8854 logBroadcastReceiverDiscard(r);
8855 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8856 r.resultExtras, r.resultAbort, true);
8857 reschedule = true;
8858 }
8859 r = mPendingBroadcast;
8860 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008861 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008862 "skip & discard pending app " + r);
8863 logBroadcastReceiverDiscard(r);
8864 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8865 r.resultExtras, r.resultAbort, true);
8866 reschedule = true;
8867 }
8868 if (reschedule) {
8869 scheduleBroadcastsLocked();
8870 }
8871 }
8872
Dan Egnor60d87622009-12-16 16:32:58 -08008873 /**
8874 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8875 * The application process will exit immediately after this call returns.
8876 * @param app object of the crashing app, null for the system server
8877 * @param crashInfo describing the exception
8878 */
8879 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8880 ProcessRecord r = findAppProcess(app);
8881
8882 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8883 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008884 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008885 crashInfo.exceptionClassName,
8886 crashInfo.exceptionMessage,
8887 crashInfo.throwFileName,
8888 crashInfo.throwLineNumber);
8889
Dan Egnor42471dd2010-01-07 17:25:22 -08008890 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008891
8892 crashApplication(r, crashInfo);
8893 }
8894
8895 /**
8896 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8897 * @param app object of the crashing app, null for the system server
8898 * @param tag reported by the caller
8899 * @param crashInfo describing the context of the error
8900 * @return true if the process should exit immediately (WTF is fatal)
8901 */
8902 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008903 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008904 ProcessRecord r = findAppProcess(app);
8905
8906 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8907 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008908 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008909 tag, crashInfo.exceptionMessage);
8910
Dan Egnor42471dd2010-01-07 17:25:22 -08008911 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008912
Doug Zongker43866e02010-01-07 12:09:54 -08008913 if (Settings.Secure.getInt(mContext.getContentResolver(),
8914 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008915 crashApplication(r, crashInfo);
8916 return true;
8917 } else {
8918 return false;
8919 }
8920 }
8921
8922 /**
8923 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8924 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8925 */
8926 private ProcessRecord findAppProcess(IBinder app) {
8927 if (app == null) {
8928 return null;
8929 }
8930
8931 synchronized (this) {
8932 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8933 final int NA = apps.size();
8934 for (int ia=0; ia<NA; ia++) {
8935 ProcessRecord p = apps.valueAt(ia);
8936 if (p.thread != null && p.thread.asBinder() == app) {
8937 return p;
8938 }
8939 }
8940 }
8941
Joe Onorato8a9b2202010-02-26 18:56:32 -08008942 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008943 return null;
8944 }
8945 }
8946
8947 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008948 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008949 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008950 * @param process which caused the error, null means the system server
8951 * @param activity which triggered the error, null if unknown
8952 * @param parent activity related to the error, null if unknown
8953 * @param subject line related to the error, null if absent
8954 * @param report in long form describing the error, null if absent
8955 * @param logFile to include in the report, null if none
8956 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008957 */
Dan Egnor42471dd2010-01-07 17:25:22 -08008958 private void addErrorToDropBox(String eventType,
8959 ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
8960 String subject, String report, File logFile,
Dan Egnor60d87622009-12-16 16:32:58 -08008961 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008962 String dropboxTag;
8963 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008964 dropboxTag = "system_server_" + eventType;
Dan Egnor42471dd2010-01-07 17:25:22 -08008965 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008966 dropboxTag = "system_app_" + eventType;
8967 } else {
8968 dropboxTag = "data_app_" + eventType;
8969 }
8970
8971 DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
8972 if (dbox != null && dbox.isTagEnabled(dropboxTag)) {
8973 StringBuilder sb = new StringBuilder(1024);
Dan Egnor42471dd2010-01-07 17:25:22 -08008974 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008975 sb.append("Process: system_server\n");
8976 } else {
Dan Egnor42471dd2010-01-07 17:25:22 -08008977 sb.append("Process: ").append(process.processName).append("\n");
Dan Egnor66c40e72010-01-26 16:23:11 -08008978 }
8979 if (process != null) {
8980 int flags = process.info.flags;
8981 IPackageManager pm = ActivityThread.getPackageManager();
8982 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8983 for (String pkg : process.pkgList) {
8984 sb.append("Package: ").append(pkg);
8985 try {
8986 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8987 if (pi != null) {
8988 sb.append(" v").append(pi.versionCode);
8989 if (pi.versionName != null) {
8990 sb.append(" (").append(pi.versionName).append(")");
8991 }
8992 }
8993 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008994 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor66c40e72010-01-26 16:23:11 -08008995 }
8996 sb.append("\n");
8997 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008998 }
8999 if (activity != null) {
9000 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9001 }
9002 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9003 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9004 }
9005 if (parent != null && parent != activity) {
9006 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9007 }
9008 if (subject != null) {
9009 sb.append("Subject: ").append(subject).append("\n");
9010 }
9011 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9012 sb.append("\n");
9013 if (report != null) {
9014 sb.append(report);
9015 }
9016 if (logFile != null) {
9017 try {
9018 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9019 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009020 Slog.e(TAG, "Error reading " + logFile, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009021 }
9022 }
Dan Egnor60d87622009-12-16 16:32:58 -08009023 if (crashInfo != null && crashInfo.stackTrace != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009024 sb.append(crashInfo.stackTrace);
Dan Egnor60d87622009-12-16 16:32:58 -08009025 }
9026 dbox.addText(dropboxTag, sb.toString());
9027 }
9028 }
9029
9030 /**
9031 * Bring up the "unexpected error" dialog box for a crashing app.
9032 * Deal with edge cases (intercepts from instrumented applications,
9033 * ActivityController, error intent receivers, that sort of thing).
9034 * @param r the application crashing
9035 * @param crashInfo describing the failure
9036 */
9037 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009038 long timeMillis = System.currentTimeMillis();
9039 String shortMsg = crashInfo.exceptionClassName;
9040 String longMsg = crashInfo.exceptionMessage;
9041 String stackTrace = crashInfo.stackTrace;
9042 if (shortMsg != null && longMsg != null) {
9043 longMsg = shortMsg + ": " + longMsg;
9044 } else if (shortMsg != null) {
9045 longMsg = shortMsg;
9046 }
9047
Dan Egnor60d87622009-12-16 16:32:58 -08009048 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009049 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009050 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009051 try {
9052 String name = r != null ? r.processName : null;
9053 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009054 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009055 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009056 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009057 + " at watcher's request");
9058 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009059 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009060 }
9061 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009062 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009063 }
9064 }
9065
9066 final long origId = Binder.clearCallingIdentity();
9067
9068 // If this process is running instrumentation, finish it.
9069 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009070 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009071 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009072 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9073 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009074 Bundle info = new Bundle();
9075 info.putString("shortMsg", shortMsg);
9076 info.putString("longMsg", longMsg);
9077 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9078 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009079 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009080 }
9081
Dan Egnor60d87622009-12-16 16:32:58 -08009082 // If we can't identify the process or it's already exceeded its crash quota,
9083 // quit right away without showing a crash dialog.
9084 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009085 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009086 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009087 }
9088
9089 Message msg = Message.obtain();
9090 msg.what = SHOW_ERROR_MSG;
9091 HashMap data = new HashMap();
9092 data.put("result", result);
9093 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009094 msg.obj = data;
9095 mHandler.sendMessage(msg);
9096
9097 Binder.restoreCallingIdentity(origId);
9098 }
9099
9100 int res = result.get();
9101
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009102 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009103 synchronized (this) {
9104 if (r != null) {
9105 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9106 SystemClock.uptimeMillis());
9107 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009108 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009109 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009110 }
9111 }
9112
9113 if (appErrorIntent != null) {
9114 try {
9115 mContext.startActivity(appErrorIntent);
9116 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009117 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009118 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009121
9122 Intent createAppErrorIntentLocked(ProcessRecord r,
9123 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9124 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009125 if (report == null) {
9126 return null;
9127 }
9128 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9129 result.setComponent(r.errorReportReceiver);
9130 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9131 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9132 return result;
9133 }
9134
Dan Egnorb7f03672009-12-09 16:22:32 -08009135 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9136 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009137 if (r.errorReportReceiver == null) {
9138 return null;
9139 }
9140
9141 if (!r.crashing && !r.notResponding) {
9142 return null;
9143 }
9144
Dan Egnorb7f03672009-12-09 16:22:32 -08009145 ApplicationErrorReport report = new ApplicationErrorReport();
9146 report.packageName = r.info.packageName;
9147 report.installerPackageName = r.errorReportReceiver.getPackageName();
9148 report.processName = r.processName;
9149 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009150 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009151
Dan Egnorb7f03672009-12-09 16:22:32 -08009152 if (r.crashing) {
9153 report.type = ApplicationErrorReport.TYPE_CRASH;
9154 report.crashInfo = crashInfo;
9155 } else if (r.notResponding) {
9156 report.type = ApplicationErrorReport.TYPE_ANR;
9157 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009158
Dan Egnorb7f03672009-12-09 16:22:32 -08009159 report.anrInfo.activity = r.notRespondingReport.tag;
9160 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9161 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009162 }
9163
Dan Egnorb7f03672009-12-09 16:22:32 -08009164 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009165 }
9166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009167 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9168 // assume our apps are happy - lazy create the list
9169 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9170
9171 synchronized (this) {
9172
9173 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009174 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9175 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009176 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9177 // This one's in trouble, so we'll generate a report for it
9178 // crashes are higher priority (in case there's a crash *and* an anr)
9179 ActivityManager.ProcessErrorStateInfo report = null;
9180 if (app.crashing) {
9181 report = app.crashingReport;
9182 } else if (app.notResponding) {
9183 report = app.notRespondingReport;
9184 }
9185
9186 if (report != null) {
9187 if (errList == null) {
9188 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9189 }
9190 errList.add(report);
9191 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009192 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009193 " crashing = " + app.crashing +
9194 " notResponding = " + app.notResponding);
9195 }
9196 }
9197 }
9198 }
9199
9200 return errList;
9201 }
9202
9203 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9204 // Lazy instantiation of list
9205 List<ActivityManager.RunningAppProcessInfo> runList = null;
9206 synchronized (this) {
9207 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009208 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9209 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009210 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9211 // Generate process state info for running application
9212 ActivityManager.RunningAppProcessInfo currApp =
9213 new ActivityManager.RunningAppProcessInfo(app.processName,
9214 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009215 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009216 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009217 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009218 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9219 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9220 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009221 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9222 } else if (adj >= HOME_APP_ADJ) {
9223 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9224 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009225 } else if (adj >= SECONDARY_SERVER_ADJ) {
9226 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9227 } else if (adj >= VISIBLE_APP_ADJ) {
9228 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9229 } else {
9230 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9231 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009232 currApp.importanceReasonCode = app.adjTypeCode;
9233 if (app.adjSource instanceof ProcessRecord) {
9234 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9235 } else if (app.adjSource instanceof HistoryRecord) {
9236 HistoryRecord r = (HistoryRecord)app.adjSource;
9237 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9238 }
9239 if (app.adjTarget instanceof ComponentName) {
9240 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9241 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009242 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009243 // + " lru=" + currApp.lru);
9244 if (runList == null) {
9245 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9246 }
9247 runList.add(currApp);
9248 }
9249 }
9250 }
9251 return runList;
9252 }
9253
9254 @Override
9255 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009256 if (checkCallingPermission(android.Manifest.permission.DUMP)
9257 != PackageManager.PERMISSION_GRANTED) {
9258 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9259 + Binder.getCallingPid()
9260 + ", uid=" + Binder.getCallingUid()
9261 + " without permission "
9262 + android.Manifest.permission.DUMP);
9263 return;
9264 }
9265
9266 boolean dumpAll = false;
9267
9268 int opti = 0;
9269 while (opti < args.length) {
9270 String opt = args[opti];
9271 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9272 break;
9273 }
9274 opti++;
9275 if ("-a".equals(opt)) {
9276 dumpAll = true;
9277 } else if ("-h".equals(opt)) {
9278 pw.println("Activity manager dump options:");
9279 pw.println(" [-a] [h- [cmd] ...");
9280 pw.println(" cmd may be one of:");
9281 pw.println(" activities: activity stack state");
9282 pw.println(" broadcasts: broadcast state");
9283 pw.println(" intents: pending intent state");
9284 pw.println(" processes: process state");
9285 pw.println(" providers: content provider state");
9286 pw.println(" services: service state");
9287 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009288 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009289 } else {
9290 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009292 }
9293
9294 // Is the caller requesting to dump a particular piece of data?
9295 if (opti < args.length) {
9296 String cmd = args[opti];
9297 opti++;
9298 if ("activities".equals(cmd) || "a".equals(cmd)) {
9299 synchronized (this) {
9300 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009301 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009302 return;
9303 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9304 synchronized (this) {
9305 dumpBroadcastsLocked(fd, pw, args, opti, true);
9306 }
9307 return;
9308 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9309 synchronized (this) {
9310 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9311 }
9312 return;
9313 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9314 synchronized (this) {
9315 dumpProcessesLocked(fd, pw, args, opti, true);
9316 }
9317 return;
9318 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9319 synchronized (this) {
9320 dumpProvidersLocked(fd, pw, args, opti, true);
9321 }
9322 return;
9323 } else if ("service".equals(cmd)) {
9324 dumpService(fd, pw, args, opti, true);
9325 return;
9326 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9327 synchronized (this) {
9328 dumpServicesLocked(fd, pw, args, opti, true);
9329 }
9330 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009331 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009332 }
9333
9334 // No piece of data specified, dump everything.
9335 synchronized (this) {
9336 boolean needSep;
9337 if (dumpAll) {
9338 pw.println("Providers in Current Activity Manager State:");
9339 }
9340 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9341 if (needSep) {
9342 pw.println(" ");
9343 }
9344 if (dumpAll) {
9345 pw.println("-------------------------------------------------------------------------------");
9346 pw.println("Broadcasts in Current Activity Manager State:");
9347 }
9348 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9349 if (needSep) {
9350 pw.println(" ");
9351 }
9352 if (dumpAll) {
9353 pw.println("-------------------------------------------------------------------------------");
9354 pw.println("Services in Current Activity Manager State:");
9355 }
9356 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9357 if (needSep) {
9358 pw.println(" ");
9359 }
9360 if (dumpAll) {
9361 pw.println("-------------------------------------------------------------------------------");
9362 pw.println("PendingIntents in Current Activity Manager State:");
9363 }
9364 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9365 if (needSep) {
9366 pw.println(" ");
9367 }
9368 if (dumpAll) {
9369 pw.println("-------------------------------------------------------------------------------");
9370 pw.println("Activities in Current Activity Manager State:");
9371 }
9372 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9373 if (needSep) {
9374 pw.println(" ");
9375 }
9376 if (dumpAll) {
9377 pw.println("-------------------------------------------------------------------------------");
9378 pw.println("Processes in Current Activity Manager State:");
9379 }
9380 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9381 }
9382 }
9383
9384 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9385 int opti, boolean dumpAll, boolean needHeader) {
9386 if (needHeader) {
9387 pw.println(" Activity stack:");
9388 }
9389 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9390 pw.println(" ");
9391 pw.println(" Running activities (most recent first):");
9392 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9393 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009394 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009395 pw.println(" Activities waiting for another to become visible:");
9396 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9397 }
9398 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009399 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009400 pw.println(" Activities waiting to stop:");
9401 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9402 }
9403 if (mFinishingActivities.size() > 0) {
9404 pw.println(" ");
9405 pw.println(" Activities waiting to finish:");
9406 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009408
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009409 pw.println(" ");
9410 pw.println(" mPausingActivity: " + mPausingActivity);
9411 pw.println(" mResumedActivity: " + mResumedActivity);
9412 pw.println(" mFocusedActivity: " + mFocusedActivity);
9413 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009414
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009415 if (dumpAll && mRecentTasks.size() > 0) {
9416 pw.println(" ");
9417 pw.println("Recent tasks in Current Activity Manager State:");
9418
9419 final int N = mRecentTasks.size();
9420 for (int i=0; i<N; i++) {
9421 TaskRecord tr = mRecentTasks.get(i);
9422 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9423 pw.println(tr);
9424 mRecentTasks.get(i).dump(pw, " ");
9425 }
9426 }
9427
9428 pw.println(" ");
9429 pw.println(" mCurTask: " + mCurTask);
9430
9431 return true;
9432 }
9433
9434 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9435 int opti, boolean dumpAll) {
9436 boolean needSep = false;
9437 int numPers = 0;
9438
9439 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009440 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9441 final int NA = procs.size();
9442 for (int ia=0; ia<NA; ia++) {
9443 if (!needSep) {
9444 pw.println(" All known processes:");
9445 needSep = true;
9446 }
9447 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009448 pw.print(r.persistent ? " *PERS*" : " *APP*");
9449 pw.print(" UID "); pw.print(procs.keyAt(ia));
9450 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009451 r.dump(pw, " ");
9452 if (r.persistent) {
9453 numPers++;
9454 }
9455 }
9456 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009457 }
9458
9459 if (mLruProcesses.size() > 0) {
9460 if (needSep) pw.println(" ");
9461 needSep = true;
9462 pw.println(" Running processes (most recent first):");
9463 dumpProcessList(pw, this, mLruProcesses, " ",
9464 "App ", "PERS", true);
9465 needSep = true;
9466 }
9467
9468 synchronized (mPidsSelfLocked) {
9469 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009470 if (needSep) pw.println(" ");
9471 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009472 pw.println(" PID mappings:");
9473 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9474 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9475 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009476 }
9477 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009478 }
9479
9480 if (mForegroundProcesses.size() > 0) {
9481 if (needSep) pw.println(" ");
9482 needSep = true;
9483 pw.println(" Foreground Processes:");
9484 for (int i=0; i<mForegroundProcesses.size(); i++) {
9485 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9486 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009487 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009488 }
9489
9490 if (mPersistentStartingProcesses.size() > 0) {
9491 if (needSep) pw.println(" ");
9492 needSep = true;
9493 pw.println(" Persisent processes that are starting:");
9494 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9495 "Starting Norm", "Restarting PERS", false);
9496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009497
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009498 if (mStartingProcesses.size() > 0) {
9499 if (needSep) pw.println(" ");
9500 needSep = true;
9501 pw.println(" Processes that are starting:");
9502 dumpProcessList(pw, this, mStartingProcesses, " ",
9503 "Starting Norm", "Starting PERS", false);
9504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009505
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009506 if (mRemovedProcesses.size() > 0) {
9507 if (needSep) pw.println(" ");
9508 needSep = true;
9509 pw.println(" Processes that are being removed:");
9510 dumpProcessList(pw, this, mRemovedProcesses, " ",
9511 "Removed Norm", "Removed PERS", false);
9512 }
9513
9514 if (mProcessesOnHold.size() > 0) {
9515 if (needSep) pw.println(" ");
9516 needSep = true;
9517 pw.println(" Processes that are on old until the system is ready:");
9518 dumpProcessList(pw, this, mProcessesOnHold, " ",
9519 "OnHold Norm", "OnHold PERS", false);
9520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009521
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009522 if (mProcessesToGc.size() > 0) {
9523 if (needSep) pw.println(" ");
9524 needSep = true;
9525 pw.println(" Processes that are waiting to GC:");
9526 long now = SystemClock.uptimeMillis();
9527 for (int i=0; i<mProcessesToGc.size(); i++) {
9528 ProcessRecord proc = mProcessesToGc.get(i);
9529 pw.print(" Process "); pw.println(proc);
9530 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9531 pw.print(", last gced=");
9532 pw.print(now-proc.lastRequestedGc);
9533 pw.print(" ms ago, last lowMem=");
9534 pw.print(now-proc.lastLowMemory);
9535 pw.println(" ms ago");
9536
9537 }
9538 }
9539
9540 if (mProcessCrashTimes.getMap().size() > 0) {
9541 if (needSep) pw.println(" ");
9542 needSep = true;
9543 pw.println(" Time since processes crashed:");
9544 long now = SystemClock.uptimeMillis();
9545 for (Map.Entry<String, SparseArray<Long>> procs
9546 : mProcessCrashTimes.getMap().entrySet()) {
9547 SparseArray<Long> uids = procs.getValue();
9548 final int N = uids.size();
9549 for (int i=0; i<N; i++) {
9550 pw.print(" Process "); pw.print(procs.getKey());
9551 pw.print(" uid "); pw.print(uids.keyAt(i));
9552 pw.print(": last crashed ");
9553 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009554 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009555 }
9556 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009558
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009559 if (mBadProcesses.getMap().size() > 0) {
9560 if (needSep) pw.println(" ");
9561 needSep = true;
9562 pw.println(" Bad processes:");
9563 for (Map.Entry<String, SparseArray<Long>> procs
9564 : mBadProcesses.getMap().entrySet()) {
9565 SparseArray<Long> uids = procs.getValue();
9566 final int N = uids.size();
9567 for (int i=0; i<N; i++) {
9568 pw.print(" Bad process "); pw.print(procs.getKey());
9569 pw.print(" uid "); pw.print(uids.keyAt(i));
9570 pw.print(": crashed at time ");
9571 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572 }
9573 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009575
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009576 pw.println(" ");
9577 pw.println(" mHomeProcess: " + mHomeProcess);
9578 pw.println(" mConfiguration: " + mConfiguration);
9579 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9580 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9581 || mOrigWaitForDebugger) {
9582 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9583 + " mDebugTransient=" + mDebugTransient
9584 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9585 }
9586 if (mAlwaysFinishActivities || mController != null) {
9587 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9588 + " mController=" + mController);
9589 }
9590 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009591 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009592 pw.println(" mStartRunning=" + mStartRunning
9593 + " mSystemReady=" + mSystemReady
9594 + " mBooting=" + mBooting
9595 + " mBooted=" + mBooted
9596 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009597 pw.println(" mGoingToSleep=" + mGoingToSleep);
9598 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009599 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009600
9601 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009602 }
9603
9604 /**
9605 * There are three ways to call this:
9606 * - no service specified: dump all the services
9607 * - a flattened component name that matched an existing service was specified as the
9608 * first arg: dump that one service
9609 * - the first arg isn't the flattened component name of an existing service:
9610 * dump all services whose component contains the first arg as a substring
9611 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009612 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9613 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009614 String[] newArgs;
9615 String componentNameString;
9616 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009617 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009618 componentNameString = null;
9619 newArgs = EMPTY_STRING_ARRAY;
9620 r = null;
9621 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009622 componentNameString = args[opti];
9623 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009624 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9625 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009626 newArgs = new String[args.length - opti];
9627 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009628 }
9629
9630 if (r != null) {
9631 dumpService(fd, pw, r, newArgs);
9632 } else {
9633 for (ServiceRecord r1 : mServices.values()) {
9634 if (componentNameString == null
9635 || r1.name.flattenToString().contains(componentNameString)) {
9636 dumpService(fd, pw, r1, newArgs);
9637 }
9638 }
9639 }
9640 }
9641
9642 /**
9643 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9644 * there is a thread associated with the service.
9645 */
9646 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9647 pw.println(" Service " + r.name.flattenToString());
9648 if (r.app != null && r.app.thread != null) {
9649 try {
9650 // flush anything that is already in the PrintWriter since the thread is going
9651 // to write to the file descriptor directly
9652 pw.flush();
9653 r.app.thread.dumpService(fd, r, args);
9654 pw.print("\n");
9655 } catch (RemoteException e) {
9656 pw.println("got a RemoteException while dumping the service");
9657 }
9658 }
9659 }
9660
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009661 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9662 int opti, boolean dumpAll) {
9663 boolean needSep = false;
9664
9665 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009666 if (mRegisteredReceivers.size() > 0) {
9667 pw.println(" ");
9668 pw.println(" Registered Receivers:");
9669 Iterator it = mRegisteredReceivers.values().iterator();
9670 while (it.hasNext()) {
9671 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009672 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009673 r.dump(pw, " ");
9674 }
9675 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009677 pw.println(" ");
9678 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009679 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009680 needSep = true;
9681 }
9682
9683 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9684 || mPendingBroadcast != null) {
9685 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009686 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009687 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009688 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009689 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9690 pw.println(" Broadcast #" + i + ":");
9691 mParallelBroadcasts.get(i).dump(pw, " ");
9692 }
9693 if (mOrderedBroadcasts.size() > 0) {
9694 pw.println(" ");
9695 pw.println(" Active serialized broadcasts:");
9696 }
9697 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9698 pw.println(" Serialized Broadcast #" + i + ":");
9699 mOrderedBroadcasts.get(i).dump(pw, " ");
9700 }
9701 pw.println(" ");
9702 pw.println(" Pending broadcast:");
9703 if (mPendingBroadcast != null) {
9704 mPendingBroadcast.dump(pw, " ");
9705 } else {
9706 pw.println(" (null)");
9707 }
9708 needSep = true;
9709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009710
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009711 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009712 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009713 pw.println(" Historical broadcasts:");
9714 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9715 BroadcastRecord r = mBroadcastHistory[i];
9716 if (r == null) {
9717 break;
9718 }
9719 pw.println(" Historical Broadcast #" + i + ":");
9720 r.dump(pw, " ");
9721 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009722 needSep = true;
9723 }
9724
9725 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009726 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009727 pw.println(" Sticky broadcasts:");
9728 StringBuilder sb = new StringBuilder(128);
9729 for (Map.Entry<String, ArrayList<Intent>> ent
9730 : mStickyBroadcasts.entrySet()) {
9731 pw.print(" * Sticky action "); pw.print(ent.getKey());
9732 pw.println(":");
9733 ArrayList<Intent> intents = ent.getValue();
9734 final int N = intents.size();
9735 for (int i=0; i<N; i++) {
9736 sb.setLength(0);
9737 sb.append(" Intent: ");
9738 intents.get(i).toShortString(sb, true, false);
9739 pw.println(sb.toString());
9740 Bundle bundle = intents.get(i).getExtras();
9741 if (bundle != null) {
9742 pw.print(" ");
9743 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009744 }
9745 }
9746 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009747 needSep = true;
9748 }
9749
9750 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009751 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009752 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009753 pw.println(" mHandler:");
9754 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009755 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009756 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009757
9758 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759 }
9760
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009761 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9762 int opti, boolean dumpAll) {
9763 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009764
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009765 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009766 if (mServices.size() > 0) {
9767 pw.println(" Active services:");
9768 Iterator<ServiceRecord> it = mServices.values().iterator();
9769 while (it.hasNext()) {
9770 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009771 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009772 r.dump(pw, " ");
9773 }
9774 needSep = true;
9775 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009777
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009778 if (mPendingServices.size() > 0) {
9779 if (needSep) pw.println(" ");
9780 pw.println(" Pending services:");
9781 for (int i=0; i<mPendingServices.size(); i++) {
9782 ServiceRecord r = mPendingServices.get(i);
9783 pw.print(" * Pending "); pw.println(r);
9784 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009785 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009786 needSep = true;
9787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009789 if (mRestartingServices.size() > 0) {
9790 if (needSep) pw.println(" ");
9791 pw.println(" Restarting services:");
9792 for (int i=0; i<mRestartingServices.size(); i++) {
9793 ServiceRecord r = mRestartingServices.get(i);
9794 pw.print(" * Restarting "); pw.println(r);
9795 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009796 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009797 needSep = true;
9798 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009799
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009800 if (mStoppingServices.size() > 0) {
9801 if (needSep) pw.println(" ");
9802 pw.println(" Stopping services:");
9803 for (int i=0; i<mStoppingServices.size(); i++) {
9804 ServiceRecord r = mStoppingServices.get(i);
9805 pw.print(" * Stopping "); pw.println(r);
9806 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009807 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009808 needSep = true;
9809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009810
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009811 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009812 if (mServiceConnections.size() > 0) {
9813 if (needSep) pw.println(" ");
9814 pw.println(" Connection bindings to services:");
9815 Iterator<ConnectionRecord> it
9816 = mServiceConnections.values().iterator();
9817 while (it.hasNext()) {
9818 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009819 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009820 r.dump(pw, " ");
9821 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009822 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009823 }
9824 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009825
9826 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009827 }
9828
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009829 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9830 int opti, boolean dumpAll) {
9831 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009833 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009834 if (mProvidersByClass.size() > 0) {
9835 if (needSep) pw.println(" ");
9836 pw.println(" Published content providers (by class):");
9837 Iterator it = mProvidersByClass.entrySet().iterator();
9838 while (it.hasNext()) {
9839 Map.Entry e = (Map.Entry)it.next();
9840 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009841 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009842 r.dump(pw, " ");
9843 }
9844 needSep = true;
9845 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009846
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009847 if (mProvidersByName.size() > 0) {
9848 pw.println(" ");
9849 pw.println(" Authority to provider mappings:");
9850 Iterator it = mProvidersByName.entrySet().iterator();
9851 while (it.hasNext()) {
9852 Map.Entry e = (Map.Entry)it.next();
9853 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9854 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9855 pw.println(r);
9856 }
9857 needSep = true;
9858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009859 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009860
9861 if (mLaunchingProviders.size() > 0) {
9862 if (needSep) pw.println(" ");
9863 pw.println(" Launching content providers:");
9864 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9865 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9866 pw.println(mLaunchingProviders.get(i));
9867 }
9868 needSep = true;
9869 }
9870
9871 if (mGrantedUriPermissions.size() > 0) {
9872 pw.println();
9873 pw.println("Granted Uri Permissions:");
9874 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9875 int uid = mGrantedUriPermissions.keyAt(i);
9876 HashMap<Uri, UriPermission> perms
9877 = mGrantedUriPermissions.valueAt(i);
9878 pw.print(" * UID "); pw.print(uid);
9879 pw.println(" holds:");
9880 for (UriPermission perm : perms.values()) {
9881 pw.print(" "); pw.println(perm);
9882 perm.dump(pw, " ");
9883 }
9884 }
9885 needSep = true;
9886 }
9887
9888 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009889 }
9890
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009891 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9892 int opti, boolean dumpAll) {
9893 boolean needSep = false;
9894
9895 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009896 if (this.mIntentSenderRecords.size() > 0) {
9897 Iterator<WeakReference<PendingIntentRecord>> it
9898 = mIntentSenderRecords.values().iterator();
9899 while (it.hasNext()) {
9900 WeakReference<PendingIntentRecord> ref = it.next();
9901 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009902 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009904 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 rec.dump(pw, " ");
9906 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009907 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009908 }
9909 }
9910 }
9911 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009912
9913 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009914 }
9915
9916 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009917 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009918 TaskRecord lastTask = null;
9919 for (int i=list.size()-1; i>=0; i--) {
9920 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009921 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 if (lastTask != r.task) {
9923 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009924 pw.print(prefix);
9925 pw.print(full ? "* " : " ");
9926 pw.println(lastTask);
9927 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009928 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009930 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009931 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9932 pw.print(" #"); pw.print(i); pw.print(": ");
9933 pw.println(r);
9934 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009935 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009937 }
9938 }
9939
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009940 private static String buildOomTag(String prefix, String space, int val, int base) {
9941 if (val == base) {
9942 if (space == null) return prefix;
9943 return prefix + " ";
9944 }
9945 return prefix + "+" + Integer.toString(val-base);
9946 }
9947
9948 private static final int dumpProcessList(PrintWriter pw,
9949 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009950 String prefix, String normalLabel, String persistentLabel,
9951 boolean inclOomAdj) {
9952 int numPers = 0;
9953 for (int i=list.size()-1; i>=0; i--) {
9954 ProcessRecord r = (ProcessRecord)list.get(i);
9955 if (false) {
9956 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
9957 + " #" + i + ":");
9958 r.dump(pw, prefix + " ");
9959 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009960 String oomAdj;
9961 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009962 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009963 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009964 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
9965 } else if (r.setAdj >= HOME_APP_ADJ) {
9966 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
9967 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
9968 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
9969 } else if (r.setAdj >= BACKUP_APP_ADJ) {
9970 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
9971 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
9972 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
9973 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
9974 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009975 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009976 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009977 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009978 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009979 } else {
9980 oomAdj = Integer.toString(r.setAdj);
9981 }
9982 String schedGroup;
9983 switch (r.setSchedGroup) {
9984 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9985 schedGroup = "B";
9986 break;
9987 case Process.THREAD_GROUP_DEFAULT:
9988 schedGroup = "F";
9989 break;
9990 default:
9991 schedGroup = Integer.toString(r.setSchedGroup);
9992 break;
9993 }
9994 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009995 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009996 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009997 if (r.adjSource != null || r.adjTarget != null) {
9998 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009999 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 } else {
10002 pw.println(String.format("%s%s #%2d: %s",
10003 prefix, (r.persistent ? persistentLabel : normalLabel),
10004 i, r.toString()));
10005 }
10006 if (r.persistent) {
10007 numPers++;
10008 }
10009 }
10010 return numPers;
10011 }
10012
10013 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
10014 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010015 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010016 long uptime = SystemClock.uptimeMillis();
10017 long realtime = SystemClock.elapsedRealtime();
10018
10019 if (isCheckinRequest) {
10020 // short checkin version
10021 pw.println(uptime + "," + realtime);
10022 pw.flush();
10023 } else {
10024 pw.println("Applications Memory Usage (kB):");
10025 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10026 }
10027 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10028 ProcessRecord r = (ProcessRecord)list.get(i);
10029 if (r.thread != null) {
10030 if (!isCheckinRequest) {
10031 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10032 pw.flush();
10033 }
10034 try {
10035 r.thread.asBinder().dump(fd, args);
10036 } catch (RemoteException e) {
10037 if (!isCheckinRequest) {
10038 pw.println("Got RemoteException!");
10039 pw.flush();
10040 }
10041 }
10042 }
10043 }
10044 }
10045
10046 /**
10047 * Searches array of arguments for the specified string
10048 * @param args array of argument strings
10049 * @param value value to search for
10050 * @return true if the value is contained in the array
10051 */
10052 private static boolean scanArgs(String[] args, String value) {
10053 if (args != null) {
10054 for (String arg : args) {
10055 if (value.equals(arg)) {
10056 return true;
10057 }
10058 }
10059 }
10060 return false;
10061 }
10062
Dianne Hackborn75b03852009-06-12 15:43:26 -070010063 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064 int count = mHistory.size();
10065
10066 // convert the token to an entry in the history.
10067 HistoryRecord r = null;
10068 int index = -1;
10069 for (int i=count-1; i>=0; i--) {
10070 Object o = mHistory.get(i);
10071 if (o == token) {
10072 r = (HistoryRecord)o;
10073 index = i;
10074 break;
10075 }
10076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010077
10078 return index;
10079 }
10080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010081 private final void killServicesLocked(ProcessRecord app,
10082 boolean allowRestart) {
10083 // Report disconnected services.
10084 if (false) {
10085 // XXX we are letting the client link to the service for
10086 // death notifications.
10087 if (app.services.size() > 0) {
10088 Iterator it = app.services.iterator();
10089 while (it.hasNext()) {
10090 ServiceRecord r = (ServiceRecord)it.next();
10091 if (r.connections.size() > 0) {
10092 Iterator<ConnectionRecord> jt
10093 = r.connections.values().iterator();
10094 while (jt.hasNext()) {
10095 ConnectionRecord c = jt.next();
10096 if (c.binding.client != app) {
10097 try {
10098 //c.conn.connected(r.className, null);
10099 } catch (Exception e) {
10100 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010101 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010102 + r.shortName
10103 + " from app " + app.processName, e);
10104 }
10105 }
10106 }
10107 }
10108 }
10109 }
10110 }
10111
10112 // Clean up any connections this application has to other services.
10113 if (app.connections.size() > 0) {
10114 Iterator<ConnectionRecord> it = app.connections.iterator();
10115 while (it.hasNext()) {
10116 ConnectionRecord r = it.next();
10117 removeConnectionLocked(r, app, null);
10118 }
10119 }
10120 app.connections.clear();
10121
10122 if (app.services.size() != 0) {
10123 // Any services running in the application need to be placed
10124 // back in the pending list.
10125 Iterator it = app.services.iterator();
10126 while (it.hasNext()) {
10127 ServiceRecord sr = (ServiceRecord)it.next();
10128 synchronized (sr.stats.getBatteryStats()) {
10129 sr.stats.stopLaunchedLocked();
10130 }
10131 sr.app = null;
10132 sr.executeNesting = 0;
10133 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010134
10135 boolean hasClients = sr.bindings.size() > 0;
10136 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010137 Iterator<IntentBindRecord> bindings
10138 = sr.bindings.values().iterator();
10139 while (bindings.hasNext()) {
10140 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010141 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010142 + ": shouldUnbind=" + b.hasBound);
10143 b.binder = null;
10144 b.requested = b.received = b.hasBound = false;
10145 }
10146 }
10147
10148 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010149 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010150 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010151 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010152 sr.crashCount, sr.shortName, app.pid);
10153 bringDownServiceLocked(sr, true);
10154 } else if (!allowRestart) {
10155 bringDownServiceLocked(sr, true);
10156 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010157 boolean canceled = scheduleServiceRestartLocked(sr, true);
10158
10159 // Should the service remain running? Note that in the
10160 // extreme case of so many attempts to deliver a command
10161 // that it failed, that we also will stop it here.
10162 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10163 if (sr.pendingStarts.size() == 0) {
10164 sr.startRequested = false;
10165 if (!hasClients) {
10166 // Whoops, no reason to restart!
10167 bringDownServiceLocked(sr, true);
10168 }
10169 }
10170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010171 }
10172 }
10173
10174 if (!allowRestart) {
10175 app.services.clear();
10176 }
10177 }
10178
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010179 // Make sure we have no more records on the stopping list.
10180 int i = mStoppingServices.size();
10181 while (i > 0) {
10182 i--;
10183 ServiceRecord sr = mStoppingServices.get(i);
10184 if (sr.app == app) {
10185 mStoppingServices.remove(i);
10186 }
10187 }
10188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010189 app.executingServices.clear();
10190 }
10191
10192 private final void removeDyingProviderLocked(ProcessRecord proc,
10193 ContentProviderRecord cpr) {
10194 synchronized (cpr) {
10195 cpr.launchingApp = null;
10196 cpr.notifyAll();
10197 }
10198
10199 mProvidersByClass.remove(cpr.info.name);
10200 String names[] = cpr.info.authority.split(";");
10201 for (int j = 0; j < names.length; j++) {
10202 mProvidersByName.remove(names[j]);
10203 }
10204
10205 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10206 while (cit.hasNext()) {
10207 ProcessRecord capp = cit.next();
10208 if (!capp.persistent && capp.thread != null
10209 && capp.pid != 0
10210 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010211 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010212 + " (pid " + capp.pid
10213 + ") because provider " + cpr.info.name
10214 + " is in dying process " + proc.processName);
10215 Process.killProcess(capp.pid);
10216 }
10217 }
10218
10219 mLaunchingProviders.remove(cpr);
10220 }
10221
10222 /**
10223 * Main code for cleaning up a process when it has gone away. This is
10224 * called both as a result of the process dying, or directly when stopping
10225 * a process when running in single process mode.
10226 */
10227 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10228 boolean restarting, int index) {
10229 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010230 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010231 }
10232
Dianne Hackborn36124872009-10-08 16:22:03 -070010233 mProcessesToGc.remove(app);
10234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010235 // Dismiss any open dialogs.
10236 if (app.crashDialog != null) {
10237 app.crashDialog.dismiss();
10238 app.crashDialog = null;
10239 }
10240 if (app.anrDialog != null) {
10241 app.anrDialog.dismiss();
10242 app.anrDialog = null;
10243 }
10244 if (app.waitDialog != null) {
10245 app.waitDialog.dismiss();
10246 app.waitDialog = null;
10247 }
10248
10249 app.crashing = false;
10250 app.notResponding = false;
10251
10252 app.resetPackageList();
10253 app.thread = null;
10254 app.forcingToForeground = null;
10255 app.foregroundServices = false;
10256
10257 killServicesLocked(app, true);
10258
10259 boolean restart = false;
10260
10261 int NL = mLaunchingProviders.size();
10262
10263 // Remove published content providers.
10264 if (!app.pubProviders.isEmpty()) {
10265 Iterator it = app.pubProviders.values().iterator();
10266 while (it.hasNext()) {
10267 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10268 cpr.provider = null;
10269 cpr.app = null;
10270
10271 // See if someone is waiting for this provider... in which
10272 // case we don't remove it, but just let it restart.
10273 int i = 0;
10274 if (!app.bad) {
10275 for (; i<NL; i++) {
10276 if (mLaunchingProviders.get(i) == cpr) {
10277 restart = true;
10278 break;
10279 }
10280 }
10281 } else {
10282 i = NL;
10283 }
10284
10285 if (i >= NL) {
10286 removeDyingProviderLocked(app, cpr);
10287 NL = mLaunchingProviders.size();
10288 }
10289 }
10290 app.pubProviders.clear();
10291 }
10292
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010293 // Take care of any launching providers waiting for this process.
10294 if (checkAppInLaunchingProvidersLocked(app, false)) {
10295 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010296 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010298 // Unregister from connected content providers.
10299 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010300 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 while (it.hasNext()) {
10302 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10303 cpr.clients.remove(app);
10304 }
10305 app.conProviders.clear();
10306 }
10307
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010308 // At this point there may be remaining entries in mLaunchingProviders
10309 // where we were the only one waiting, so they are no longer of use.
10310 // Look for these and clean up if found.
10311 // XXX Commented out for now. Trying to figure out a way to reproduce
10312 // the actual situation to identify what is actually going on.
10313 if (false) {
10314 for (int i=0; i<NL; i++) {
10315 ContentProviderRecord cpr = (ContentProviderRecord)
10316 mLaunchingProviders.get(i);
10317 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10318 synchronized (cpr) {
10319 cpr.launchingApp = null;
10320 cpr.notifyAll();
10321 }
10322 }
10323 }
10324 }
10325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010326 skipCurrentReceiverLocked(app);
10327
10328 // Unregister any receivers.
10329 if (app.receivers.size() > 0) {
10330 Iterator<ReceiverList> it = app.receivers.iterator();
10331 while (it.hasNext()) {
10332 removeReceiverLocked(it.next());
10333 }
10334 app.receivers.clear();
10335 }
10336
Christopher Tate181fafa2009-05-14 11:12:14 -070010337 // If the app is undergoing backup, tell the backup manager about it
10338 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010339 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010340 try {
10341 IBackupManager bm = IBackupManager.Stub.asInterface(
10342 ServiceManager.getService(Context.BACKUP_SERVICE));
10343 bm.agentDisconnected(app.info.packageName);
10344 } catch (RemoteException e) {
10345 // can't happen; backup manager is local
10346 }
10347 }
10348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010349 // If the caller is restarting this app, then leave it in its
10350 // current lists and let the caller take care of it.
10351 if (restarting) {
10352 return;
10353 }
10354
10355 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010356 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 "Removing non-persistent process during cleanup: " + app);
10358 mProcessNames.remove(app.processName, app.info.uid);
10359 } else if (!app.removed) {
10360 // This app is persistent, so we need to keep its record around.
10361 // If it is not already on the pending app list, add it there
10362 // and start a new process for it.
10363 app.thread = null;
10364 app.forcingToForeground = null;
10365 app.foregroundServices = false;
10366 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10367 mPersistentStartingProcesses.add(app);
10368 restart = true;
10369 }
10370 }
10371 mProcessesOnHold.remove(app);
10372
The Android Open Source Project4df24232009-03-05 14:34:35 -080010373 if (app == mHomeProcess) {
10374 mHomeProcess = null;
10375 }
10376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010377 if (restart) {
10378 // We have components that still need to be running in the
10379 // process, so re-launch it.
10380 mProcessNames.put(app.processName, app.info.uid, app);
10381 startProcessLocked(app, "restart", app.processName);
10382 } else if (app.pid > 0 && app.pid != MY_PID) {
10383 // Goodbye!
10384 synchronized (mPidsSelfLocked) {
10385 mPidsSelfLocked.remove(app.pid);
10386 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10387 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010388 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010389 }
10390 }
10391
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010392 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10393 // Look through the content providers we are waiting to have launched,
10394 // and if any run in this process then either schedule a restart of
10395 // the process or kill the client waiting for it if this process has
10396 // gone bad.
10397 int NL = mLaunchingProviders.size();
10398 boolean restart = false;
10399 for (int i=0; i<NL; i++) {
10400 ContentProviderRecord cpr = (ContentProviderRecord)
10401 mLaunchingProviders.get(i);
10402 if (cpr.launchingApp == app) {
10403 if (!alwaysBad && !app.bad) {
10404 restart = true;
10405 } else {
10406 removeDyingProviderLocked(app, cpr);
10407 NL = mLaunchingProviders.size();
10408 }
10409 }
10410 }
10411 return restart;
10412 }
10413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414 // =========================================================
10415 // SERVICES
10416 // =========================================================
10417
10418 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10419 ActivityManager.RunningServiceInfo info =
10420 new ActivityManager.RunningServiceInfo();
10421 info.service = r.name;
10422 if (r.app != null) {
10423 info.pid = r.app.pid;
10424 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010425 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010426 info.process = r.processName;
10427 info.foreground = r.isForeground;
10428 info.activeSince = r.createTime;
10429 info.started = r.startRequested;
10430 info.clientCount = r.connections.size();
10431 info.crashCount = r.crashCount;
10432 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010433 if (r.isForeground) {
10434 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10435 }
10436 if (r.startRequested) {
10437 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10438 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010439 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010440 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10441 }
10442 if (r.app != null && r.app.persistent) {
10443 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10444 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010445 for (ConnectionRecord conn : r.connections.values()) {
10446 if (conn.clientLabel != 0) {
10447 info.clientPackage = conn.binding.client.info.packageName;
10448 info.clientLabel = conn.clientLabel;
10449 break;
10450 }
10451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010452 return info;
10453 }
10454
10455 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10456 int flags) {
10457 synchronized (this) {
10458 ArrayList<ActivityManager.RunningServiceInfo> res
10459 = new ArrayList<ActivityManager.RunningServiceInfo>();
10460
10461 if (mServices.size() > 0) {
10462 Iterator<ServiceRecord> it = mServices.values().iterator();
10463 while (it.hasNext() && res.size() < maxNum) {
10464 res.add(makeRunningServiceInfoLocked(it.next()));
10465 }
10466 }
10467
10468 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10469 ServiceRecord r = mRestartingServices.get(i);
10470 ActivityManager.RunningServiceInfo info =
10471 makeRunningServiceInfoLocked(r);
10472 info.restarting = r.nextRestartTime;
10473 res.add(info);
10474 }
10475
10476 return res;
10477 }
10478 }
10479
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010480 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10481 synchronized (this) {
10482 ServiceRecord r = mServices.get(name);
10483 if (r != null) {
10484 for (ConnectionRecord conn : r.connections.values()) {
10485 if (conn.clientIntent != null) {
10486 return conn.clientIntent;
10487 }
10488 }
10489 }
10490 }
10491 return null;
10492 }
10493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010494 private final ServiceRecord findServiceLocked(ComponentName name,
10495 IBinder token) {
10496 ServiceRecord r = mServices.get(name);
10497 return r == token ? r : null;
10498 }
10499
10500 private final class ServiceLookupResult {
10501 final ServiceRecord record;
10502 final String permission;
10503
10504 ServiceLookupResult(ServiceRecord _record, String _permission) {
10505 record = _record;
10506 permission = _permission;
10507 }
10508 };
10509
10510 private ServiceLookupResult findServiceLocked(Intent service,
10511 String resolvedType) {
10512 ServiceRecord r = null;
10513 if (service.getComponent() != null) {
10514 r = mServices.get(service.getComponent());
10515 }
10516 if (r == null) {
10517 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10518 r = mServicesByIntent.get(filter);
10519 }
10520
10521 if (r == null) {
10522 try {
10523 ResolveInfo rInfo =
10524 ActivityThread.getPackageManager().resolveService(
10525 service, resolvedType, 0);
10526 ServiceInfo sInfo =
10527 rInfo != null ? rInfo.serviceInfo : null;
10528 if (sInfo == null) {
10529 return null;
10530 }
10531
10532 ComponentName name = new ComponentName(
10533 sInfo.applicationInfo.packageName, sInfo.name);
10534 r = mServices.get(name);
10535 } catch (RemoteException ex) {
10536 // pm is in same process, this will never happen.
10537 }
10538 }
10539 if (r != null) {
10540 int callingPid = Binder.getCallingPid();
10541 int callingUid = Binder.getCallingUid();
10542 if (checkComponentPermission(r.permission,
10543 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10544 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010545 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 + " from pid=" + callingPid
10547 + ", uid=" + callingUid
10548 + " requires " + r.permission);
10549 return new ServiceLookupResult(null, r.permission);
10550 }
10551 return new ServiceLookupResult(r, null);
10552 }
10553 return null;
10554 }
10555
10556 private class ServiceRestarter implements Runnable {
10557 private ServiceRecord mService;
10558
10559 void setService(ServiceRecord service) {
10560 mService = service;
10561 }
10562
10563 public void run() {
10564 synchronized(ActivityManagerService.this) {
10565 performServiceRestartLocked(mService);
10566 }
10567 }
10568 }
10569
10570 private ServiceLookupResult retrieveServiceLocked(Intent service,
10571 String resolvedType, int callingPid, int callingUid) {
10572 ServiceRecord r = null;
10573 if (service.getComponent() != null) {
10574 r = mServices.get(service.getComponent());
10575 }
10576 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10577 r = mServicesByIntent.get(filter);
10578 if (r == null) {
10579 try {
10580 ResolveInfo rInfo =
10581 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010582 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 ServiceInfo sInfo =
10584 rInfo != null ? rInfo.serviceInfo : null;
10585 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010586 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010587 ": not found");
10588 return null;
10589 }
10590
10591 ComponentName name = new ComponentName(
10592 sInfo.applicationInfo.packageName, sInfo.name);
10593 r = mServices.get(name);
10594 if (r == null) {
10595 filter = new Intent.FilterComparison(service.cloneFilter());
10596 ServiceRestarter res = new ServiceRestarter();
10597 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10598 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10599 synchronized (stats) {
10600 ss = stats.getServiceStatsLocked(
10601 sInfo.applicationInfo.uid, sInfo.packageName,
10602 sInfo.name);
10603 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010604 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010605 res.setService(r);
10606 mServices.put(name, r);
10607 mServicesByIntent.put(filter, r);
10608
10609 // Make sure this component isn't in the pending list.
10610 int N = mPendingServices.size();
10611 for (int i=0; i<N; i++) {
10612 ServiceRecord pr = mPendingServices.get(i);
10613 if (pr.name.equals(name)) {
10614 mPendingServices.remove(i);
10615 i--;
10616 N--;
10617 }
10618 }
10619 }
10620 } catch (RemoteException ex) {
10621 // pm is in same process, this will never happen.
10622 }
10623 }
10624 if (r != null) {
10625 if (checkComponentPermission(r.permission,
10626 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10627 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010628 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010629 + " from pid=" + Binder.getCallingPid()
10630 + ", uid=" + Binder.getCallingUid()
10631 + " requires " + r.permission);
10632 return new ServiceLookupResult(null, r.permission);
10633 }
10634 return new ServiceLookupResult(r, null);
10635 }
10636 return null;
10637 }
10638
10639 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10640 long now = SystemClock.uptimeMillis();
10641 if (r.executeNesting == 0 && r.app != null) {
10642 if (r.app.executingServices.size() == 0) {
10643 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10644 msg.obj = r.app;
10645 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10646 }
10647 r.app.executingServices.add(r);
10648 }
10649 r.executeNesting++;
10650 r.executingStart = now;
10651 }
10652
10653 private final void sendServiceArgsLocked(ServiceRecord r,
10654 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010655 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010656 if (N == 0) {
10657 return;
10658 }
10659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010660 int i = 0;
10661 while (i < N) {
10662 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010663 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010664 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010665 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010666 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010667 // If somehow we got a dummy start at the front, then
10668 // just drop it here.
10669 i++;
10670 continue;
10671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010672 bumpServiceExecutingLocked(r);
10673 if (!oomAdjusted) {
10674 oomAdjusted = true;
10675 updateOomAdjLocked(r.app);
10676 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010677 int flags = 0;
10678 if (si.deliveryCount > 0) {
10679 flags |= Service.START_FLAG_RETRY;
10680 }
10681 if (si.doneExecutingCount > 0) {
10682 flags |= Service.START_FLAG_REDELIVERY;
10683 }
10684 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10685 si.deliveredTime = SystemClock.uptimeMillis();
10686 r.deliveredStarts.add(si);
10687 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010688 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010689 } catch (RemoteException e) {
10690 // Remote process gone... we'll let the normal cleanup take
10691 // care of this.
10692 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010693 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010694 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010695 break;
10696 }
10697 }
10698 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010699 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010700 } else {
10701 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010702 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010703 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010704 }
10705 }
10706 }
10707
10708 private final boolean requestServiceBindingLocked(ServiceRecord r,
10709 IntentBindRecord i, boolean rebind) {
10710 if (r.app == null || r.app.thread == null) {
10711 // If service is not currently running, can't yet bind.
10712 return false;
10713 }
10714 if ((!i.requested || rebind) && i.apps.size() > 0) {
10715 try {
10716 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010717 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010718 + ": shouldUnbind=" + i.hasBound);
10719 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10720 if (!rebind) {
10721 i.requested = true;
10722 }
10723 i.hasBound = true;
10724 i.doRebind = false;
10725 } catch (RemoteException e) {
10726 return false;
10727 }
10728 }
10729 return true;
10730 }
10731
10732 private final void requestServiceBindingsLocked(ServiceRecord r) {
10733 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10734 while (bindings.hasNext()) {
10735 IntentBindRecord i = bindings.next();
10736 if (!requestServiceBindingLocked(r, i, false)) {
10737 break;
10738 }
10739 }
10740 }
10741
10742 private final void realStartServiceLocked(ServiceRecord r,
10743 ProcessRecord app) throws RemoteException {
10744 if (app.thread == null) {
10745 throw new RemoteException();
10746 }
10747
10748 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010749 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010750
10751 app.services.add(r);
10752 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010753 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010754
10755 boolean created = false;
10756 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010757 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010758 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010759 mStringBuilder.setLength(0);
10760 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010761 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010762 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010763 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764 synchronized (r.stats.getBatteryStats()) {
10765 r.stats.startLaunchedLocked();
10766 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010767 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010768 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010769 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010770 created = true;
10771 } finally {
10772 if (!created) {
10773 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010774 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010775 }
10776 }
10777
10778 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010779
10780 // If the service is in the started state, and there are no
10781 // pending arguments, then fake up one so its onStartCommand() will
10782 // be called.
10783 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10784 r.lastStartId++;
10785 if (r.lastStartId < 1) {
10786 r.lastStartId = 1;
10787 }
10788 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10789 }
10790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010791 sendServiceArgsLocked(r, true);
10792 }
10793
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010794 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10795 boolean allowCancel) {
10796 boolean canceled = false;
10797
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010798 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010799 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010800 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010801
10802 // Any delivered but not yet finished starts should be put back
10803 // on the pending list.
10804 final int N = r.deliveredStarts.size();
10805 if (N > 0) {
10806 for (int i=N-1; i>=0; i--) {
10807 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10808 if (si.intent == null) {
10809 // We'll generate this again if needed.
10810 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10811 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10812 r.pendingStarts.add(0, si);
10813 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10814 dur *= 2;
10815 if (minDuration < dur) minDuration = dur;
10816 if (resetTime < dur) resetTime = dur;
10817 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010818 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010819 + r.name);
10820 canceled = true;
10821 }
10822 }
10823 r.deliveredStarts.clear();
10824 }
10825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010826 r.totalRestartCount++;
10827 if (r.restartDelay == 0) {
10828 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010829 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830 } else {
10831 // If it has been a "reasonably long time" since the service
10832 // was started, then reset our restart duration back to
10833 // the beginning, so we don't infinitely increase the duration
10834 // on a service that just occasionally gets killed (which is
10835 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010836 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010837 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010838 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010840 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010841 if (r.restartDelay < minDuration) {
10842 r.restartDelay = minDuration;
10843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010844 }
10845 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010846
10847 r.nextRestartTime = now + r.restartDelay;
10848
10849 // Make sure that we don't end up restarting a bunch of services
10850 // all at the same time.
10851 boolean repeat;
10852 do {
10853 repeat = false;
10854 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10855 ServiceRecord r2 = mRestartingServices.get(i);
10856 if (r2 != r && r.nextRestartTime
10857 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10858 && r.nextRestartTime
10859 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10860 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10861 r.restartDelay = r.nextRestartTime - now;
10862 repeat = true;
10863 break;
10864 }
10865 }
10866 } while (repeat);
10867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010868 if (!mRestartingServices.contains(r)) {
10869 mRestartingServices.add(r);
10870 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010871
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010872 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010874 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010875 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010876 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010877 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010878 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010879 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010880 r.shortName, r.restartDelay);
10881
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010882 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010883 }
10884
10885 final void performServiceRestartLocked(ServiceRecord r) {
10886 if (!mRestartingServices.contains(r)) {
10887 return;
10888 }
10889 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10890 }
10891
10892 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10893 if (r.restartDelay == 0) {
10894 return false;
10895 }
10896 r.resetRestartCounter();
10897 mRestartingServices.remove(r);
10898 mHandler.removeCallbacks(r.restarter);
10899 return true;
10900 }
10901
10902 private final boolean bringUpServiceLocked(ServiceRecord r,
10903 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010904 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010905 //r.dump(" ");
10906
Dianne Hackborn36124872009-10-08 16:22:03 -070010907 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 sendServiceArgsLocked(r, false);
10909 return true;
10910 }
10911
10912 if (!whileRestarting && r.restartDelay > 0) {
10913 // If waiting for a restart, then do nothing.
10914 return true;
10915 }
10916
Joe Onorato8a9b2202010-02-26 18:56:32 -080010917 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010918 + " " + r.intent);
10919
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010920 // We are now bringing the service up, so no longer in the
10921 // restarting state.
10922 mRestartingServices.remove(r);
10923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010924 final String appName = r.processName;
10925 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10926 if (app != null && app.thread != null) {
10927 try {
10928 realStartServiceLocked(r, app);
10929 return true;
10930 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010931 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010932 }
10933
10934 // If a dead object exception was thrown -- fall through to
10935 // restart the application.
10936 }
10937
Dianne Hackborn36124872009-10-08 16:22:03 -070010938 // Not running -- get it started, and enqueue this service record
10939 // to be executed when the app comes up.
10940 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10941 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010942 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070010943 + r.appInfo.packageName + "/"
10944 + r.appInfo.uid + " for service "
10945 + r.intent.getIntent() + ": process is bad");
10946 bringDownServiceLocked(r, true);
10947 return false;
10948 }
10949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010950 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 mPendingServices.add(r);
10952 }
Dianne Hackborn36124872009-10-08 16:22:03 -070010953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 return true;
10955 }
10956
10957 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010958 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959 //r.dump(" ");
10960
10961 // Does it still need to run?
10962 if (!force && r.startRequested) {
10963 return;
10964 }
10965 if (r.connections.size() > 0) {
10966 if (!force) {
10967 // XXX should probably keep a count of the number of auto-create
10968 // connections directly in the service.
10969 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10970 while (it.hasNext()) {
10971 ConnectionRecord cr = it.next();
10972 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10973 return;
10974 }
10975 }
10976 }
10977
10978 // Report to all of the connections that the service is no longer
10979 // available.
10980 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10981 while (it.hasNext()) {
10982 ConnectionRecord c = it.next();
10983 try {
10984 // todo: shouldn't be a synchronous call!
10985 c.conn.connected(r.name, null);
10986 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010987 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010988 " to connection " + c.conn.asBinder() +
10989 " (in " + c.binding.client.processName + ")", e);
10990 }
10991 }
10992 }
10993
10994 // Tell the service that it has been unbound.
10995 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10996 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10997 while (it.hasNext()) {
10998 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010999 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011000 + ": hasBound=" + ibr.hasBound);
11001 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11002 try {
11003 bumpServiceExecutingLocked(r);
11004 updateOomAdjLocked(r.app);
11005 ibr.hasBound = false;
11006 r.app.thread.scheduleUnbindService(r,
11007 ibr.intent.getIntent());
11008 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011009 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011010 + r.shortName, e);
11011 serviceDoneExecutingLocked(r, true);
11012 }
11013 }
11014 }
11015 }
11016
Joe Onorato8a9b2202010-02-26 18:56:32 -080011017 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011019 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011020 System.identityHashCode(r), r.shortName,
11021 (r.app != null) ? r.app.pid : -1);
11022
11023 mServices.remove(r.name);
11024 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011025 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026 r.totalRestartCount = 0;
11027 unscheduleServiceRestartLocked(r);
11028
11029 // Also make sure it is not on the pending list.
11030 int N = mPendingServices.size();
11031 for (int i=0; i<N; i++) {
11032 if (mPendingServices.get(i) == r) {
11033 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011034 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011035 TAG, "Removed pending service: " + r.shortName);
11036 i--;
11037 N--;
11038 }
11039 }
11040
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011041 r.cancelNotification();
11042 r.isForeground = false;
11043 r.foregroundId = 0;
11044 r.foregroundNoti = null;
11045
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011046 // Clear start entries.
11047 r.deliveredStarts.clear();
11048 r.pendingStarts.clear();
11049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011050 if (r.app != null) {
11051 synchronized (r.stats.getBatteryStats()) {
11052 r.stats.stopLaunchedLocked();
11053 }
11054 r.app.services.remove(r);
11055 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011057 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011058 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011059 bumpServiceExecutingLocked(r);
11060 mStoppingServices.add(r);
11061 updateOomAdjLocked(r.app);
11062 r.app.thread.scheduleStopService(r);
11063 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011064 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 + r.shortName, e);
11066 serviceDoneExecutingLocked(r, true);
11067 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011068 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011069 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011070 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011071 TAG, "Removed service that has no process: " + r.shortName);
11072 }
11073 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011074 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011075 TAG, "Removed service that is not running: " + r.shortName);
11076 }
11077 }
11078
11079 ComponentName startServiceLocked(IApplicationThread caller,
11080 Intent service, String resolvedType,
11081 int callingPid, int callingUid) {
11082 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011083 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084 + " type=" + resolvedType + " args=" + service.getExtras());
11085
11086 if (caller != null) {
11087 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11088 if (callerApp == null) {
11089 throw new SecurityException(
11090 "Unable to find app for caller " + caller
11091 + " (pid=" + Binder.getCallingPid()
11092 + ") when starting service " + service);
11093 }
11094 }
11095
11096 ServiceLookupResult res =
11097 retrieveServiceLocked(service, resolvedType,
11098 callingPid, callingUid);
11099 if (res == null) {
11100 return null;
11101 }
11102 if (res.record == null) {
11103 return new ComponentName("!", res.permission != null
11104 ? res.permission : "private to package");
11105 }
11106 ServiceRecord r = res.record;
11107 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011108 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 + r.shortName);
11110 }
11111 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011112 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011113 r.lastStartId++;
11114 if (r.lastStartId < 1) {
11115 r.lastStartId = 1;
11116 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011117 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011118 r.lastActivity = SystemClock.uptimeMillis();
11119 synchronized (r.stats.getBatteryStats()) {
11120 r.stats.startRunningLocked();
11121 }
11122 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11123 return new ComponentName("!", "Service process is bad");
11124 }
11125 return r.name;
11126 }
11127 }
11128
11129 public ComponentName startService(IApplicationThread caller, Intent service,
11130 String resolvedType) {
11131 // Refuse possible leaked file descriptors
11132 if (service != null && service.hasFileDescriptors() == true) {
11133 throw new IllegalArgumentException("File descriptors passed in Intent");
11134 }
11135
11136 synchronized(this) {
11137 final int callingPid = Binder.getCallingPid();
11138 final int callingUid = Binder.getCallingUid();
11139 final long origId = Binder.clearCallingIdentity();
11140 ComponentName res = startServiceLocked(caller, service,
11141 resolvedType, callingPid, callingUid);
11142 Binder.restoreCallingIdentity(origId);
11143 return res;
11144 }
11145 }
11146
11147 ComponentName startServiceInPackage(int uid,
11148 Intent service, String resolvedType) {
11149 synchronized(this) {
11150 final long origId = Binder.clearCallingIdentity();
11151 ComponentName res = startServiceLocked(null, service,
11152 resolvedType, -1, uid);
11153 Binder.restoreCallingIdentity(origId);
11154 return res;
11155 }
11156 }
11157
11158 public int stopService(IApplicationThread caller, Intent service,
11159 String resolvedType) {
11160 // Refuse possible leaked file descriptors
11161 if (service != null && service.hasFileDescriptors() == true) {
11162 throw new IllegalArgumentException("File descriptors passed in Intent");
11163 }
11164
11165 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011166 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011167 + " type=" + resolvedType);
11168
11169 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11170 if (caller != null && callerApp == null) {
11171 throw new SecurityException(
11172 "Unable to find app for caller " + caller
11173 + " (pid=" + Binder.getCallingPid()
11174 + ") when stopping service " + service);
11175 }
11176
11177 // If this service is active, make sure it is stopped.
11178 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11179 if (r != null) {
11180 if (r.record != null) {
11181 synchronized (r.record.stats.getBatteryStats()) {
11182 r.record.stats.stopRunningLocked();
11183 }
11184 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011185 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186 final long origId = Binder.clearCallingIdentity();
11187 bringDownServiceLocked(r.record, false);
11188 Binder.restoreCallingIdentity(origId);
11189 return 1;
11190 }
11191 return -1;
11192 }
11193 }
11194
11195 return 0;
11196 }
11197
11198 public IBinder peekService(Intent service, String resolvedType) {
11199 // Refuse possible leaked file descriptors
11200 if (service != null && service.hasFileDescriptors() == true) {
11201 throw new IllegalArgumentException("File descriptors passed in Intent");
11202 }
11203
11204 IBinder ret = null;
11205
11206 synchronized(this) {
11207 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11208
11209 if (r != null) {
11210 // r.record is null if findServiceLocked() failed the caller permission check
11211 if (r.record == null) {
11212 throw new SecurityException(
11213 "Permission Denial: Accessing service " + r.record.name
11214 + " from pid=" + Binder.getCallingPid()
11215 + ", uid=" + Binder.getCallingUid()
11216 + " requires " + r.permission);
11217 }
11218 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11219 if (ib != null) {
11220 ret = ib.binder;
11221 }
11222 }
11223 }
11224
11225 return ret;
11226 }
11227
11228 public boolean stopServiceToken(ComponentName className, IBinder token,
11229 int startId) {
11230 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011231 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011232 + " " + token + " startId=" + startId);
11233 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011234 if (r != null) {
11235 if (startId >= 0) {
11236 // Asked to only stop if done with all work. Note that
11237 // to avoid leaks, we will take this as dropping all
11238 // start items up to and including this one.
11239 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11240 if (si != null) {
11241 while (r.deliveredStarts.size() > 0) {
11242 if (r.deliveredStarts.remove(0) == si) {
11243 break;
11244 }
11245 }
11246 }
11247
11248 if (r.lastStartId != startId) {
11249 return false;
11250 }
11251
11252 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011253 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011254 + " is last, but have " + r.deliveredStarts.size()
11255 + " remaining args");
11256 }
11257 }
11258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011259 synchronized (r.stats.getBatteryStats()) {
11260 r.stats.stopRunningLocked();
11261 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011262 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 }
11264 final long origId = Binder.clearCallingIdentity();
11265 bringDownServiceLocked(r, false);
11266 Binder.restoreCallingIdentity(origId);
11267 return true;
11268 }
11269 }
11270 return false;
11271 }
11272
11273 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011274 int id, Notification notification, boolean removeNotification) {
11275 final long origId = Binder.clearCallingIdentity();
11276 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011277 synchronized(this) {
11278 ServiceRecord r = findServiceLocked(className, token);
11279 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011280 if (id != 0) {
11281 if (notification == null) {
11282 throw new IllegalArgumentException("null notification");
11283 }
11284 if (r.foregroundId != id) {
11285 r.cancelNotification();
11286 r.foregroundId = id;
11287 }
11288 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11289 r.foregroundNoti = notification;
11290 r.isForeground = true;
11291 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011292 if (r.app != null) {
11293 updateServiceForegroundLocked(r.app, true);
11294 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011295 } else {
11296 if (r.isForeground) {
11297 r.isForeground = false;
11298 if (r.app != null) {
11299 updateServiceForegroundLocked(r.app, true);
11300 }
11301 }
11302 if (removeNotification) {
11303 r.cancelNotification();
11304 r.foregroundId = 0;
11305 r.foregroundNoti = null;
11306 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011307 }
11308 }
11309 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011310 } finally {
11311 Binder.restoreCallingIdentity(origId);
11312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 }
11314
11315 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11316 boolean anyForeground = false;
11317 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11318 if (sr.isForeground) {
11319 anyForeground = true;
11320 break;
11321 }
11322 }
11323 if (anyForeground != proc.foregroundServices) {
11324 proc.foregroundServices = anyForeground;
11325 if (oomAdj) {
11326 updateOomAdjLocked();
11327 }
11328 }
11329 }
11330
11331 public int bindService(IApplicationThread caller, IBinder token,
11332 Intent service, String resolvedType,
11333 IServiceConnection connection, int flags) {
11334 // Refuse possible leaked file descriptors
11335 if (service != null && service.hasFileDescriptors() == true) {
11336 throw new IllegalArgumentException("File descriptors passed in Intent");
11337 }
11338
11339 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011340 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 + " type=" + resolvedType + " conn=" + connection.asBinder()
11342 + " flags=0x" + Integer.toHexString(flags));
11343 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11344 if (callerApp == null) {
11345 throw new SecurityException(
11346 "Unable to find app for caller " + caller
11347 + " (pid=" + Binder.getCallingPid()
11348 + ") when binding service " + service);
11349 }
11350
11351 HistoryRecord activity = null;
11352 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011353 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011354 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011355 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011356 return 0;
11357 }
11358 activity = (HistoryRecord)mHistory.get(aindex);
11359 }
11360
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011361 int clientLabel = 0;
11362 PendingIntent clientIntent = null;
11363
11364 if (callerApp.info.uid == Process.SYSTEM_UID) {
11365 // Hacky kind of thing -- allow system stuff to tell us
11366 // what they are, so we can report this elsewhere for
11367 // others to know why certain services are running.
11368 try {
11369 clientIntent = (PendingIntent)service.getParcelableExtra(
11370 Intent.EXTRA_CLIENT_INTENT);
11371 } catch (RuntimeException e) {
11372 }
11373 if (clientIntent != null) {
11374 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11375 if (clientLabel != 0) {
11376 // There are no useful extras in the intent, trash them.
11377 // System code calling with this stuff just needs to know
11378 // this will happen.
11379 service = service.cloneFilter();
11380 }
11381 }
11382 }
11383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384 ServiceLookupResult res =
11385 retrieveServiceLocked(service, resolvedType,
11386 Binder.getCallingPid(), Binder.getCallingUid());
11387 if (res == null) {
11388 return 0;
11389 }
11390 if (res.record == null) {
11391 return -1;
11392 }
11393 ServiceRecord s = res.record;
11394
11395 final long origId = Binder.clearCallingIdentity();
11396
11397 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011398 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 + s.shortName);
11400 }
11401
11402 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11403 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011404 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405
11406 IBinder binder = connection.asBinder();
11407 s.connections.put(binder, c);
11408 b.connections.add(c);
11409 if (activity != null) {
11410 if (activity.connections == null) {
11411 activity.connections = new HashSet<ConnectionRecord>();
11412 }
11413 activity.connections.add(c);
11414 }
11415 b.client.connections.add(c);
11416 mServiceConnections.put(binder, c);
11417
11418 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11419 s.lastActivity = SystemClock.uptimeMillis();
11420 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11421 return 0;
11422 }
11423 }
11424
11425 if (s.app != null) {
11426 // This could have made the service more important.
11427 updateOomAdjLocked(s.app);
11428 }
11429
Joe Onorato8a9b2202010-02-26 18:56:32 -080011430 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011431 + ": received=" + b.intent.received
11432 + " apps=" + b.intent.apps.size()
11433 + " doRebind=" + b.intent.doRebind);
11434
11435 if (s.app != null && b.intent.received) {
11436 // Service is already running, so we can immediately
11437 // publish the connection.
11438 try {
11439 c.conn.connected(s.name, b.intent.binder);
11440 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011441 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011442 + " to connection " + c.conn.asBinder()
11443 + " (in " + c.binding.client.processName + ")", e);
11444 }
11445
11446 // If this is the first app connected back to this binding,
11447 // and the service had previously asked to be told when
11448 // rebound, then do so.
11449 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11450 requestServiceBindingLocked(s, b.intent, true);
11451 }
11452 } else if (!b.intent.requested) {
11453 requestServiceBindingLocked(s, b.intent, false);
11454 }
11455
11456 Binder.restoreCallingIdentity(origId);
11457 }
11458
11459 return 1;
11460 }
11461
11462 private void removeConnectionLocked(
11463 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11464 IBinder binder = c.conn.asBinder();
11465 AppBindRecord b = c.binding;
11466 ServiceRecord s = b.service;
11467 s.connections.remove(binder);
11468 b.connections.remove(c);
11469 if (c.activity != null && c.activity != skipAct) {
11470 if (c.activity.connections != null) {
11471 c.activity.connections.remove(c);
11472 }
11473 }
11474 if (b.client != skipApp) {
11475 b.client.connections.remove(c);
11476 }
11477 mServiceConnections.remove(binder);
11478
11479 if (b.connections.size() == 0) {
11480 b.intent.apps.remove(b.client);
11481 }
11482
Joe Onorato8a9b2202010-02-26 18:56:32 -080011483 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011484 + ": shouldUnbind=" + b.intent.hasBound);
11485 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11486 && b.intent.hasBound) {
11487 try {
11488 bumpServiceExecutingLocked(s);
11489 updateOomAdjLocked(s.app);
11490 b.intent.hasBound = false;
11491 // Assume the client doesn't want to know about a rebind;
11492 // we will deal with that later if it asks for one.
11493 b.intent.doRebind = false;
11494 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11495 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011496 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011497 serviceDoneExecutingLocked(s, true);
11498 }
11499 }
11500
11501 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11502 bringDownServiceLocked(s, false);
11503 }
11504 }
11505
11506 public boolean unbindService(IServiceConnection connection) {
11507 synchronized (this) {
11508 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011509 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011510 ConnectionRecord r = mServiceConnections.get(binder);
11511 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011512 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 + connection.asBinder());
11514 return false;
11515 }
11516
11517 final long origId = Binder.clearCallingIdentity();
11518
11519 removeConnectionLocked(r, null, null);
11520
11521 if (r.binding.service.app != null) {
11522 // This could have made the service less important.
11523 updateOomAdjLocked(r.binding.service.app);
11524 }
11525
11526 Binder.restoreCallingIdentity(origId);
11527 }
11528
11529 return true;
11530 }
11531
11532 public void publishService(IBinder token, Intent intent, IBinder service) {
11533 // Refuse possible leaked file descriptors
11534 if (intent != null && intent.hasFileDescriptors() == true) {
11535 throw new IllegalArgumentException("File descriptors passed in Intent");
11536 }
11537
11538 synchronized(this) {
11539 if (!(token instanceof ServiceRecord)) {
11540 throw new IllegalArgumentException("Invalid service token");
11541 }
11542 ServiceRecord r = (ServiceRecord)token;
11543
11544 final long origId = Binder.clearCallingIdentity();
11545
Joe Onorato8a9b2202010-02-26 18:56:32 -080011546 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011547 + " " + intent + ": " + service);
11548 if (r != null) {
11549 Intent.FilterComparison filter
11550 = new Intent.FilterComparison(intent);
11551 IntentBindRecord b = r.bindings.get(filter);
11552 if (b != null && !b.received) {
11553 b.binder = service;
11554 b.requested = true;
11555 b.received = true;
11556 if (r.connections.size() > 0) {
11557 Iterator<ConnectionRecord> it
11558 = r.connections.values().iterator();
11559 while (it.hasNext()) {
11560 ConnectionRecord c = it.next();
11561 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011562 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011564 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011565 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011566 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011567 TAG, "Published intent: " + intent);
11568 continue;
11569 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011570 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571 try {
11572 c.conn.connected(r.name, service);
11573 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011574 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011575 " to connection " + c.conn.asBinder() +
11576 " (in " + c.binding.client.processName + ")", e);
11577 }
11578 }
11579 }
11580 }
11581
11582 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11583
11584 Binder.restoreCallingIdentity(origId);
11585 }
11586 }
11587 }
11588
11589 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11590 // Refuse possible leaked file descriptors
11591 if (intent != null && intent.hasFileDescriptors() == true) {
11592 throw new IllegalArgumentException("File descriptors passed in Intent");
11593 }
11594
11595 synchronized(this) {
11596 if (!(token instanceof ServiceRecord)) {
11597 throw new IllegalArgumentException("Invalid service token");
11598 }
11599 ServiceRecord r = (ServiceRecord)token;
11600
11601 final long origId = Binder.clearCallingIdentity();
11602
11603 if (r != null) {
11604 Intent.FilterComparison filter
11605 = new Intent.FilterComparison(intent);
11606 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011607 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011608 + " at " + b + ": apps="
11609 + (b != null ? b.apps.size() : 0));
11610 if (b != null) {
11611 if (b.apps.size() > 0) {
11612 // Applications have already bound since the last
11613 // unbind, so just rebind right here.
11614 requestServiceBindingLocked(r, b, true);
11615 } else {
11616 // Note to tell the service the next time there is
11617 // a new client.
11618 b.doRebind = true;
11619 }
11620 }
11621
11622 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11623
11624 Binder.restoreCallingIdentity(origId);
11625 }
11626 }
11627 }
11628
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011629 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011630 synchronized(this) {
11631 if (!(token instanceof ServiceRecord)) {
11632 throw new IllegalArgumentException("Invalid service token");
11633 }
11634 ServiceRecord r = (ServiceRecord)token;
11635 boolean inStopping = mStoppingServices.contains(token);
11636 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011637 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011638 + ": nesting=" + r.executeNesting
11639 + ", inStopping=" + inStopping);
11640 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011641 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011642 + " with incorrect token: given " + token
11643 + ", expected " + r);
11644 return;
11645 }
11646
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011647 if (type == 1) {
11648 // This is a call from a service start... take care of
11649 // book-keeping.
11650 r.callStart = true;
11651 switch (res) {
11652 case Service.START_STICKY_COMPATIBILITY:
11653 case Service.START_STICKY: {
11654 // We are done with the associated start arguments.
11655 r.findDeliveredStart(startId, true);
11656 // Don't stop if killed.
11657 r.stopIfKilled = false;
11658 break;
11659 }
11660 case Service.START_NOT_STICKY: {
11661 // We are done with the associated start arguments.
11662 r.findDeliveredStart(startId, true);
11663 if (r.lastStartId == startId) {
11664 // There is no more work, and this service
11665 // doesn't want to hang around if killed.
11666 r.stopIfKilled = true;
11667 }
11668 break;
11669 }
11670 case Service.START_REDELIVER_INTENT: {
11671 // We'll keep this item until they explicitly
11672 // call stop for it, but keep track of the fact
11673 // that it was delivered.
11674 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11675 if (si != null) {
11676 si.deliveryCount = 0;
11677 si.doneExecutingCount++;
11678 // Don't stop if killed.
11679 r.stopIfKilled = true;
11680 }
11681 break;
11682 }
11683 default:
11684 throw new IllegalArgumentException(
11685 "Unknown service start result: " + res);
11686 }
11687 if (res == Service.START_STICKY_COMPATIBILITY) {
11688 r.callStart = false;
11689 }
11690 }
11691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011692 final long origId = Binder.clearCallingIdentity();
11693 serviceDoneExecutingLocked(r, inStopping);
11694 Binder.restoreCallingIdentity(origId);
11695 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011696 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011697 + " with token " + token);
11698 }
11699 }
11700 }
11701
11702 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11703 r.executeNesting--;
11704 if (r.executeNesting <= 0 && r.app != null) {
11705 r.app.executingServices.remove(r);
11706 if (r.app.executingServices.size() == 0) {
11707 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11708 }
11709 if (inStopping) {
11710 mStoppingServices.remove(r);
11711 }
11712 updateOomAdjLocked(r.app);
11713 }
11714 }
11715
11716 void serviceTimeout(ProcessRecord proc) {
11717 synchronized(this) {
11718 if (proc.executingServices.size() == 0 || proc.thread == null) {
11719 return;
11720 }
11721 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11722 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11723 ServiceRecord timeout = null;
11724 long nextTime = 0;
11725 while (it.hasNext()) {
11726 ServiceRecord sr = it.next();
11727 if (sr.executingStart < maxTime) {
11728 timeout = sr;
11729 break;
11730 }
11731 if (sr.executingStart > nextTime) {
11732 nextTime = sr.executingStart;
11733 }
11734 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011735 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011736 Slog.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011737 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011738 } else {
11739 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11740 msg.obj = proc;
11741 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11742 }
11743 }
11744 }
11745
11746 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011747 // BACKUP AND RESTORE
11748 // =========================================================
11749
11750 // Cause the target app to be launched if necessary and its backup agent
11751 // instantiated. The backup agent will invoke backupAgentCreated() on the
11752 // activity manager to announce its creation.
11753 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011754 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011755 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11756
11757 synchronized(this) {
11758 // !!! TODO: currently no check here that we're already bound
11759 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11760 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11761 synchronized (stats) {
11762 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11763 }
11764
11765 BackupRecord r = new BackupRecord(ss, app, backupMode);
11766 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11767 // startProcessLocked() returns existing proc's record if it's already running
11768 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011769 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011770 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011771 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011772 return false;
11773 }
11774
11775 r.app = proc;
11776 mBackupTarget = r;
11777 mBackupAppName = app.packageName;
11778
Christopher Tate6fa95972009-06-05 18:43:55 -070011779 // Try not to kill the process during backup
11780 updateOomAdjLocked(proc);
11781
Christopher Tate181fafa2009-05-14 11:12:14 -070011782 // If the process is already attached, schedule the creation of the backup agent now.
11783 // If it is not yet live, this will be done when it attaches to the framework.
11784 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011785 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011786 try {
11787 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11788 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011789 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011790 }
11791 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011792 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011793 }
11794 // Invariants: at this point, the target app process exists and the application
11795 // is either already running or in the process of coming up. mBackupTarget and
11796 // mBackupAppName describe the app, so that when it binds back to the AM we
11797 // know that it's scheduled for a backup-agent operation.
11798 }
11799
11800 return true;
11801 }
11802
11803 // A backup agent has just come up
11804 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011805 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011806 + " = " + agent);
11807
11808 synchronized(this) {
11809 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011810 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011811 return;
11812 }
11813
Christopher Tate043dadc2009-06-02 16:11:00 -070011814 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011815 try {
11816 IBackupManager bm = IBackupManager.Stub.asInterface(
11817 ServiceManager.getService(Context.BACKUP_SERVICE));
11818 bm.agentConnected(agentPackageName, agent);
11819 } catch (RemoteException e) {
11820 // can't happen; the backup manager service is local
11821 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011822 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070011823 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011824 } finally {
11825 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011826 }
11827 }
11828 }
11829
11830 // done with this agent
11831 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011832 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011833 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011834 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011835 return;
11836 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011837
11838 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011839 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011840 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011841 return;
11842 }
11843
Christopher Tate181fafa2009-05-14 11:12:14 -070011844 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011845 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011846 return;
11847 }
11848
Christopher Tate6fa95972009-06-05 18:43:55 -070011849 ProcessRecord proc = mBackupTarget.app;
11850 mBackupTarget = null;
11851 mBackupAppName = null;
11852
11853 // Not backing this app up any more; reset its OOM adjustment
11854 updateOomAdjLocked(proc);
11855
Christopher Tatec7b31e32009-06-10 15:49:30 -070011856 // If the app crashed during backup, 'thread' will be null here
11857 if (proc.thread != null) {
11858 try {
11859 proc.thread.scheduleDestroyBackupAgent(appInfo);
11860 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011861 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070011862 e.printStackTrace();
11863 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011864 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011865 }
11866 }
11867 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011868 // BROADCASTS
11869 // =========================================================
11870
11871 private final List getStickies(String action, IntentFilter filter,
11872 List cur) {
11873 final ContentResolver resolver = mContext.getContentResolver();
11874 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11875 if (list == null) {
11876 return cur;
11877 }
11878 int N = list.size();
11879 for (int i=0; i<N; i++) {
11880 Intent intent = list.get(i);
11881 if (filter.match(resolver, intent, true, TAG) >= 0) {
11882 if (cur == null) {
11883 cur = new ArrayList<Intent>();
11884 }
11885 cur.add(intent);
11886 }
11887 }
11888 return cur;
11889 }
11890
11891 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011892 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011893 + mBroadcastsScheduled);
11894
11895 if (mBroadcastsScheduled) {
11896 return;
11897 }
11898 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11899 mBroadcastsScheduled = true;
11900 }
11901
11902 public Intent registerReceiver(IApplicationThread caller,
11903 IIntentReceiver receiver, IntentFilter filter, String permission) {
11904 synchronized(this) {
11905 ProcessRecord callerApp = null;
11906 if (caller != null) {
11907 callerApp = getRecordForAppLocked(caller);
11908 if (callerApp == null) {
11909 throw new SecurityException(
11910 "Unable to find app for caller " + caller
11911 + " (pid=" + Binder.getCallingPid()
11912 + ") when registering receiver " + receiver);
11913 }
11914 }
11915
11916 List allSticky = null;
11917
11918 // Look for any matching sticky broadcasts...
11919 Iterator actions = filter.actionsIterator();
11920 if (actions != null) {
11921 while (actions.hasNext()) {
11922 String action = (String)actions.next();
11923 allSticky = getStickies(action, filter, allSticky);
11924 }
11925 } else {
11926 allSticky = getStickies(null, filter, allSticky);
11927 }
11928
11929 // The first sticky in the list is returned directly back to
11930 // the client.
11931 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11932
Joe Onorato8a9b2202010-02-26 18:56:32 -080011933 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011934 + ": " + sticky);
11935
11936 if (receiver == null) {
11937 return sticky;
11938 }
11939
11940 ReceiverList rl
11941 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11942 if (rl == null) {
11943 rl = new ReceiverList(this, callerApp,
11944 Binder.getCallingPid(),
11945 Binder.getCallingUid(), receiver);
11946 if (rl.app != null) {
11947 rl.app.receivers.add(rl);
11948 } else {
11949 try {
11950 receiver.asBinder().linkToDeath(rl, 0);
11951 } catch (RemoteException e) {
11952 return sticky;
11953 }
11954 rl.linkedToDeath = true;
11955 }
11956 mRegisteredReceivers.put(receiver.asBinder(), rl);
11957 }
11958 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
11959 rl.add(bf);
11960 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011961 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011962 }
11963 mReceiverResolver.addFilter(bf);
11964
11965 // Enqueue broadcasts for all existing stickies that match
11966 // this filter.
11967 if (allSticky != null) {
11968 ArrayList receivers = new ArrayList();
11969 receivers.add(bf);
11970
11971 int N = allSticky.size();
11972 for (int i=0; i<N; i++) {
11973 Intent intent = (Intent)allSticky.get(i);
11974 BroadcastRecord r = new BroadcastRecord(intent, null,
11975 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011976 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011977 if (mParallelBroadcasts.size() == 0) {
11978 scheduleBroadcastsLocked();
11979 }
11980 mParallelBroadcasts.add(r);
11981 }
11982 }
11983
11984 return sticky;
11985 }
11986 }
11987
11988 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011989 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011990
11991 boolean doNext = false;
11992
11993 synchronized(this) {
11994 ReceiverList rl
11995 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11996 if (rl != null) {
11997 if (rl.curBroadcast != null) {
11998 BroadcastRecord r = rl.curBroadcast;
11999 doNext = finishReceiverLocked(
12000 receiver.asBinder(), r.resultCode, r.resultData,
12001 r.resultExtras, r.resultAbort, true);
12002 }
12003
12004 if (rl.app != null) {
12005 rl.app.receivers.remove(rl);
12006 }
12007 removeReceiverLocked(rl);
12008 if (rl.linkedToDeath) {
12009 rl.linkedToDeath = false;
12010 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12011 }
12012 }
12013 }
12014
12015 if (!doNext) {
12016 return;
12017 }
12018
12019 final long origId = Binder.clearCallingIdentity();
12020 processNextBroadcast(false);
12021 trimApplications();
12022 Binder.restoreCallingIdentity(origId);
12023 }
12024
12025 void removeReceiverLocked(ReceiverList rl) {
12026 mRegisteredReceivers.remove(rl.receiver.asBinder());
12027 int N = rl.size();
12028 for (int i=0; i<N; i++) {
12029 mReceiverResolver.removeFilter(rl.get(i));
12030 }
12031 }
12032
12033 private final int broadcastIntentLocked(ProcessRecord callerApp,
12034 String callerPackage, Intent intent, String resolvedType,
12035 IIntentReceiver resultTo, int resultCode, String resultData,
12036 Bundle map, String requiredPermission,
12037 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12038 intent = new Intent(intent);
12039
Joe Onorato8a9b2202010-02-26 18:56:32 -080012040 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012041 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12042 + " ordered=" + ordered);
12043 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012044 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012045 }
12046
12047 // Handle special intents: if this broadcast is from the package
12048 // manager about a package being removed, we need to remove all of
12049 // its activities from the history stack.
12050 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12051 intent.getAction());
12052 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12053 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012054 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012055 || uidRemoved) {
12056 if (checkComponentPermission(
12057 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12058 callingPid, callingUid, -1)
12059 == PackageManager.PERMISSION_GRANTED) {
12060 if (uidRemoved) {
12061 final Bundle intentExtras = intent.getExtras();
12062 final int uid = intentExtras != null
12063 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12064 if (uid >= 0) {
12065 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12066 synchronized (bs) {
12067 bs.removeUidStatsLocked(uid);
12068 }
12069 }
12070 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012071 // If resources are unvailble just force stop all
12072 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012073 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012074 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12075 if (list != null && (list.length > 0)) {
12076 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012077 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012078 }
12079 }
12080 } else {
12081 Uri data = intent.getData();
12082 String ssp;
12083 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12084 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12085 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012086 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012088 }
12089 }
12090 }
12091 } else {
12092 String msg = "Permission Denial: " + intent.getAction()
12093 + " broadcast from " + callerPackage + " (pid=" + callingPid
12094 + ", uid=" + callingUid + ")"
12095 + " requires "
12096 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012097 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012098 throw new SecurityException(msg);
12099 }
12100 }
12101
12102 /*
12103 * If this is the time zone changed action, queue up a message that will reset the timezone
12104 * of all currently running processes. This message will get queued up before the broadcast
12105 * happens.
12106 */
12107 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12108 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12109 }
12110
Dianne Hackborn854060af2009-07-09 18:14:31 -070012111 /*
12112 * Prevent non-system code (defined here to be non-persistent
12113 * processes) from sending protected broadcasts.
12114 */
12115 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12116 || callingUid == Process.SHELL_UID || callingUid == 0) {
12117 // Always okay.
12118 } else if (callerApp == null || !callerApp.persistent) {
12119 try {
12120 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12121 intent.getAction())) {
12122 String msg = "Permission Denial: not allowed to send broadcast "
12123 + intent.getAction() + " from pid="
12124 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012125 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012126 throw new SecurityException(msg);
12127 }
12128 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012129 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012130 return BROADCAST_SUCCESS;
12131 }
12132 }
12133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012134 // Add to the sticky list if requested.
12135 if (sticky) {
12136 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12137 callingPid, callingUid)
12138 != PackageManager.PERMISSION_GRANTED) {
12139 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12140 + callingPid + ", uid=" + callingUid
12141 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012142 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012143 throw new SecurityException(msg);
12144 }
12145 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012146 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012147 + " and enforce permission " + requiredPermission);
12148 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12149 }
12150 if (intent.getComponent() != null) {
12151 throw new SecurityException(
12152 "Sticky broadcasts can't target a specific component");
12153 }
12154 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12155 if (list == null) {
12156 list = new ArrayList<Intent>();
12157 mStickyBroadcasts.put(intent.getAction(), list);
12158 }
12159 int N = list.size();
12160 int i;
12161 for (i=0; i<N; i++) {
12162 if (intent.filterEquals(list.get(i))) {
12163 // This sticky already exists, replace it.
12164 list.set(i, new Intent(intent));
12165 break;
12166 }
12167 }
12168 if (i >= N) {
12169 list.add(new Intent(intent));
12170 }
12171 }
12172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012173 // Figure out who all will receive this broadcast.
12174 List receivers = null;
12175 List<BroadcastFilter> registeredReceivers = null;
12176 try {
12177 if (intent.getComponent() != null) {
12178 // Broadcast is going to one specific receiver class...
12179 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012180 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012181 if (ai != null) {
12182 receivers = new ArrayList();
12183 ResolveInfo ri = new ResolveInfo();
12184 ri.activityInfo = ai;
12185 receivers.add(ri);
12186 }
12187 } else {
12188 // Need to resolve the intent to interested receivers...
12189 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12190 == 0) {
12191 receivers =
12192 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012193 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012194 }
Mihai Preda074edef2009-05-18 17:13:31 +020012195 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012196 }
12197 } catch (RemoteException ex) {
12198 // pm is in same process, this will never happen.
12199 }
12200
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012201 final boolean replacePending =
12202 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12203
Joe Onorato8a9b2202010-02-26 18:56:32 -080012204 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012205 + " replacePending=" + replacePending);
12206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012207 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12208 if (!ordered && NR > 0) {
12209 // If we are not serializing this broadcast, then send the
12210 // registered receivers separately so they don't wait for the
12211 // components to be launched.
12212 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12213 callerPackage, callingPid, callingUid, requiredPermission,
12214 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012215 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012216 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012217 TAG, "Enqueueing parallel broadcast " + r
12218 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012219 boolean replaced = false;
12220 if (replacePending) {
12221 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12222 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012223 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012224 "***** DROPPING PARALLEL: " + intent);
12225 mParallelBroadcasts.set(i, r);
12226 replaced = true;
12227 break;
12228 }
12229 }
12230 }
12231 if (!replaced) {
12232 mParallelBroadcasts.add(r);
12233 scheduleBroadcastsLocked();
12234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012235 registeredReceivers = null;
12236 NR = 0;
12237 }
12238
12239 // Merge into one list.
12240 int ir = 0;
12241 if (receivers != null) {
12242 // A special case for PACKAGE_ADDED: do not allow the package
12243 // being added to see this broadcast. This prevents them from
12244 // using this as a back door to get run as soon as they are
12245 // installed. Maybe in the future we want to have a special install
12246 // broadcast or such for apps, but we'd like to deliberately make
12247 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012248 String skipPackages[] = null;
12249 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12250 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12251 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12252 Uri data = intent.getData();
12253 if (data != null) {
12254 String pkgName = data.getSchemeSpecificPart();
12255 if (pkgName != null) {
12256 skipPackages = new String[] { pkgName };
12257 }
12258 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012259 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012260 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012261 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012262 if (skipPackages != null && (skipPackages.length > 0)) {
12263 for (String skipPackage : skipPackages) {
12264 if (skipPackage != null) {
12265 int NT = receivers.size();
12266 for (int it=0; it<NT; it++) {
12267 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12268 if (curt.activityInfo.packageName.equals(skipPackage)) {
12269 receivers.remove(it);
12270 it--;
12271 NT--;
12272 }
12273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012274 }
12275 }
12276 }
12277
12278 int NT = receivers != null ? receivers.size() : 0;
12279 int it = 0;
12280 ResolveInfo curt = null;
12281 BroadcastFilter curr = null;
12282 while (it < NT && ir < NR) {
12283 if (curt == null) {
12284 curt = (ResolveInfo)receivers.get(it);
12285 }
12286 if (curr == null) {
12287 curr = registeredReceivers.get(ir);
12288 }
12289 if (curr.getPriority() >= curt.priority) {
12290 // Insert this broadcast record into the final list.
12291 receivers.add(it, curr);
12292 ir++;
12293 curr = null;
12294 it++;
12295 NT++;
12296 } else {
12297 // Skip to the next ResolveInfo in the final list.
12298 it++;
12299 curt = null;
12300 }
12301 }
12302 }
12303 while (ir < NR) {
12304 if (receivers == null) {
12305 receivers = new ArrayList();
12306 }
12307 receivers.add(registeredReceivers.get(ir));
12308 ir++;
12309 }
12310
12311 if ((receivers != null && receivers.size() > 0)
12312 || resultTo != null) {
12313 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12314 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012315 receivers, resultTo, resultCode, resultData, map, ordered,
12316 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012317 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012318 TAG, "Enqueueing ordered broadcast " + r
12319 + ": prev had " + mOrderedBroadcasts.size());
12320 if (DEBUG_BROADCAST) {
12321 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012322 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012323 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012324 boolean replaced = false;
12325 if (replacePending) {
12326 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12327 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012328 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012329 "***** DROPPING ORDERED: " + intent);
12330 mOrderedBroadcasts.set(i, r);
12331 replaced = true;
12332 break;
12333 }
12334 }
12335 }
12336 if (!replaced) {
12337 mOrderedBroadcasts.add(r);
12338 scheduleBroadcastsLocked();
12339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012340 }
12341
12342 return BROADCAST_SUCCESS;
12343 }
12344
12345 public final int broadcastIntent(IApplicationThread caller,
12346 Intent intent, String resolvedType, IIntentReceiver resultTo,
12347 int resultCode, String resultData, Bundle map,
12348 String requiredPermission, boolean serialized, boolean sticky) {
12349 // Refuse possible leaked file descriptors
12350 if (intent != null && intent.hasFileDescriptors() == true) {
12351 throw new IllegalArgumentException("File descriptors passed in Intent");
12352 }
12353
12354 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012355 int flags = intent.getFlags();
12356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012357 if (!mSystemReady) {
12358 // if the caller really truly claims to know what they're doing, go
12359 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012360 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12361 intent = new Intent(intent);
12362 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12363 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012364 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012365 + " before boot completion");
12366 throw new IllegalStateException("Cannot broadcast before boot completed");
12367 }
12368 }
12369
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012370 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12371 throw new IllegalArgumentException(
12372 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12373 }
12374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012375 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12376 final int callingPid = Binder.getCallingPid();
12377 final int callingUid = Binder.getCallingUid();
12378 final long origId = Binder.clearCallingIdentity();
12379 int res = broadcastIntentLocked(callerApp,
12380 callerApp != null ? callerApp.info.packageName : null,
12381 intent, resolvedType, resultTo,
12382 resultCode, resultData, map, requiredPermission, serialized,
12383 sticky, callingPid, callingUid);
12384 Binder.restoreCallingIdentity(origId);
12385 return res;
12386 }
12387 }
12388
12389 int broadcastIntentInPackage(String packageName, int uid,
12390 Intent intent, String resolvedType, IIntentReceiver resultTo,
12391 int resultCode, String resultData, Bundle map,
12392 String requiredPermission, boolean serialized, boolean sticky) {
12393 synchronized(this) {
12394 final long origId = Binder.clearCallingIdentity();
12395 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12396 resultTo, resultCode, resultData, map, requiredPermission,
12397 serialized, sticky, -1, uid);
12398 Binder.restoreCallingIdentity(origId);
12399 return res;
12400 }
12401 }
12402
12403 public final void unbroadcastIntent(IApplicationThread caller,
12404 Intent intent) {
12405 // Refuse possible leaked file descriptors
12406 if (intent != null && intent.hasFileDescriptors() == true) {
12407 throw new IllegalArgumentException("File descriptors passed in Intent");
12408 }
12409
12410 synchronized(this) {
12411 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12412 != PackageManager.PERMISSION_GRANTED) {
12413 String msg = "Permission Denial: unbroadcastIntent() from pid="
12414 + Binder.getCallingPid()
12415 + ", uid=" + Binder.getCallingUid()
12416 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012417 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012418 throw new SecurityException(msg);
12419 }
12420 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12421 if (list != null) {
12422 int N = list.size();
12423 int i;
12424 for (i=0; i<N; i++) {
12425 if (intent.filterEquals(list.get(i))) {
12426 list.remove(i);
12427 break;
12428 }
12429 }
12430 }
12431 }
12432 }
12433
12434 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12435 String resultData, Bundle resultExtras, boolean resultAbort,
12436 boolean explicit) {
12437 if (mOrderedBroadcasts.size() == 0) {
12438 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012439 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012440 }
12441 return false;
12442 }
12443 BroadcastRecord r = mOrderedBroadcasts.get(0);
12444 if (r.receiver == null) {
12445 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012446 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012447 }
12448 return false;
12449 }
12450 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012451 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012452 return false;
12453 }
12454 int state = r.state;
12455 r.state = r.IDLE;
12456 if (state == r.IDLE) {
12457 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012458 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012459 }
12460 }
12461 r.receiver = null;
12462 r.intent.setComponent(null);
12463 if (r.curApp != null) {
12464 r.curApp.curReceiver = null;
12465 }
12466 if (r.curFilter != null) {
12467 r.curFilter.receiverList.curBroadcast = null;
12468 }
12469 r.curFilter = null;
12470 r.curApp = null;
12471 r.curComponent = null;
12472 r.curReceiver = null;
12473 mPendingBroadcast = null;
12474
12475 r.resultCode = resultCode;
12476 r.resultData = resultData;
12477 r.resultExtras = resultExtras;
12478 r.resultAbort = resultAbort;
12479
12480 // We will process the next receiver right now if this is finishing
12481 // an app receiver (which is always asynchronous) or after we have
12482 // come back from calling a receiver.
12483 return state == BroadcastRecord.APP_RECEIVE
12484 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12485 }
12486
12487 public void finishReceiver(IBinder who, int resultCode, String resultData,
12488 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012489 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012490
12491 // Refuse possible leaked file descriptors
12492 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12493 throw new IllegalArgumentException("File descriptors passed in Bundle");
12494 }
12495
12496 boolean doNext;
12497
12498 final long origId = Binder.clearCallingIdentity();
12499
12500 synchronized(this) {
12501 doNext = finishReceiverLocked(
12502 who, resultCode, resultData, resultExtras, resultAbort, true);
12503 }
12504
12505 if (doNext) {
12506 processNextBroadcast(false);
12507 }
12508 trimApplications();
12509
12510 Binder.restoreCallingIdentity(origId);
12511 }
12512
12513 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12514 if (r.nextReceiver > 0) {
12515 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12516 if (curReceiver instanceof BroadcastFilter) {
12517 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012518 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012519 System.identityHashCode(r),
12520 r.intent.getAction(),
12521 r.nextReceiver - 1,
12522 System.identityHashCode(bf));
12523 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012524 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012525 System.identityHashCode(r),
12526 r.intent.getAction(),
12527 r.nextReceiver - 1,
12528 ((ResolveInfo)curReceiver).toString());
12529 }
12530 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012531 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012532 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012533 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012534 System.identityHashCode(r),
12535 r.intent.getAction(),
12536 r.nextReceiver,
12537 "NONE");
12538 }
12539 }
12540
12541 private final void broadcastTimeout() {
12542 synchronized (this) {
12543 if (mOrderedBroadcasts.size() == 0) {
12544 return;
12545 }
12546 long now = SystemClock.uptimeMillis();
12547 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012548 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012549 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012550 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012551 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012552 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012553 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012554 return;
12555 }
12556
Joe Onorato8a9b2202010-02-26 18:56:32 -080012557 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012558 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012559 r.anrCount++;
12560
12561 // Current receiver has passed its expiration date.
12562 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012563 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012564 return;
12565 }
12566
12567 ProcessRecord app = null;
12568
12569 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012570 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012571 logBroadcastReceiverDiscard(r);
12572 if (curReceiver instanceof BroadcastFilter) {
12573 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12574 if (bf.receiverList.pid != 0
12575 && bf.receiverList.pid != MY_PID) {
12576 synchronized (this.mPidsSelfLocked) {
12577 app = this.mPidsSelfLocked.get(
12578 bf.receiverList.pid);
12579 }
12580 }
12581 } else {
12582 app = r.curApp;
12583 }
12584
12585 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012586 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012587 }
12588
12589 if (mPendingBroadcast == r) {
12590 mPendingBroadcast = null;
12591 }
12592
12593 // Move on to the next receiver.
12594 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12595 r.resultExtras, r.resultAbort, true);
12596 scheduleBroadcastsLocked();
12597 }
12598 }
12599
12600 private final void processCurBroadcastLocked(BroadcastRecord r,
12601 ProcessRecord app) throws RemoteException {
12602 if (app.thread == null) {
12603 throw new RemoteException();
12604 }
12605 r.receiver = app.thread.asBinder();
12606 r.curApp = app;
12607 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012608 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012609
12610 // Tell the application to launch this receiver.
12611 r.intent.setComponent(r.curComponent);
12612
12613 boolean started = false;
12614 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012615 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012616 "Delivering to component " + r.curComponent
12617 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012618 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012619 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12620 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12621 started = true;
12622 } finally {
12623 if (!started) {
12624 r.receiver = null;
12625 r.curApp = null;
12626 app.curReceiver = null;
12627 }
12628 }
12629
12630 }
12631
12632 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012633 Intent intent, int resultCode, String data, Bundle extras,
12634 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012635 if (app != null && app.thread != null) {
12636 // If we have an app thread, do the call through that so it is
12637 // correctly ordered with other one-way calls.
12638 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012639 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012640 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012641 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012642 }
12643 }
12644
12645 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12646 BroadcastFilter filter, boolean ordered) {
12647 boolean skip = false;
12648 if (filter.requiredPermission != null) {
12649 int perm = checkComponentPermission(filter.requiredPermission,
12650 r.callingPid, r.callingUid, -1);
12651 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012652 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012653 + r.intent.toString()
12654 + " from " + r.callerPackage + " (pid="
12655 + r.callingPid + ", uid=" + r.callingUid + ")"
12656 + " requires " + filter.requiredPermission
12657 + " due to registered receiver " + filter);
12658 skip = true;
12659 }
12660 }
12661 if (r.requiredPermission != null) {
12662 int perm = checkComponentPermission(r.requiredPermission,
12663 filter.receiverList.pid, filter.receiverList.uid, -1);
12664 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012665 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012666 + r.intent.toString()
12667 + " to " + filter.receiverList.app
12668 + " (pid=" + filter.receiverList.pid
12669 + ", uid=" + filter.receiverList.uid + ")"
12670 + " requires " + r.requiredPermission
12671 + " due to sender " + r.callerPackage
12672 + " (uid " + r.callingUid + ")");
12673 skip = true;
12674 }
12675 }
12676
12677 if (!skip) {
12678 // If this is not being sent as an ordered broadcast, then we
12679 // don't want to touch the fields that keep track of the current
12680 // state of ordered broadcasts.
12681 if (ordered) {
12682 r.receiver = filter.receiverList.receiver.asBinder();
12683 r.curFilter = filter;
12684 filter.receiverList.curBroadcast = r;
12685 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012686 if (filter.receiverList.app != null) {
12687 // Bump hosting application to no longer be in background
12688 // scheduling class. Note that we can't do that if there
12689 // isn't an app... but we can only be in that case for
12690 // things that directly call the IActivityManager API, which
12691 // are already core system stuff so don't matter for this.
12692 r.curApp = filter.receiverList.app;
12693 filter.receiverList.app.curReceiver = r;
12694 updateOomAdjLocked();
12695 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012696 }
12697 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012698 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012699 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012700 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012701 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012702 }
12703 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12704 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012705 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012706 if (ordered) {
12707 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12708 }
12709 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012710 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012711 if (ordered) {
12712 r.receiver = null;
12713 r.curFilter = null;
12714 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012715 if (filter.receiverList.app != null) {
12716 filter.receiverList.app.curReceiver = null;
12717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012718 }
12719 }
12720 }
12721 }
12722
Dianne Hackborn12527f92009-11-11 17:39:50 -080012723 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12724 if (r.callingUid < 0) {
12725 // This was from a registerReceiver() call; ignore it.
12726 return;
12727 }
12728 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12729 MAX_BROADCAST_HISTORY-1);
12730 r.finishTime = SystemClock.uptimeMillis();
12731 mBroadcastHistory[0] = r;
12732 }
12733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012734 private final void processNextBroadcast(boolean fromMsg) {
12735 synchronized(this) {
12736 BroadcastRecord r;
12737
Joe Onorato8a9b2202010-02-26 18:56:32 -080012738 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012739 + mParallelBroadcasts.size() + " broadcasts, "
12740 + mOrderedBroadcasts.size() + " serialized broadcasts");
12741
12742 updateCpuStats();
12743
12744 if (fromMsg) {
12745 mBroadcastsScheduled = false;
12746 }
12747
12748 // First, deliver any non-serialized broadcasts right away.
12749 while (mParallelBroadcasts.size() > 0) {
12750 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012751 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012752 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012753 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012754 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012755 for (int i=0; i<N; i++) {
12756 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012757 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012758 "Delivering non-serialized to registered "
12759 + target + ": " + r);
12760 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12761 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012762 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012763 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012764 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012765 }
12766
12767 // Now take care of the next serialized one...
12768
12769 // If we are waiting for a process to come up to handle the next
12770 // broadcast, then do nothing at this point. Just in case, we
12771 // check that the process we're waiting for still exists.
12772 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012773 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012774 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012775 + mPendingBroadcast.curApp);
12776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012777
12778 boolean isDead;
12779 synchronized (mPidsSelfLocked) {
12780 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12781 }
12782 if (!isDead) {
12783 // It's still alive, so keep waiting
12784 return;
12785 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012786 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012787 + " died before responding to broadcast");
12788 mPendingBroadcast = null;
12789 }
12790 }
12791
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012792 boolean looped = false;
12793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012794 do {
12795 if (mOrderedBroadcasts.size() == 0) {
12796 // No more broadcasts pending, so all done!
12797 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012798 if (looped) {
12799 // If we had finished the last ordered broadcast, then
12800 // make sure all processes have correct oom and sched
12801 // adjustments.
12802 updateOomAdjLocked();
12803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012804 return;
12805 }
12806 r = mOrderedBroadcasts.get(0);
12807 boolean forceReceive = false;
12808
12809 // Ensure that even if something goes awry with the timeout
12810 // detection, we catch "hung" broadcasts here, discard them,
12811 // and continue to make progress.
12812 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12813 long now = SystemClock.uptimeMillis();
12814 if (r.dispatchTime > 0) {
12815 if ((numReceivers > 0) &&
12816 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012817 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012818 + " now=" + now
12819 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012820 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012821 + " intent=" + r.intent
12822 + " numReceivers=" + numReceivers
12823 + " nextReceiver=" + r.nextReceiver
12824 + " state=" + r.state);
12825 broadcastTimeout(); // forcibly finish this broadcast
12826 forceReceive = true;
12827 r.state = BroadcastRecord.IDLE;
12828 }
12829 }
12830
12831 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012832 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012833 "processNextBroadcast() called when not idle (state="
12834 + r.state + ")");
12835 return;
12836 }
12837
12838 if (r.receivers == null || r.nextReceiver >= numReceivers
12839 || r.resultAbort || forceReceive) {
12840 // No more receivers for this broadcast! Send the final
12841 // result if requested...
12842 if (r.resultTo != null) {
12843 try {
12844 if (DEBUG_BROADCAST) {
12845 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012846 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012847 + " seq=" + seq + " app=" + r.callerApp);
12848 }
12849 performReceive(r.callerApp, r.resultTo,
12850 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012851 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012852 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012853 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012854 }
12855 }
12856
Joe Onorato8a9b2202010-02-26 18:56:32 -080012857 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012858 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12859
Joe Onorato8a9b2202010-02-26 18:56:32 -080012860 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012861 + r);
12862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012863 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012864 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012865 mOrderedBroadcasts.remove(0);
12866 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012867 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012868 continue;
12869 }
12870 } while (r == null);
12871
12872 // Get the next receiver...
12873 int recIdx = r.nextReceiver++;
12874
12875 // Keep track of when this receiver started, and make sure there
12876 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012877 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012878 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012879 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012880
Joe Onorato8a9b2202010-02-26 18:56:32 -080012881 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012882 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012883 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012884 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012885 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012886 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012887 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012888 }
12889
12890 Object nextReceiver = r.receivers.get(recIdx);
12891 if (nextReceiver instanceof BroadcastFilter) {
12892 // Simple case: this is a registered receiver who gets
12893 // a direct call.
12894 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012895 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012896 "Delivering serialized to registered "
12897 + filter + ": " + r);
12898 deliverToRegisteredReceiver(r, filter, r.ordered);
12899 if (r.receiver == null || !r.ordered) {
12900 // The receiver has already finished, so schedule to
12901 // process the next one.
12902 r.state = BroadcastRecord.IDLE;
12903 scheduleBroadcastsLocked();
12904 }
12905 return;
12906 }
12907
12908 // Hard case: need to instantiate the receiver, possibly
12909 // starting its application process to host it.
12910
12911 ResolveInfo info =
12912 (ResolveInfo)nextReceiver;
12913
12914 boolean skip = false;
12915 int perm = checkComponentPermission(info.activityInfo.permission,
12916 r.callingPid, r.callingUid,
12917 info.activityInfo.exported
12918 ? -1 : info.activityInfo.applicationInfo.uid);
12919 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012920 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012921 + r.intent.toString()
12922 + " from " + r.callerPackage + " (pid=" + r.callingPid
12923 + ", uid=" + r.callingUid + ")"
12924 + " requires " + info.activityInfo.permission
12925 + " due to receiver " + info.activityInfo.packageName
12926 + "/" + info.activityInfo.name);
12927 skip = true;
12928 }
12929 if (r.callingUid != Process.SYSTEM_UID &&
12930 r.requiredPermission != null) {
12931 try {
12932 perm = ActivityThread.getPackageManager().
12933 checkPermission(r.requiredPermission,
12934 info.activityInfo.applicationInfo.packageName);
12935 } catch (RemoteException e) {
12936 perm = PackageManager.PERMISSION_DENIED;
12937 }
12938 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012939 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012940 + r.intent + " to "
12941 + info.activityInfo.applicationInfo.packageName
12942 + " requires " + r.requiredPermission
12943 + " due to sender " + r.callerPackage
12944 + " (uid " + r.callingUid + ")");
12945 skip = true;
12946 }
12947 }
12948 if (r.curApp != null && r.curApp.crashing) {
12949 // If the target process is crashing, just skip it.
12950 skip = true;
12951 }
12952
12953 if (skip) {
12954 r.receiver = null;
12955 r.curFilter = null;
12956 r.state = BroadcastRecord.IDLE;
12957 scheduleBroadcastsLocked();
12958 return;
12959 }
12960
12961 r.state = BroadcastRecord.APP_RECEIVE;
12962 String targetProcess = info.activityInfo.processName;
12963 r.curComponent = new ComponentName(
12964 info.activityInfo.applicationInfo.packageName,
12965 info.activityInfo.name);
12966 r.curReceiver = info.activityInfo;
12967
12968 // Is this receiver's application already running?
12969 ProcessRecord app = getProcessRecordLocked(targetProcess,
12970 info.activityInfo.applicationInfo.uid);
12971 if (app != null && app.thread != null) {
12972 try {
12973 processCurBroadcastLocked(r, app);
12974 return;
12975 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012976 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012977 + r.curComponent, e);
12978 }
12979
12980 // If a dead object exception was thrown -- fall through to
12981 // restart the application.
12982 }
12983
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012984 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012985 if ((r.curApp=startProcessLocked(targetProcess,
12986 info.activityInfo.applicationInfo, true,
12987 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012988 "broadcast", r.curComponent,
12989 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12990 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012991 // Ah, this recipient is unavailable. Finish it if necessary,
12992 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012993 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012994 + info.activityInfo.applicationInfo.packageName + "/"
12995 + info.activityInfo.applicationInfo.uid + " for broadcast "
12996 + r.intent + ": process is bad");
12997 logBroadcastReceiverDiscard(r);
12998 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12999 r.resultExtras, r.resultAbort, true);
13000 scheduleBroadcastsLocked();
13001 r.state = BroadcastRecord.IDLE;
13002 return;
13003 }
13004
13005 mPendingBroadcast = r;
13006 }
13007 }
13008
13009 // =========================================================
13010 // INSTRUMENTATION
13011 // =========================================================
13012
13013 public boolean startInstrumentation(ComponentName className,
13014 String profileFile, int flags, Bundle arguments,
13015 IInstrumentationWatcher watcher) {
13016 // Refuse possible leaked file descriptors
13017 if (arguments != null && arguments.hasFileDescriptors()) {
13018 throw new IllegalArgumentException("File descriptors passed in Bundle");
13019 }
13020
13021 synchronized(this) {
13022 InstrumentationInfo ii = null;
13023 ApplicationInfo ai = null;
13024 try {
13025 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013026 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013027 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013028 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013029 } catch (PackageManager.NameNotFoundException e) {
13030 }
13031 if (ii == null) {
13032 reportStartInstrumentationFailure(watcher, className,
13033 "Unable to find instrumentation info for: " + className);
13034 return false;
13035 }
13036 if (ai == null) {
13037 reportStartInstrumentationFailure(watcher, className,
13038 "Unable to find instrumentation target package: " + ii.targetPackage);
13039 return false;
13040 }
13041
13042 int match = mContext.getPackageManager().checkSignatures(
13043 ii.targetPackage, ii.packageName);
13044 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13045 String msg = "Permission Denial: starting instrumentation "
13046 + className + " from pid="
13047 + Binder.getCallingPid()
13048 + ", uid=" + Binder.getCallingPid()
13049 + " not allowed because package " + ii.packageName
13050 + " does not have a signature matching the target "
13051 + ii.targetPackage;
13052 reportStartInstrumentationFailure(watcher, className, msg);
13053 throw new SecurityException(msg);
13054 }
13055
13056 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013057 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013058 ProcessRecord app = addAppLocked(ai);
13059 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013060 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013061 app.instrumentationProfileFile = profileFile;
13062 app.instrumentationArguments = arguments;
13063 app.instrumentationWatcher = watcher;
13064 app.instrumentationResultClass = className;
13065 Binder.restoreCallingIdentity(origId);
13066 }
13067
13068 return true;
13069 }
13070
13071 /**
13072 * Report errors that occur while attempting to start Instrumentation. Always writes the
13073 * error to the logs, but if somebody is watching, send the report there too. This enables
13074 * the "am" command to report errors with more information.
13075 *
13076 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13077 * @param cn The component name of the instrumentation.
13078 * @param report The error report.
13079 */
13080 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13081 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013082 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013083 try {
13084 if (watcher != null) {
13085 Bundle results = new Bundle();
13086 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13087 results.putString("Error", report);
13088 watcher.instrumentationStatus(cn, -1, results);
13089 }
13090 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013091 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013092 }
13093 }
13094
13095 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13096 if (app.instrumentationWatcher != null) {
13097 try {
13098 // NOTE: IInstrumentationWatcher *must* be oneway here
13099 app.instrumentationWatcher.instrumentationFinished(
13100 app.instrumentationClass,
13101 resultCode,
13102 results);
13103 } catch (RemoteException e) {
13104 }
13105 }
13106 app.instrumentationWatcher = null;
13107 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013108 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013109 app.instrumentationProfileFile = null;
13110 app.instrumentationArguments = null;
13111
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013112 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013113 }
13114
13115 public void finishInstrumentation(IApplicationThread target,
13116 int resultCode, Bundle results) {
13117 // Refuse possible leaked file descriptors
13118 if (results != null && results.hasFileDescriptors()) {
13119 throw new IllegalArgumentException("File descriptors passed in Intent");
13120 }
13121
13122 synchronized(this) {
13123 ProcessRecord app = getRecordForAppLocked(target);
13124 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013125 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013126 return;
13127 }
13128 final long origId = Binder.clearCallingIdentity();
13129 finishInstrumentationLocked(app, resultCode, results);
13130 Binder.restoreCallingIdentity(origId);
13131 }
13132 }
13133
13134 // =========================================================
13135 // CONFIGURATION
13136 // =========================================================
13137
13138 public ConfigurationInfo getDeviceConfigurationInfo() {
13139 ConfigurationInfo config = new ConfigurationInfo();
13140 synchronized (this) {
13141 config.reqTouchScreen = mConfiguration.touchscreen;
13142 config.reqKeyboardType = mConfiguration.keyboard;
13143 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013144 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13145 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013146 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13147 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013148 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13149 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013150 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13151 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013152 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013153 }
13154 return config;
13155 }
13156
13157 public Configuration getConfiguration() {
13158 Configuration ci;
13159 synchronized(this) {
13160 ci = new Configuration(mConfiguration);
13161 }
13162 return ci;
13163 }
13164
13165 public void updateConfiguration(Configuration values) {
13166 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13167 "updateConfiguration()");
13168
13169 synchronized(this) {
13170 if (values == null && mWindowManager != null) {
13171 // sentinel: fetch the current configuration from the window manager
13172 values = mWindowManager.computeNewConfiguration();
13173 }
13174
13175 final long origId = Binder.clearCallingIdentity();
13176 updateConfigurationLocked(values, null);
13177 Binder.restoreCallingIdentity(origId);
13178 }
13179 }
13180
13181 /**
13182 * Do either or both things: (1) change the current configuration, and (2)
13183 * make sure the given activity is running with the (now) current
13184 * configuration. Returns true if the activity has been left running, or
13185 * false if <var>starting</var> is being destroyed to match the new
13186 * configuration.
13187 */
13188 public boolean updateConfigurationLocked(Configuration values,
13189 HistoryRecord starting) {
13190 int changes = 0;
13191
13192 boolean kept = true;
13193
13194 if (values != null) {
13195 Configuration newConfig = new Configuration(mConfiguration);
13196 changes = newConfig.updateFrom(values);
13197 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013198 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013199 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013200 }
13201
Doug Zongker2bec3d42009-12-04 12:52:44 -080013202 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203
13204 if (values.locale != null) {
13205 saveLocaleLocked(values.locale,
13206 !values.locale.equals(mConfiguration.locale),
13207 values.userSetLocale);
13208 }
13209
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013210 mConfigurationSeq++;
13211 if (mConfigurationSeq <= 0) {
13212 mConfigurationSeq = 1;
13213 }
13214 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013215 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013216 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013217
13218 AttributeCache ac = AttributeCache.instance();
13219 if (ac != null) {
13220 ac.updateConfiguration(mConfiguration);
13221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013222
13223 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13224 msg.obj = new Configuration(mConfiguration);
13225 mHandler.sendMessage(msg);
13226
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013227 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13228 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013229 try {
13230 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013231 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013232 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013233 app.thread.scheduleConfigurationChanged(mConfiguration);
13234 }
13235 } catch (Exception e) {
13236 }
13237 }
13238 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013239 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13240 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013241 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13242 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013243 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13244 broadcastIntentLocked(null, null,
13245 new Intent(Intent.ACTION_LOCALE_CHANGED),
13246 null, null, 0, null, null,
13247 null, false, false, MY_PID, Process.SYSTEM_UID);
13248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013249 }
13250 }
13251
13252 if (changes != 0 && starting == null) {
13253 // If the configuration changed, and the caller is not already
13254 // in the process of starting an activity, then find the top
13255 // activity to check if its configuration needs to change.
13256 starting = topRunningActivityLocked(null);
13257 }
13258
13259 if (starting != null) {
13260 kept = ensureActivityConfigurationLocked(starting, changes);
13261 if (kept) {
13262 // If this didn't result in the starting activity being
13263 // destroyed, then we need to make sure at this point that all
13264 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013265 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013266 + ", ensuring others are correct.");
13267 ensureActivitiesVisibleLocked(starting, changes);
13268 }
13269 }
13270
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013271 if (values != null && mWindowManager != null) {
13272 mWindowManager.setNewConfiguration(mConfiguration);
13273 }
13274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013275 return kept;
13276 }
13277
13278 private final boolean relaunchActivityLocked(HistoryRecord r,
13279 int changes, boolean andResume) {
13280 List<ResultInfo> results = null;
13281 List<Intent> newIntents = null;
13282 if (andResume) {
13283 results = r.results;
13284 newIntents = r.newIntents;
13285 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013286 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013287 + " with results=" + results + " newIntents=" + newIntents
13288 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013289 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13290 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013291 r.task.taskId, r.shortComponentName);
13292
13293 r.startFreezingScreenLocked(r.app, 0);
13294
13295 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013296 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013297 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013298 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013299 // Note: don't need to call pauseIfSleepingLocked() here, because
13300 // the caller will only pass in 'andResume' if this activity is
13301 // currently resumed, which implies we aren't sleeping.
13302 } catch (RemoteException e) {
13303 return false;
13304 }
13305
13306 if (andResume) {
13307 r.results = null;
13308 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013309 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013310 }
13311
13312 return true;
13313 }
13314
13315 /**
13316 * Make sure the given activity matches the current configuration. Returns
13317 * false if the activity had to be destroyed. Returns true if the
13318 * configuration is the same, or the activity will remain running as-is
13319 * for whatever reason. Ensures the HistoryRecord is updated with the
13320 * correct configuration and all other bookkeeping is handled.
13321 */
13322 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13323 int globalChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013324 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013325 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013326
13327 // Short circuit: if the two configurations are the exact same
13328 // object (the common case), then there is nothing to do.
13329 Configuration newConfig = mConfiguration;
13330 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013331 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013332 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013333 return true;
13334 }
13335
13336 // We don't worry about activities that are finishing.
13337 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013338 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013339 "Configuration doesn't matter in finishing " + r);
13340 r.stopFreezingScreenLocked(false);
13341 return true;
13342 }
13343
13344 // Okay we now are going to make this activity have the new config.
13345 // But then we need to figure out how it needs to deal with that.
13346 Configuration oldConfig = r.configuration;
13347 r.configuration = newConfig;
13348
13349 // If the activity isn't currently running, just leave the new
13350 // configuration and it will pick that up next time it starts.
13351 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013352 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013353 "Configuration doesn't matter not running " + r);
13354 r.stopFreezingScreenLocked(false);
13355 return true;
13356 }
13357
13358 // If the activity isn't persistent, there is a chance we will
13359 // need to restart it.
13360 if (!r.persistent) {
13361
13362 // Figure out what has changed between the two configurations.
13363 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013364 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013365 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013366 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013367 + Integer.toHexString(r.info.configChanges)
13368 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013369 }
13370 if ((changes&(~r.info.configChanges)) != 0) {
13371 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13372 r.configChangeFlags |= changes;
13373 r.startFreezingScreenLocked(r.app, globalChanges);
13374 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013375 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013376 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013377 destroyActivityLocked(r, true);
13378 } else if (r.state == ActivityState.PAUSING) {
13379 // A little annoying: we are waiting for this activity to
13380 // finish pausing. Let's not do anything now, but just
13381 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013382 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013383 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013384 r.configDestroy = true;
13385 return true;
13386 } else if (r.state == ActivityState.RESUMED) {
13387 // Try to optimize this case: the configuration is changing
13388 // and we need to restart the top, resumed activity.
13389 // Instead of doing the normal handshaking, just say
13390 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013391 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013392 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013393 relaunchActivityLocked(r, r.configChangeFlags, true);
13394 r.configChangeFlags = 0;
13395 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013396 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013397 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013398 relaunchActivityLocked(r, r.configChangeFlags, false);
13399 r.configChangeFlags = 0;
13400 }
13401
13402 // All done... tell the caller we weren't able to keep this
13403 // activity around.
13404 return false;
13405 }
13406 }
13407
13408 // Default case: the activity can handle this new configuration, so
13409 // hand it over. Note that we don't need to give it the new
13410 // configuration, since we always send configuration changes to all
13411 // process when they happen so it can just use whatever configuration
13412 // it last got.
13413 if (r.app != null && r.app.thread != null) {
13414 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013415 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013416 r.app.thread.scheduleActivityConfigurationChanged(r);
13417 } catch (RemoteException e) {
13418 // If process died, whatever.
13419 }
13420 }
13421 r.stopFreezingScreenLocked(false);
13422
13423 return true;
13424 }
13425
13426 /**
13427 * Save the locale. You must be inside a synchronized (this) block.
13428 */
13429 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13430 if(isDiff) {
13431 SystemProperties.set("user.language", l.getLanguage());
13432 SystemProperties.set("user.region", l.getCountry());
13433 }
13434
13435 if(isPersist) {
13436 SystemProperties.set("persist.sys.language", l.getLanguage());
13437 SystemProperties.set("persist.sys.country", l.getCountry());
13438 SystemProperties.set("persist.sys.localevar", l.getVariant());
13439 }
13440 }
13441
13442 // =========================================================
13443 // LIFETIME MANAGEMENT
13444 // =========================================================
13445
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013446 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13447 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013448 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013449 // This adjustment has already been computed. If we are calling
13450 // from the top, we may have already computed our adjustment with
13451 // an earlier hidden adjustment that isn't really for us... if
13452 // so, use the new hidden adjustment.
13453 if (!recursed && app.hidden) {
13454 app.curAdj = hiddenAdj;
13455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013456 return app.curAdj;
13457 }
13458
13459 if (app.thread == null) {
13460 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013461 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013462 return (app.curAdj=EMPTY_APP_ADJ);
13463 }
13464
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013465 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13466 // The max adjustment doesn't allow this app to be anything
13467 // below foreground, so it is not worth doing work for it.
13468 app.adjType = "fixed";
13469 app.adjSeq = mAdjSeq;
13470 app.curRawAdj = app.maxAdj;
13471 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13472 return (app.curAdj=app.maxAdj);
13473 }
13474
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013475 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013476 app.adjSource = null;
13477 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013478 app.empty = false;
13479 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013480
The Android Open Source Project4df24232009-03-05 14:34:35 -080013481 // Determine the importance of the process, starting with most
13482 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013483 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013484 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013485 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013486 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013487 // The last app on the list is the foreground app.
13488 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013489 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013490 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013491 } else if (app.instrumentationClass != null) {
13492 // Don't want to kill running instrumentation.
13493 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013494 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013495 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013496 } else if (app.persistentActivities > 0) {
13497 // Special persistent activities... shouldn't be used these days.
13498 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013499 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013500 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013501 } else if (app.curReceiver != null ||
13502 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13503 // An app that is currently receiving a broadcast also
13504 // counts as being in the foreground.
13505 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013506 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013507 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013508 } else if (app.executingServices.size() > 0) {
13509 // An app that is currently executing a service callback also
13510 // counts as being in the foreground.
13511 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013512 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013513 app.adjType = "exec-service";
13514 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 // The user is aware of this app, so make it visible.
13516 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013517 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013518 app.adjType = "foreground-service";
13519 } else if (app.forcingToForeground != null) {
13520 // The user is aware of this app, so make it visible.
13521 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013522 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013523 app.adjType = "force-foreground";
13524 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013525 } else if (app == mHomeProcess) {
13526 // This process is hosting what we currently consider to be the
13527 // home app, so we don't want to let it go into the background.
13528 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013529 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013530 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013531 } else if ((N=app.activities.size()) != 0) {
13532 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013533 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013534 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013535 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013536 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013537 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013538 for (int j=0; j<N; j++) {
13539 if (((HistoryRecord)app.activities.get(j)).visible) {
13540 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013541 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013542 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013543 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013544 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013545 break;
13546 }
13547 }
13548 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013549 // A very not-needed process. If this is lower in the lru list,
13550 // we will push it in to the empty bucket.
13551 app.hidden = true;
13552 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013553 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013554 adj = hiddenAdj;
13555 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013556 }
13557
Joe Onorato8a9b2202010-02-26 18:56:32 -080013558 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013559
The Android Open Source Project4df24232009-03-05 14:34:35 -080013560 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013561 // there are applications dependent on our services or providers, but
13562 // this gives us a baseline and makes sure we don't get into an
13563 // infinite recursion.
13564 app.adjSeq = mAdjSeq;
13565 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013566
Christopher Tate6fa95972009-06-05 18:43:55 -070013567 if (mBackupTarget != null && app == mBackupTarget.app) {
13568 // If possible we want to avoid killing apps while they're being backed up
13569 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013570 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013571 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013572 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013573 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013574 }
13575 }
13576
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013577 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13578 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013579 final long now = SystemClock.uptimeMillis();
13580 // This process is more important if the top activity is
13581 // bound to the service.
13582 Iterator jt = app.services.iterator();
13583 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13584 ServiceRecord s = (ServiceRecord)jt.next();
13585 if (s.startRequested) {
13586 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13587 // This service has seen some activity within
13588 // recent memory, so we will keep its process ahead
13589 // of the background processes.
13590 if (adj > SECONDARY_SERVER_ADJ) {
13591 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013592 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013593 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013594 }
13595 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013596 // If we have let the service slide into the background
13597 // state, still have some text describing what it is doing
13598 // even though the service no longer has an impact.
13599 if (adj > SECONDARY_SERVER_ADJ) {
13600 app.adjType = "started-bg-services";
13601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013602 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013603 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13604 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013605 Iterator<ConnectionRecord> kt
13606 = s.connections.values().iterator();
13607 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13608 // XXX should compute this based on the max of
13609 // all connected clients.
13610 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013611 if (cr.binding.client == app) {
13612 // Binding to ourself is not interesting.
13613 continue;
13614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013615 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13616 ProcessRecord client = cr.binding.client;
13617 int myHiddenAdj = hiddenAdj;
13618 if (myHiddenAdj > client.hiddenAdj) {
13619 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13620 myHiddenAdj = client.hiddenAdj;
13621 } else {
13622 myHiddenAdj = VISIBLE_APP_ADJ;
13623 }
13624 }
13625 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013626 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013627 if (adj > clientAdj) {
13628 adj = clientAdj > VISIBLE_APP_ADJ
13629 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013630 if (!client.hidden) {
13631 app.hidden = false;
13632 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013633 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013634 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13635 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013636 app.adjSource = cr.binding.client;
13637 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013638 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013639 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13640 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13641 schedGroup = Process.THREAD_GROUP_DEFAULT;
13642 }
13643 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013644 }
13645 HistoryRecord a = cr.activity;
13646 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013647 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013648 //}
13649 if (a != null && adj > FOREGROUND_APP_ADJ &&
13650 (a.state == ActivityState.RESUMED
13651 || a.state == ActivityState.PAUSING)) {
13652 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013653 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013654 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013655 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013656 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13657 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013658 app.adjSource = a;
13659 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013660 }
13661 }
13662 }
13663 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013664
13665 // Finally, f this process has active services running in it, we
13666 // would like to avoid killing it unless it would prevent the current
13667 // application from running. By default we put the process in
13668 // with the rest of the background processes; as we scan through
13669 // its services we may bump it up from there.
13670 if (adj > hiddenAdj) {
13671 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013672 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013673 app.adjType = "bg-services";
13674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013675 }
13676
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013677 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13678 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013679 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013680 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13681 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013682 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13683 if (cpr.clients.size() != 0) {
13684 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13685 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13686 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013687 if (client == app) {
13688 // Being our own client is not interesting.
13689 continue;
13690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013691 int myHiddenAdj = hiddenAdj;
13692 if (myHiddenAdj > client.hiddenAdj) {
13693 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13694 myHiddenAdj = client.hiddenAdj;
13695 } else {
13696 myHiddenAdj = FOREGROUND_APP_ADJ;
13697 }
13698 }
13699 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013700 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013701 if (adj > clientAdj) {
13702 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013703 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013704 if (!client.hidden) {
13705 app.hidden = false;
13706 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013707 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013708 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13709 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013710 app.adjSource = client;
13711 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013712 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013713 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13714 schedGroup = Process.THREAD_GROUP_DEFAULT;
13715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013716 }
13717 }
13718 // If the provider has external (non-framework) process
13719 // dependencies, ensure that its adjustment is at least
13720 // FOREGROUND_APP_ADJ.
13721 if (cpr.externals != 0) {
13722 if (adj > FOREGROUND_APP_ADJ) {
13723 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013724 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013725 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013726 app.adjType = "provider";
13727 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013728 }
13729 }
13730 }
13731 }
13732
13733 app.curRawAdj = adj;
13734
Joe Onorato8a9b2202010-02-26 18:56:32 -080013735 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013736 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13737 if (adj > app.maxAdj) {
13738 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013739 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13740 schedGroup = Process.THREAD_GROUP_DEFAULT;
13741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013742 }
13743
13744 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013745 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013747 return adj;
13748 }
13749
13750 /**
13751 * Ask a given process to GC right now.
13752 */
13753 final void performAppGcLocked(ProcessRecord app) {
13754 try {
13755 app.lastRequestedGc = SystemClock.uptimeMillis();
13756 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013757 if (app.reportLowMemory) {
13758 app.reportLowMemory = false;
13759 app.thread.scheduleLowMemory();
13760 } else {
13761 app.thread.processInBackground();
13762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013763 }
13764 } catch (Exception e) {
13765 // whatever.
13766 }
13767 }
13768
13769 /**
13770 * Returns true if things are idle enough to perform GCs.
13771 */
13772 private final boolean canGcNow() {
13773 return mParallelBroadcasts.size() == 0
13774 && mOrderedBroadcasts.size() == 0
13775 && (mSleeping || (mResumedActivity != null &&
13776 mResumedActivity.idle));
13777 }
13778
13779 /**
13780 * Perform GCs on all processes that are waiting for it, but only
13781 * if things are idle.
13782 */
13783 final void performAppGcsLocked() {
13784 final int N = mProcessesToGc.size();
13785 if (N <= 0) {
13786 return;
13787 }
13788 if (canGcNow()) {
13789 while (mProcessesToGc.size() > 0) {
13790 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013791 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13792 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13793 <= SystemClock.uptimeMillis()) {
13794 // To avoid spamming the system, we will GC processes one
13795 // at a time, waiting a few seconds between each.
13796 performAppGcLocked(proc);
13797 scheduleAppGcsLocked();
13798 return;
13799 } else {
13800 // It hasn't been long enough since we last GCed this
13801 // process... put it in the list to wait for its time.
13802 addProcessToGcListLocked(proc);
13803 break;
13804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013805 }
13806 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013807
13808 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013809 }
13810 }
13811
13812 /**
13813 * If all looks good, perform GCs on all processes waiting for them.
13814 */
13815 final void performAppGcsIfAppropriateLocked() {
13816 if (canGcNow()) {
13817 performAppGcsLocked();
13818 return;
13819 }
13820 // Still not idle, wait some more.
13821 scheduleAppGcsLocked();
13822 }
13823
13824 /**
13825 * Schedule the execution of all pending app GCs.
13826 */
13827 final void scheduleAppGcsLocked() {
13828 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013829
13830 if (mProcessesToGc.size() > 0) {
13831 // Schedule a GC for the time to the next process.
13832 ProcessRecord proc = mProcessesToGc.get(0);
13833 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13834
13835 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13836 long now = SystemClock.uptimeMillis();
13837 if (when < (now+GC_TIMEOUT)) {
13838 when = now + GC_TIMEOUT;
13839 }
13840 mHandler.sendMessageAtTime(msg, when);
13841 }
13842 }
13843
13844 /**
13845 * Add a process to the array of processes waiting to be GCed. Keeps the
13846 * list in sorted order by the last GC time. The process can't already be
13847 * on the list.
13848 */
13849 final void addProcessToGcListLocked(ProcessRecord proc) {
13850 boolean added = false;
13851 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13852 if (mProcessesToGc.get(i).lastRequestedGc <
13853 proc.lastRequestedGc) {
13854 added = true;
13855 mProcessesToGc.add(i+1, proc);
13856 break;
13857 }
13858 }
13859 if (!added) {
13860 mProcessesToGc.add(0, proc);
13861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013862 }
13863
13864 /**
13865 * Set up to ask a process to GC itself. This will either do it
13866 * immediately, or put it on the list of processes to gc the next
13867 * time things are idle.
13868 */
13869 final void scheduleAppGcLocked(ProcessRecord app) {
13870 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013871 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013872 return;
13873 }
13874 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013875 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013876 scheduleAppGcsLocked();
13877 }
13878 }
13879
13880 private final boolean updateOomAdjLocked(
13881 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13882 app.hiddenAdj = hiddenAdj;
13883
13884 if (app.thread == null) {
13885 return true;
13886 }
13887
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013888 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013889
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013890 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013891 if (app.curRawAdj != app.setRawAdj) {
13892 if (app.curRawAdj > FOREGROUND_APP_ADJ
13893 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13894 // If this app is transitioning from foreground to
13895 // non-foreground, have it do a gc.
13896 scheduleAppGcLocked(app);
13897 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13898 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13899 // Likewise do a gc when an app is moving in to the
13900 // background (such as a service stopping).
13901 scheduleAppGcLocked(app);
13902 }
13903 app.setRawAdj = app.curRawAdj;
13904 }
13905 if (adj != app.setAdj) {
13906 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013907 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013908 TAG, "Set app " + app.processName +
13909 " oom adj to " + adj);
13910 app.setAdj = adj;
13911 } else {
13912 return false;
13913 }
13914 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013915 if (app.setSchedGroup != app.curSchedGroup) {
13916 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013917 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013918 "Setting process group of " + app.processName
13919 + " to " + app.curSchedGroup);
13920 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013921 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013922 try {
13923 Process.setProcessGroup(app.pid, app.curSchedGroup);
13924 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013925 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013926 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013927 e.printStackTrace();
13928 } finally {
13929 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013930 }
13931 }
13932 if (false) {
13933 if (app.thread != null) {
13934 try {
13935 app.thread.setSchedulingGroup(app.curSchedGroup);
13936 } catch (RemoteException e) {
13937 }
13938 }
13939 }
13940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013941 }
13942
13943 return true;
13944 }
13945
13946 private final HistoryRecord resumedAppLocked() {
13947 HistoryRecord resumedActivity = mResumedActivity;
13948 if (resumedActivity == null || resumedActivity.app == null) {
13949 resumedActivity = mPausingActivity;
13950 if (resumedActivity == null || resumedActivity.app == null) {
13951 resumedActivity = topRunningActivityLocked(null);
13952 }
13953 }
13954 return resumedActivity;
13955 }
13956
13957 private final boolean updateOomAdjLocked(ProcessRecord app) {
13958 final HistoryRecord TOP_ACT = resumedAppLocked();
13959 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13960 int curAdj = app.curAdj;
13961 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13962 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13963
13964 mAdjSeq++;
13965
13966 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13967 if (res) {
13968 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13969 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13970 if (nowHidden != wasHidden) {
13971 // Changed to/from hidden state, so apps after it in the LRU
13972 // list may also be changed.
13973 updateOomAdjLocked();
13974 }
13975 }
13976 return res;
13977 }
13978
13979 private final boolean updateOomAdjLocked() {
13980 boolean didOomAdj = true;
13981 final HistoryRecord TOP_ACT = resumedAppLocked();
13982 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13983
13984 if (false) {
13985 RuntimeException e = new RuntimeException();
13986 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013987 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013988 }
13989
13990 mAdjSeq++;
13991
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013992 // Let's determine how many processes we have running vs.
13993 // how many slots we have for background processes; we may want
13994 // to put multiple processes in a slot of there are enough of
13995 // them.
13996 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13997 int factor = (mLruProcesses.size()-4)/numSlots;
13998 if (factor < 1) factor = 1;
13999 int step = 0;
14000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014001 // First try updating the OOM adjustment for each of the
14002 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014003 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014004 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14005 while (i > 0) {
14006 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014007 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014008 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014009 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014010 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014011 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014012 step++;
14013 if (step >= factor) {
14014 step = 0;
14015 curHiddenAdj++;
14016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014017 }
14018 } else {
14019 didOomAdj = false;
14020 }
14021 }
14022
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014023 // If we return false, we will fall back on killing processes to
14024 // have a fixed limit. Do this if a limit has been requested; else
14025 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014026 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14027 }
14028
14029 private final void trimApplications() {
14030 synchronized (this) {
14031 int i;
14032
14033 // First remove any unused application processes whose package
14034 // has been removed.
14035 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14036 final ProcessRecord app = mRemovedProcesses.get(i);
14037 if (app.activities.size() == 0
14038 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014039 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014040 TAG, "Exiting empty application process "
14041 + app.processName + " ("
14042 + (app.thread != null ? app.thread.asBinder() : null)
14043 + ")\n");
14044 if (app.pid > 0 && app.pid != MY_PID) {
14045 Process.killProcess(app.pid);
14046 } else {
14047 try {
14048 app.thread.scheduleExit();
14049 } catch (Exception e) {
14050 // Ignore exceptions.
14051 }
14052 }
14053 cleanUpApplicationRecordLocked(app, false, -1);
14054 mRemovedProcesses.remove(i);
14055
14056 if (app.persistent) {
14057 if (app.persistent) {
14058 addAppLocked(app.info);
14059 }
14060 }
14061 }
14062 }
14063
14064 // Now try updating the OOM adjustment for each of the
14065 // application processes based on their current state.
14066 // If the setOomAdj() API is not supported, then go with our
14067 // back-up plan...
14068 if (!updateOomAdjLocked()) {
14069
14070 // Count how many processes are running services.
14071 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014072 for (i=mLruProcesses.size()-1; i>=0; i--) {
14073 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014074
14075 if (app.persistent || app.services.size() != 0
14076 || app.curReceiver != null
14077 || app.persistentActivities > 0) {
14078 // Don't count processes holding services against our
14079 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014080 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014081 TAG, "Not trimming app " + app + " with services: "
14082 + app.services);
14083 numServiceProcs++;
14084 }
14085 }
14086
14087 int curMaxProcs = mProcessLimit;
14088 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14089 if (mAlwaysFinishActivities) {
14090 curMaxProcs = 1;
14091 }
14092 curMaxProcs += numServiceProcs;
14093
14094 // Quit as many processes as we can to get down to the desired
14095 // process count. First remove any processes that no longer
14096 // have activites running in them.
14097 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014098 i<mLruProcesses.size()
14099 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014100 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014101 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014102 // Quit an application only if it is not currently
14103 // running any activities.
14104 if (!app.persistent && app.activities.size() == 0
14105 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014106 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014107 TAG, "Exiting empty application process "
14108 + app.processName + " ("
14109 + (app.thread != null ? app.thread.asBinder() : null)
14110 + ")\n");
14111 if (app.pid > 0 && app.pid != MY_PID) {
14112 Process.killProcess(app.pid);
14113 } else {
14114 try {
14115 app.thread.scheduleExit();
14116 } catch (Exception e) {
14117 // Ignore exceptions.
14118 }
14119 }
14120 // todo: For now we assume the application is not buggy
14121 // or evil, and will quit as a result of our request.
14122 // Eventually we need to drive this off of the death
14123 // notification, and kill the process if it takes too long.
14124 cleanUpApplicationRecordLocked(app, false, i);
14125 i--;
14126 }
14127 }
14128
14129 // If we still have too many processes, now from the least
14130 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014131 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014132 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014133 " of " + curMaxProcs + " processes");
14134 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014135 i<mLruProcesses.size()
14136 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014137 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014138 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014139 // Quit the application only if we have a state saved for
14140 // all of its activities.
14141 boolean canQuit = !app.persistent && app.curReceiver == null
14142 && app.services.size() == 0
14143 && app.persistentActivities == 0;
14144 int NUMA = app.activities.size();
14145 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014146 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014147 TAG, "Looking to quit " + app.processName);
14148 for (j=0; j<NUMA && canQuit; j++) {
14149 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014150 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014151 TAG, " " + r.intent.getComponent().flattenToShortString()
14152 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14153 canQuit = (r.haveState || !r.stateNotNeeded)
14154 && !r.visible && r.stopped;
14155 }
14156 if (canQuit) {
14157 // Finish all of the activities, and then the app itself.
14158 for (j=0; j<NUMA; j++) {
14159 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14160 if (!r.finishing) {
14161 destroyActivityLocked(r, false);
14162 }
14163 r.resultTo = null;
14164 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014165 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014166 + app.processName + " ("
14167 + (app.thread != null ? app.thread.asBinder() : null)
14168 + ")\n");
14169 if (app.pid > 0 && app.pid != MY_PID) {
14170 Process.killProcess(app.pid);
14171 } else {
14172 try {
14173 app.thread.scheduleExit();
14174 } catch (Exception e) {
14175 // Ignore exceptions.
14176 }
14177 }
14178 // todo: For now we assume the application is not buggy
14179 // or evil, and will quit as a result of our request.
14180 // Eventually we need to drive this off of the death
14181 // notification, and kill the process if it takes too long.
14182 cleanUpApplicationRecordLocked(app, false, i);
14183 i--;
14184 //dump();
14185 }
14186 }
14187
14188 }
14189
14190 int curMaxActivities = MAX_ACTIVITIES;
14191 if (mAlwaysFinishActivities) {
14192 curMaxActivities = 1;
14193 }
14194
14195 // Finally, if there are too many activities now running, try to
14196 // finish as many as we can to get back down to the limit.
14197 for ( i=0;
14198 i<mLRUActivities.size()
14199 && mLRUActivities.size() > curMaxActivities;
14200 i++) {
14201 final HistoryRecord r
14202 = (HistoryRecord)mLRUActivities.get(i);
14203
14204 // We can finish this one if we have its icicle saved and
14205 // it is not persistent.
14206 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14207 && r.stopped && !r.persistent && !r.finishing) {
14208 final int origSize = mLRUActivities.size();
14209 destroyActivityLocked(r, true);
14210
14211 // This will remove it from the LRU list, so keep
14212 // our index at the same value. Note that this check to
14213 // see if the size changes is just paranoia -- if
14214 // something unexpected happens, we don't want to end up
14215 // in an infinite loop.
14216 if (origSize > mLRUActivities.size()) {
14217 i--;
14218 }
14219 }
14220 }
14221 }
14222 }
14223
14224 /** This method sends the specified signal to each of the persistent apps */
14225 public void signalPersistentProcesses(int sig) throws RemoteException {
14226 if (sig != Process.SIGNAL_USR1) {
14227 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14228 }
14229
14230 synchronized (this) {
14231 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14232 != PackageManager.PERMISSION_GRANTED) {
14233 throw new SecurityException("Requires permission "
14234 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14235 }
14236
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014237 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14238 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014239 if (r.thread != null && r.persistent) {
14240 Process.sendSignal(r.pid, sig);
14241 }
14242 }
14243 }
14244 }
14245
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014246 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014247 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014248
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014249 try {
14250 synchronized (this) {
14251 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14252 // its own permission.
14253 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14254 != PackageManager.PERMISSION_GRANTED) {
14255 throw new SecurityException("Requires permission "
14256 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014257 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014258
14259 if (start && fd == null) {
14260 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014261 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014262
14263 ProcessRecord proc = null;
14264 try {
14265 int pid = Integer.parseInt(process);
14266 synchronized (mPidsSelfLocked) {
14267 proc = mPidsSelfLocked.get(pid);
14268 }
14269 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014270 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014271
14272 if (proc == null) {
14273 HashMap<String, SparseArray<ProcessRecord>> all
14274 = mProcessNames.getMap();
14275 SparseArray<ProcessRecord> procs = all.get(process);
14276 if (procs != null && procs.size() > 0) {
14277 proc = procs.valueAt(0);
14278 }
14279 }
14280
14281 if (proc == null || proc.thread == null) {
14282 throw new IllegalArgumentException("Unknown process: " + process);
14283 }
14284
14285 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14286 if (isSecure) {
14287 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14288 throw new SecurityException("Process not debuggable: " + proc);
14289 }
14290 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014291
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014292 proc.thread.profilerControl(start, path, fd);
14293 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014294 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014295 }
14296 } catch (RemoteException e) {
14297 throw new IllegalStateException("Process disappeared");
14298 } finally {
14299 if (fd != null) {
14300 try {
14301 fd.close();
14302 } catch (IOException e) {
14303 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014304 }
14305 }
14306 }
14307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014308 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14309 public void monitor() {
14310 synchronized (this) { }
14311 }
14312}