blob: f6289ae3abb612ae6a9c3bc368b398cfd0620a37 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070020import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.server.IntentResolver;
22import com.android.server.ProcessMap;
23import com.android.server.ProcessStats;
24import com.android.server.SystemServer;
25import com.android.server.Watchdog;
26import com.android.server.WindowManagerService;
27
Dianne Hackborndd71fc82009-12-16 19:24:32 -080028import dalvik.system.Zygote;
29
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.app.Activity;
31import android.app.ActivityManager;
32import android.app.ActivityManagerNative;
33import android.app.ActivityThread;
34import android.app.AlertDialog;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020035import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070037import android.app.IActivityController;
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -080038import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.IActivityWatcher;
40import android.app.IApplicationThread;
41import android.app.IInstrumentationWatcher;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.app.IServiceConnection;
43import android.app.IThumbnailReceiver;
44import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070045import android.app.Notification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.PendingIntent;
47import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070048import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080049import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020050import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080051import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.ComponentName;
53import android.content.ContentResolver;
54import android.content.Context;
55import android.content.Intent;
56import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070057import android.content.IIntentReceiver;
58import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070059import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.content.pm.ActivityInfo;
61import android.content.pm.ApplicationInfo;
62import android.content.pm.ConfigurationInfo;
63import android.content.pm.IPackageDataObserver;
64import android.content.pm.IPackageManager;
65import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080066import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070068import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.content.pm.ProviderInfo;
70import android.content.pm.ResolveInfo;
71import android.content.pm.ServiceInfo;
72import android.content.res.Configuration;
73import android.graphics.Bitmap;
74import android.net.Uri;
75import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080076import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080077import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070078import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080079import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.FileUtils;
83import android.os.Handler;
84import android.os.IBinder;
85import android.os.IPermissionController;
86import android.os.Looper;
87import android.os.Message;
88import android.os.Parcel;
89import android.os.ParcelFileDescriptor;
90import android.os.PowerManager;
91import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070092import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.os.RemoteException;
94import android.os.ServiceManager;
95import android.os.SystemClock;
96import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.util.Config;
99import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800100import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800101import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.PrintWriterPrinter;
103import android.util.SparseArray;
104import android.view.Gravity;
105import android.view.LayoutInflater;
106import android.view.View;
107import android.view.WindowManager;
108import android.view.WindowManagerPolicy;
109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import java.io.File;
111import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200113import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import java.io.PrintWriter;
115import java.lang.IllegalStateException;
116import java.lang.ref.WeakReference;
117import java.util.ArrayList;
118import java.util.HashMap;
119import java.util.HashSet;
120import java.util.Iterator;
121import java.util.List;
122import java.util.Locale;
123import java.util.Map;
124
125public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
126 static final String TAG = "ActivityManager";
127 static final boolean DEBUG = false;
128 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
129 static final boolean DEBUG_SWITCH = localLOGV || false;
130 static final boolean DEBUG_TASKS = localLOGV || false;
131 static final boolean DEBUG_PAUSE = localLOGV || false;
132 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
133 static final boolean DEBUG_TRANSITION = localLOGV || false;
134 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700135 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 static final boolean DEBUG_SERVICE = localLOGV || false;
137 static final boolean DEBUG_VISBILITY = localLOGV || false;
138 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700139 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800140 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700142 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700143 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700144 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean VALIDATE_TOKENS = false;
146 static final boolean SHOW_ACTIVITY_START_TIME = true;
147
148 // Control over CPU and battery monitoring.
149 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
150 static final boolean MONITOR_CPU_USAGE = true;
151 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
152 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
153 static final boolean MONITOR_THREAD_CPU_USAGE = false;
154
Dianne Hackborn1655be42009-05-08 14:29:01 -0700155 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700156 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 private static final String SYSTEM_SECURE = "ro.secure";
159
160 // This is the maximum number of application processes we would like
161 // to have running. Due to the asynchronous nature of things, we can
162 // temporarily go beyond this limit.
163 static final int MAX_PROCESSES = 2;
164
165 // Set to false to leave processes running indefinitely, relying on
166 // the kernel killing them as resources are required.
167 static final boolean ENFORCE_PROCESS_LIMIT = false;
168
169 // This is the maximum number of activities that we would like to have
170 // running at a given time.
171 static final int MAX_ACTIVITIES = 20;
172
173 // Maximum number of recent tasks that we can remember.
174 static final int MAX_RECENT_TASKS = 20;
175
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700176 // Amount of time after a call to stopAppSwitches() during which we will
177 // prevent further untrusted switches from happening.
178 static final long APP_SWITCH_DELAY_TIME = 5*1000;
179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 // How long until we reset a task when the user returns to it. Currently
181 // 30 minutes.
182 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
183
184 // Set to true to disable the icon that is shown while a new activity
185 // is being started.
186 static final boolean SHOW_APP_STARTING_ICON = true;
187
188 // How long we wait until giving up on the last activity to pause. This
189 // is short because it directly impacts the responsiveness of starting the
190 // next activity.
191 static final int PAUSE_TIMEOUT = 500;
192
193 /**
194 * How long we can hold the launch wake lock before giving up.
195 */
196 static final int LAUNCH_TIMEOUT = 10*1000;
197
198 // How long we wait for a launched process to attach to the activity manager
199 // before we decide it's never going to come up for real.
200 static final int PROC_START_TIMEOUT = 10*1000;
201
202 // How long we wait until giving up on the last activity telling us it
203 // is idle.
204 static final int IDLE_TIMEOUT = 10*1000;
205
206 // How long to wait after going idle before forcing apps to GC.
207 static final int GC_TIMEOUT = 5*1000;
208
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700209 // The minimum amount of time between successive GC requests for a process.
210 static final int GC_MIN_INTERVAL = 60*1000;
211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 // How long we wait until giving up on an activity telling us it has
213 // finished destroying itself.
214 static final int DESTROY_TIMEOUT = 10*1000;
215
216 // How long we allow a receiver to run before giving up on it.
217 static final int BROADCAST_TIMEOUT = 10*1000;
218
219 // How long we wait for a service to finish executing.
220 static final int SERVICE_TIMEOUT = 20*1000;
221
222 // How long a service needs to be running until restarting its process
223 // is no longer considered to be a relaunch of the service.
224 static final int SERVICE_RESTART_DURATION = 5*1000;
225
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700226 // How long a service needs to be running until it will start back at
227 // SERVICE_RESTART_DURATION after being killed.
228 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
229
230 // Multiplying factor to increase restart duration time by, for each time
231 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
232 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
233
234 // The minimum amount of time between restarting services that we allow.
235 // That is, when multiple services are restarting, we won't allow each
236 // to restart less than this amount of time from the last one.
237 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 // Maximum amount of time for there to be no activity on a service before
240 // we consider it non-essential and allow its process to go on the
241 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700242 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243
244 // How long we wait until we timeout on key dispatching.
245 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
246
247 // The minimum time we allow between crashes, for us to consider this
248 // application to be bad and stop and its services and reject broadcasts.
249 static final int MIN_CRASH_INTERVAL = 60*1000;
250
251 // How long we wait until we timeout on key dispatching during instrumentation.
252 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
253
254 // OOM adjustments for processes in various states:
255
256 // This is a process without anything currently running in it. Definitely
257 // the first to go! Value set in system/rootdir/init.rc on startup.
258 // This value is initalized in the constructor, careful when refering to
259 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800260 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261
262 // This is a process only hosting activities that are not visible,
263 // so it can be killed without any disruption. Value set in
264 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800265 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 static int HIDDEN_APP_MIN_ADJ;
267
The Android Open Source Project4df24232009-03-05 14:34:35 -0800268 // This is a process holding the home application -- we want to try
269 // avoiding killing it, even if it would normally be in the background,
270 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800271 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800272
Christopher Tate6fa95972009-06-05 18:43:55 -0700273 // This is a process currently hosting a backup operation. Killing it
274 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 // This is a process holding a secondary server -- killing it will not
278 // have much of an impact as far as the user is concerned. Value set in
279 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800280 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281
282 // This is a process only hosting activities that are visible to the
283 // user, so we'd prefer they don't disappear. Value set in
284 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800285 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286
287 // This is the process running the current foreground app. We'd really
288 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
291 // This is a process running a core server, such as telephony. Definitely
292 // don't want to kill it, but doing so is not completely fatal.
293 static final int CORE_SERVER_ADJ = -12;
294
295 // The system process runs at the default adjustment.
296 static final int SYSTEM_ADJ = -16;
297
298 // Memory pages are 4K.
299 static final int PAGE_SIZE = 4*1024;
300
301 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800302 static final int EMPTY_APP_MEM;
303 static final int HIDDEN_APP_MEM;
304 static final int HOME_APP_MEM;
305 static final int BACKUP_APP_MEM;
306 static final int SECONDARY_SERVER_MEM;
307 static final int VISIBLE_APP_MEM;
308 static final int FOREGROUND_APP_MEM;
309
310 // The minimum number of hidden apps we want to be able to keep around,
311 // without empty apps being able to push them out of memory.
312 static final int MIN_HIDDEN_APPS = 2;
313
314 // We put empty content processes after any hidden processes that have
315 // been idle for less than 30 seconds.
316 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
317
318 // We put empty content processes after any hidden processes that have
319 // been idle for less than 60 seconds.
320 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
321
322 static {
323 // These values are set in system/rootdir/init.rc on startup.
324 FOREGROUND_APP_ADJ =
325 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
326 VISIBLE_APP_ADJ =
327 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
328 SECONDARY_SERVER_ADJ =
329 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
330 BACKUP_APP_ADJ =
331 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
332 HOME_APP_ADJ =
333 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
334 HIDDEN_APP_MIN_ADJ =
335 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
336 EMPTY_APP_ADJ =
337 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
338 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
339 FOREGROUND_APP_MEM =
340 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
341 VISIBLE_APP_MEM =
342 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
343 SECONDARY_SERVER_MEM =
344 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
345 BACKUP_APP_MEM =
346 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
347 HOME_APP_MEM =
348 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
349 HIDDEN_APP_MEM =
350 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
351 EMPTY_APP_MEM =
352 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354
Dan Egnor42471dd2010-01-07 17:25:22 -0800355 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356
357 static final String[] EMPTY_STRING_ARRAY = new String[0];
358
359 enum ActivityState {
360 INITIALIZING,
361 RESUMED,
362 PAUSING,
363 PAUSED,
364 STOPPING,
365 STOPPED,
366 FINISHING,
367 DESTROYING,
368 DESTROYED
369 }
370
371 /**
372 * The back history of all previous (and possibly still
373 * running) activities. It contains HistoryRecord objects.
374 */
375 final ArrayList mHistory = new ArrayList();
376
377 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700378 * Description of a request to start a new activity, which has been held
379 * due to app switches being disabled.
380 */
381 class PendingActivityLaunch {
382 HistoryRecord r;
383 HistoryRecord sourceRecord;
384 Uri[] grantedUriPermissions;
385 int grantedMode;
386 boolean onlyIfNeeded;
387 }
388
389 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
390 = new ArrayList<PendingActivityLaunch>();
391
392 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800393 * List of people waiting to find out about the next launched activity.
394 */
395 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
396 = new ArrayList<IActivityManager.WaitResult>();
397
398 /**
399 * List of people waiting to find out about the next visible activity.
400 */
401 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
402 = new ArrayList<IActivityManager.WaitResult>();
403
404 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 * List of all active broadcasts that are to be executed immediately
406 * (without waiting for another broadcast to finish). Currently this only
407 * contains broadcasts to registered receivers, to avoid spinning up
408 * a bunch of processes to execute IntentReceiver components.
409 */
410 final ArrayList<BroadcastRecord> mParallelBroadcasts
411 = new ArrayList<BroadcastRecord>();
412
413 /**
414 * List of all active broadcasts that are to be executed one at a time.
415 * The object at the top of the list is the currently activity broadcasts;
416 * those after it are waiting for the top to finish..
417 */
418 final ArrayList<BroadcastRecord> mOrderedBroadcasts
419 = new ArrayList<BroadcastRecord>();
420
421 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800422 * Historical data of past broadcasts, for debugging.
423 */
424 static final int MAX_BROADCAST_HISTORY = 100;
425 final BroadcastRecord[] mBroadcastHistory
426 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
427
428 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 * Set when we current have a BROADCAST_INTENT_MSG in flight.
430 */
431 boolean mBroadcastsScheduled = false;
432
433 /**
434 * Set to indicate whether to issue an onUserLeaving callback when a
435 * newly launched activity is being brought in front of us.
436 */
437 boolean mUserLeaving = false;
438
439 /**
440 * When we are in the process of pausing an activity, before starting the
441 * next one, this variable holds the activity that is currently being paused.
442 */
443 HistoryRecord mPausingActivity = null;
444
445 /**
446 * Current activity that is resumed, or null if there is none.
447 */
448 HistoryRecord mResumedActivity = null;
449
450 /**
451 * Activity we have told the window manager to have key focus.
452 */
453 HistoryRecord mFocusedActivity = null;
454
455 /**
456 * This is the last activity that we put into the paused state. This is
457 * used to determine if we need to do an activity transition while sleeping,
458 * when we normally hold the top activity paused.
459 */
460 HistoryRecord mLastPausedActivity = null;
461
462 /**
463 * List of activities that are waiting for a new activity
464 * to become visible before completing whatever operation they are
465 * supposed to do.
466 */
467 final ArrayList mWaitingVisibleActivities = new ArrayList();
468
469 /**
470 * List of activities that are ready to be stopped, but waiting
471 * for the next activity to settle down before doing so. It contains
472 * HistoryRecord objects.
473 */
474 final ArrayList<HistoryRecord> mStoppingActivities
475 = new ArrayList<HistoryRecord>();
476
477 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700478 * Animations that for the current transition have requested not to
479 * be considered for the transition animation.
480 */
481 final ArrayList<HistoryRecord> mNoAnimActivities
482 = new ArrayList<HistoryRecord>();
483
484 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 * List of intents that were used to start the most recent tasks.
486 */
487 final ArrayList<TaskRecord> mRecentTasks
488 = new ArrayList<TaskRecord>();
489
490 /**
491 * List of activities that are ready to be finished, but waiting
492 * for the previous activity to settle down before doing so. It contains
493 * HistoryRecord objects.
494 */
495 final ArrayList mFinishingActivities = new ArrayList();
496
497 /**
498 * All of the applications we currently have running organized by name.
499 * The keys are strings of the application package name (as
500 * returned by the package manager), and the keys are ApplicationRecord
501 * objects.
502 */
503 final ProcessMap<ProcessRecord> mProcessNames
504 = new ProcessMap<ProcessRecord>();
505
506 /**
507 * The last time that various processes have crashed.
508 */
509 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
510
511 /**
512 * Set of applications that we consider to be bad, and will reject
513 * incoming broadcasts from (which the user has no control over).
514 * Processes are added to this set when they have crashed twice within
515 * a minimum amount of time; they are removed from it when they are
516 * later restarted (hopefully due to some user action). The value is the
517 * time it was added to the list.
518 */
519 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
520
521 /**
522 * All of the processes we currently have running organized by pid.
523 * The keys are the pid running the application.
524 *
525 * <p>NOTE: This object is protected by its own lock, NOT the global
526 * activity manager lock!
527 */
528 final SparseArray<ProcessRecord> mPidsSelfLocked
529 = new SparseArray<ProcessRecord>();
530
531 /**
532 * All of the processes that have been forced to be foreground. The key
533 * is the pid of the caller who requested it (we hold a death
534 * link on it).
535 */
536 abstract class ForegroundToken implements IBinder.DeathRecipient {
537 int pid;
538 IBinder token;
539 }
540 final SparseArray<ForegroundToken> mForegroundProcesses
541 = new SparseArray<ForegroundToken>();
542
543 /**
544 * List of records for processes that someone had tried to start before the
545 * system was ready. We don't start them at that point, but ensure they
546 * are started by the time booting is complete.
547 */
548 final ArrayList<ProcessRecord> mProcessesOnHold
549 = new ArrayList<ProcessRecord>();
550
551 /**
552 * List of records for processes that we have started and are waiting
553 * for them to call back. This is really only needed when running in
554 * single processes mode, in which case we do not have a unique pid for
555 * each process.
556 */
557 final ArrayList<ProcessRecord> mStartingProcesses
558 = new ArrayList<ProcessRecord>();
559
560 /**
561 * List of persistent applications that are in the process
562 * of being started.
563 */
564 final ArrayList<ProcessRecord> mPersistentStartingProcesses
565 = new ArrayList<ProcessRecord>();
566
567 /**
568 * Processes that are being forcibly torn down.
569 */
570 final ArrayList<ProcessRecord> mRemovedProcesses
571 = new ArrayList<ProcessRecord>();
572
573 /**
574 * List of running applications, sorted by recent usage.
575 * The first entry in the list is the least recently used.
576 * It contains ApplicationRecord objects. This list does NOT include
577 * any persistent application records (since we never want to exit them).
578 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800579 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 = new ArrayList<ProcessRecord>();
581
582 /**
583 * List of processes that should gc as soon as things are idle.
584 */
585 final ArrayList<ProcessRecord> mProcessesToGc
586 = new ArrayList<ProcessRecord>();
587
588 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800589 * This is the process holding what we currently consider to be
590 * the "home" activity.
591 */
592 private ProcessRecord mHomeProcess;
593
594 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 * List of running activities, sorted by recent usage.
596 * The first entry in the list is the least recently used.
597 * It contains HistoryRecord objects.
598 */
599 private final ArrayList mLRUActivities = new ArrayList();
600
601 /**
602 * Set of PendingResultRecord objects that are currently active.
603 */
604 final HashSet mPendingResultRecords = new HashSet();
605
606 /**
607 * Set of IntentSenderRecord objects that are currently active.
608 */
609 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
610 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
611
612 /**
613 * Intent broadcast that we have tried to start, but are
614 * waiting for its application's process to be created. We only
615 * need one (instead of a list) because we always process broadcasts
616 * one at a time, so no others can be started while waiting for this
617 * one.
618 */
619 BroadcastRecord mPendingBroadcast = null;
620
621 /**
622 * Keeps track of all IIntentReceivers that have been registered for
623 * broadcasts. Hash keys are the receiver IBinder, hash value is
624 * a ReceiverList.
625 */
626 final HashMap mRegisteredReceivers = new HashMap();
627
628 /**
629 * Resolver for broadcast intents to registered receivers.
630 * Holds BroadcastFilter (subclass of IntentFilter).
631 */
632 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
633 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
634 @Override
635 protected boolean allowFilterResult(
636 BroadcastFilter filter, List<BroadcastFilter> dest) {
637 IBinder target = filter.receiverList.receiver.asBinder();
638 for (int i=dest.size()-1; i>=0; i--) {
639 if (dest.get(i).receiverList.receiver.asBinder() == target) {
640 return false;
641 }
642 }
643 return true;
644 }
645 };
646
647 /**
648 * State of all active sticky broadcasts. Keys are the action of the
649 * sticky Intent, values are an ArrayList of all broadcasted intents with
650 * that action (which should usually be one).
651 */
652 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
653 new HashMap<String, ArrayList<Intent>>();
654
655 /**
656 * All currently running services.
657 */
658 final HashMap<ComponentName, ServiceRecord> mServices =
659 new HashMap<ComponentName, ServiceRecord>();
660
661 /**
662 * All currently running services indexed by the Intent used to start them.
663 */
664 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
665 new HashMap<Intent.FilterComparison, ServiceRecord>();
666
667 /**
668 * All currently bound service connections. Keys are the IBinder of
669 * the client's IServiceConnection.
670 */
671 final HashMap<IBinder, ConnectionRecord> mServiceConnections
672 = new HashMap<IBinder, ConnectionRecord>();
673
674 /**
675 * List of services that we have been asked to start,
676 * but haven't yet been able to. It is used to hold start requests
677 * while waiting for their corresponding application thread to get
678 * going.
679 */
680 final ArrayList<ServiceRecord> mPendingServices
681 = new ArrayList<ServiceRecord>();
682
683 /**
684 * List of services that are scheduled to restart following a crash.
685 */
686 final ArrayList<ServiceRecord> mRestartingServices
687 = new ArrayList<ServiceRecord>();
688
689 /**
690 * List of services that are in the process of being stopped.
691 */
692 final ArrayList<ServiceRecord> mStoppingServices
693 = new ArrayList<ServiceRecord>();
694
695 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700696 * Backup/restore process management
697 */
698 String mBackupAppName = null;
699 BackupRecord mBackupTarget = null;
700
701 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 * List of PendingThumbnailsRecord objects of clients who are still
703 * waiting to receive all of the thumbnails for a task.
704 */
705 final ArrayList mPendingThumbnails = new ArrayList();
706
707 /**
708 * List of HistoryRecord objects that have been finished and must
709 * still report back to a pending thumbnail receiver.
710 */
711 final ArrayList mCancelledThumbnails = new ArrayList();
712
713 /**
714 * All of the currently running global content providers. Keys are a
715 * string containing the provider name and values are a
716 * ContentProviderRecord object containing the data about it. Note
717 * that a single provider may be published under multiple names, so
718 * there may be multiple entries here for a single one in mProvidersByClass.
719 */
720 final HashMap mProvidersByName = new HashMap();
721
722 /**
723 * All of the currently running global content providers. Keys are a
724 * string containing the provider's implementation class and values are a
725 * ContentProviderRecord object containing the data about it.
726 */
727 final HashMap mProvidersByClass = new HashMap();
728
729 /**
730 * List of content providers who have clients waiting for them. The
731 * application is currently being launched and the provider will be
732 * removed from this list once it is published.
733 */
734 final ArrayList mLaunchingProviders = new ArrayList();
735
736 /**
737 * Global set of specific Uri permissions that have been granted.
738 */
739 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
740 = new SparseArray<HashMap<Uri, UriPermission>>();
741
742 /**
743 * Thread-local storage used to carry caller permissions over through
744 * indirect content-provider access.
745 * @see #ActivityManagerService.openContentUri()
746 */
747 private class Identity {
748 public int pid;
749 public int uid;
750
751 Identity(int _pid, int _uid) {
752 pid = _pid;
753 uid = _uid;
754 }
755 }
756 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
757
758 /**
759 * All information we have collected about the runtime performance of
760 * any user id that can impact battery performance.
761 */
762 final BatteryStatsService mBatteryStatsService;
763
764 /**
765 * information about component usage
766 */
767 final UsageStatsService mUsageStatsService;
768
769 /**
770 * Current configuration information. HistoryRecord objects are given
771 * a reference to this object to indicate which configuration they are
772 * currently running in, so this object must be kept immutable.
773 */
774 Configuration mConfiguration = new Configuration();
775
776 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800777 * Current sequencing integer of the configuration, for skipping old
778 * configurations.
779 */
780 int mConfigurationSeq = 0;
781
782 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700783 * Hardware-reported OpenGLES version.
784 */
785 final int GL_ES_VERSION;
786
787 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 * List of initialization arguments to pass to all processes when binding applications to them.
789 * For example, references to the commonly used services.
790 */
791 HashMap<String, IBinder> mAppBindArgs;
792
793 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700794 * Temporary to avoid allocations. Protected by main lock.
795 */
796 final StringBuilder mStringBuilder = new StringBuilder(256);
797
798 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 * Used to control how we initialize the service.
800 */
801 boolean mStartRunning = false;
802 ComponentName mTopComponent;
803 String mTopAction;
804 String mTopData;
805 boolean mSystemReady = false;
806 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700807 boolean mWaitingUpdate = false;
808 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809
810 Context mContext;
811
812 int mFactoryTest;
813
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700814 boolean mCheckedForSetup;
815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700817 * The time at which we will allow normal application switches again,
818 * after a call to {@link #stopAppSwitches()}.
819 */
820 long mAppSwitchesAllowedTime;
821
822 /**
823 * This is set to true after the first switch after mAppSwitchesAllowedTime
824 * is set; any switches after that will clear the time.
825 */
826 boolean mDidAppSwitch;
827
828 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 * Set while we are wanting to sleep, to prevent any
830 * activities from being started/resumed.
831 */
832 boolean mSleeping = false;
833
834 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700835 * Set if we are shutting down the system, similar to sleeping.
836 */
837 boolean mShuttingDown = false;
838
839 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 * Set when the system is going to sleep, until we have
841 * successfully paused the current activity and released our wake lock.
842 * At that point the system is allowed to actually sleep.
843 */
844 PowerManager.WakeLock mGoingToSleep;
845
846 /**
847 * We don't want to allow the device to go to sleep while in the process
848 * of launching an activity. This is primarily to allow alarm intent
849 * receivers to launch an activity and get that to run before the device
850 * goes back to sleep.
851 */
852 PowerManager.WakeLock mLaunchingActivity;
853
854 /**
855 * Task identifier that activities are currently being started
856 * in. Incremented each time a new task is created.
857 * todo: Replace this with a TokenSpace class that generates non-repeating
858 * integers that won't wrap.
859 */
860 int mCurTask = 1;
861
862 /**
863 * Current sequence id for oom_adj computation traversal.
864 */
865 int mAdjSeq = 0;
866
867 /**
868 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
869 * is set, indicating the user wants processes started in such a way
870 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
871 * running in each process (thus no pre-initialized process, etc).
872 */
873 boolean mSimpleProcessManagement = false;
874
875 /**
876 * System monitoring: number of processes that died since the last
877 * N procs were started.
878 */
879 int[] mProcDeaths = new int[20];
880
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700881 /**
882 * This is set if we had to do a delayed dexopt of an app before launching
883 * it, to increasing the ANR timeouts in that case.
884 */
885 boolean mDidDexOpt;
886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 String mDebugApp = null;
888 boolean mWaitForDebugger = false;
889 boolean mDebugTransient = false;
890 String mOrigDebugApp = null;
891 boolean mOrigWaitForDebugger = false;
892 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700893 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700895 final RemoteCallbackList<IActivityWatcher> mWatchers
896 = new RemoteCallbackList<IActivityWatcher>();
897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 /**
899 * Callback of last caller to {@link #requestPss}.
900 */
901 Runnable mRequestPssCallback;
902
903 /**
904 * Remaining processes for which we are waiting results from the last
905 * call to {@link #requestPss}.
906 */
907 final ArrayList<ProcessRecord> mRequestPssList
908 = new ArrayList<ProcessRecord>();
909
910 /**
911 * Runtime statistics collection thread. This object's lock is used to
912 * protect all related state.
913 */
914 final Thread mProcessStatsThread;
915
916 /**
917 * Used to collect process stats when showing not responding dialog.
918 * Protected by mProcessStatsThread.
919 */
920 final ProcessStats mProcessStats = new ProcessStats(
921 MONITOR_THREAD_CPU_USAGE);
922 long mLastCpuTime = 0;
923 long mLastWriteTime = 0;
924
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700925 long mInitialStartTime = 0;
926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 /**
928 * Set to true after the system has finished booting.
929 */
930 boolean mBooted = false;
931
932 int mProcessLimit = 0;
933
934 WindowManagerService mWindowManager;
935
936 static ActivityManagerService mSelf;
937 static ActivityThread mSystemThread;
938
939 private final class AppDeathRecipient implements IBinder.DeathRecipient {
940 final ProcessRecord mApp;
941 final int mPid;
942 final IApplicationThread mAppThread;
943
944 AppDeathRecipient(ProcessRecord app, int pid,
945 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800946 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 TAG, "New death recipient " + this
948 + " for thread " + thread.asBinder());
949 mApp = app;
950 mPid = pid;
951 mAppThread = thread;
952 }
953
954 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800955 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 TAG, "Death received in " + this
957 + " for thread " + mAppThread.asBinder());
958 removeRequestedPss(mApp);
959 synchronized(ActivityManagerService.this) {
960 appDiedLocked(mApp, mPid, mAppThread);
961 }
962 }
963 }
964
965 static final int SHOW_ERROR_MSG = 1;
966 static final int SHOW_NOT_RESPONDING_MSG = 2;
967 static final int SHOW_FACTORY_ERROR_MSG = 3;
968 static final int UPDATE_CONFIGURATION_MSG = 4;
969 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
970 static final int WAIT_FOR_DEBUGGER_MSG = 6;
971 static final int BROADCAST_INTENT_MSG = 7;
972 static final int BROADCAST_TIMEOUT_MSG = 8;
973 static final int PAUSE_TIMEOUT_MSG = 9;
974 static final int IDLE_TIMEOUT_MSG = 10;
975 static final int IDLE_NOW_MSG = 11;
976 static final int SERVICE_TIMEOUT_MSG = 12;
977 static final int UPDATE_TIME_ZONE = 13;
978 static final int SHOW_UID_ERROR_MSG = 14;
979 static final int IM_FEELING_LUCKY_MSG = 15;
980 static final int LAUNCH_TIMEOUT_MSG = 16;
981 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 static final int RESUME_TOP_ACTIVITY_MSG = 19;
983 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700984 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700985 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800986 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987
988 AlertDialog mUidAlert;
989
990 final Handler mHandler = new Handler() {
991 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800992 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 //}
994
995 public void handleMessage(Message msg) {
996 switch (msg.what) {
997 case SHOW_ERROR_MSG: {
998 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 synchronized (ActivityManagerService.this) {
1000 ProcessRecord proc = (ProcessRecord)data.get("app");
1001 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001002 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 return;
1004 }
1005 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001006 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001007 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001008 d.show();
1009 proc.crashDialog = d;
1010 } else {
1011 // The device is asleep, so just pretend that the user
1012 // saw a crash dialog and hit "force quit".
1013 res.set(0);
1014 }
1015 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001016
1017 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } break;
1019 case SHOW_NOT_RESPONDING_MSG: {
1020 synchronized (ActivityManagerService.this) {
1021 HashMap data = (HashMap) msg.obj;
1022 ProcessRecord proc = (ProcessRecord)data.get("app");
1023 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001024 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 return;
1026 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001027
1028 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1029 null, null, 0, null, null, null,
1030 false, false, MY_PID, Process.SYSTEM_UID);
1031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1033 mContext, proc, (HistoryRecord)data.get("activity"));
1034 d.show();
1035 proc.anrDialog = d;
1036 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001037
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001038 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 } break;
1040 case SHOW_FACTORY_ERROR_MSG: {
1041 Dialog d = new FactoryErrorDialog(
1042 mContext, msg.getData().getCharSequence("msg"));
1043 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001044 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 } break;
1046 case UPDATE_CONFIGURATION_MSG: {
1047 final ContentResolver resolver = mContext.getContentResolver();
1048 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1049 } break;
1050 case GC_BACKGROUND_PROCESSES_MSG: {
1051 synchronized (ActivityManagerService.this) {
1052 performAppGcsIfAppropriateLocked();
1053 }
1054 } break;
1055 case WAIT_FOR_DEBUGGER_MSG: {
1056 synchronized (ActivityManagerService.this) {
1057 ProcessRecord app = (ProcessRecord)msg.obj;
1058 if (msg.arg1 != 0) {
1059 if (!app.waitedForDebugger) {
1060 Dialog d = new AppWaitingForDebuggerDialog(
1061 ActivityManagerService.this,
1062 mContext, app);
1063 app.waitDialog = d;
1064 app.waitedForDebugger = true;
1065 d.show();
1066 }
1067 } else {
1068 if (app.waitDialog != null) {
1069 app.waitDialog.dismiss();
1070 app.waitDialog = null;
1071 }
1072 }
1073 }
1074 } break;
1075 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001076 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 TAG, "Received BROADCAST_INTENT_MSG");
1078 processNextBroadcast(true);
1079 } break;
1080 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001081 if (mDidDexOpt) {
1082 mDidDexOpt = false;
1083 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1084 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1085 return;
1086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 broadcastTimeout();
1088 } break;
1089 case PAUSE_TIMEOUT_MSG: {
1090 IBinder token = (IBinder)msg.obj;
1091 // We don't at this point know if the activity is fullscreen,
1092 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001093 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 activityPaused(token, null, true);
1095 } break;
1096 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001097 if (mDidDexOpt) {
1098 mDidDexOpt = false;
1099 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1100 nmsg.obj = msg.obj;
1101 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1102 return;
1103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 // We don't at this point know if the activity is fullscreen,
1105 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001106 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001107 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001108 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 } break;
1110 case DESTROY_TIMEOUT_MSG: {
1111 IBinder token = (IBinder)msg.obj;
1112 // We don't at this point know if the activity is fullscreen,
1113 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001114 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 activityDestroyed(token);
1116 } break;
1117 case IDLE_NOW_MSG: {
1118 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001119 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 } break;
1121 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001122 if (mDidDexOpt) {
1123 mDidDexOpt = false;
1124 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1125 nmsg.obj = msg.obj;
1126 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1127 return;
1128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 serviceTimeout((ProcessRecord)msg.obj);
1130 } break;
1131 case UPDATE_TIME_ZONE: {
1132 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001133 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1134 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 if (r.thread != null) {
1136 try {
1137 r.thread.updateTimeZone();
1138 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001139 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 }
1141 }
1142 }
1143 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001144 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 case SHOW_UID_ERROR_MSG: {
1146 // XXX This is a temporary dialog, no need to localize.
1147 AlertDialog d = new BaseErrorDialog(mContext);
1148 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1149 d.setCancelable(false);
1150 d.setTitle("System UIDs Inconsistent");
1151 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1152 d.setButton("I'm Feeling Lucky",
1153 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1154 mUidAlert = d;
1155 d.show();
1156 } break;
1157 case IM_FEELING_LUCKY_MSG: {
1158 if (mUidAlert != null) {
1159 mUidAlert.dismiss();
1160 mUidAlert = null;
1161 }
1162 } break;
1163 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001164 if (mDidDexOpt) {
1165 mDidDexOpt = false;
1166 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1167 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1168 return;
1169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 synchronized (ActivityManagerService.this) {
1171 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001172 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 mLaunchingActivity.release();
1174 }
1175 }
1176 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 case RESUME_TOP_ACTIVITY_MSG: {
1178 synchronized (ActivityManagerService.this) {
1179 resumeTopActivityLocked(null);
1180 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001181 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001183 if (mDidDexOpt) {
1184 mDidDexOpt = false;
1185 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1186 nmsg.obj = msg.obj;
1187 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1188 return;
1189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 ProcessRecord app = (ProcessRecord)msg.obj;
1191 synchronized (ActivityManagerService.this) {
1192 processStartTimedOutLocked(app);
1193 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001194 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001195 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1196 synchronized (ActivityManagerService.this) {
1197 doPendingActivityLaunchesLocked(true);
1198 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001199 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001200 case KILL_APPLICATION_MSG: {
1201 synchronized (ActivityManagerService.this) {
1202 int uid = msg.arg1;
1203 boolean restart = (msg.arg2 == 1);
1204 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001205 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001206 }
1207 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001208 case FINALIZE_PENDING_INTENT_MSG: {
1209 ((PendingIntentRecord)msg.obj).completeFinalize();
1210 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 }
1212 }
1213 };
1214
1215 public static void setSystemProcess() {
1216 try {
1217 ActivityManagerService m = mSelf;
1218
1219 ServiceManager.addService("activity", m);
1220 ServiceManager.addService("meminfo", new MemBinder(m));
1221 if (MONITOR_CPU_USAGE) {
1222 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 ServiceManager.addService("permission", new PermissionController(m));
1225
1226 ApplicationInfo info =
1227 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001228 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001229 mSystemThread.installSystemApplicationInfo(info);
1230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 synchronized (mSelf) {
1232 ProcessRecord app = mSelf.newProcessRecordLocked(
1233 mSystemThread.getApplicationThread(), info,
1234 info.processName);
1235 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001236 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 app.maxAdj = SYSTEM_ADJ;
1238 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1239 synchronized (mSelf.mPidsSelfLocked) {
1240 mSelf.mPidsSelfLocked.put(app.pid, app);
1241 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001242 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 }
1244 } catch (PackageManager.NameNotFoundException e) {
1245 throw new RuntimeException(
1246 "Unable to find android system package", e);
1247 }
1248 }
1249
1250 public void setWindowManager(WindowManagerService wm) {
1251 mWindowManager = wm;
1252 }
1253
1254 public static final Context main(int factoryTest) {
1255 AThread thr = new AThread();
1256 thr.start();
1257
1258 synchronized (thr) {
1259 while (thr.mService == null) {
1260 try {
1261 thr.wait();
1262 } catch (InterruptedException e) {
1263 }
1264 }
1265 }
1266
1267 ActivityManagerService m = thr.mService;
1268 mSelf = m;
1269 ActivityThread at = ActivityThread.systemMain();
1270 mSystemThread = at;
1271 Context context = at.getSystemContext();
1272 m.mContext = context;
1273 m.mFactoryTest = factoryTest;
1274 PowerManager pm =
1275 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1276 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1277 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1278 m.mLaunchingActivity.setReferenceCounted(false);
1279
1280 m.mBatteryStatsService.publish(context);
1281 m.mUsageStatsService.publish(context);
1282
1283 synchronized (thr) {
1284 thr.mReady = true;
1285 thr.notifyAll();
1286 }
1287
1288 m.startRunning(null, null, null, null);
1289
1290 return context;
1291 }
1292
1293 public static ActivityManagerService self() {
1294 return mSelf;
1295 }
1296
1297 static class AThread extends Thread {
1298 ActivityManagerService mService;
1299 boolean mReady = false;
1300
1301 public AThread() {
1302 super("ActivityManager");
1303 }
1304
1305 public void run() {
1306 Looper.prepare();
1307
1308 android.os.Process.setThreadPriority(
1309 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1310
1311 ActivityManagerService m = new ActivityManagerService();
1312
1313 synchronized (this) {
1314 mService = m;
1315 notifyAll();
1316 }
1317
1318 synchronized (this) {
1319 while (!mReady) {
1320 try {
1321 wait();
1322 } catch (InterruptedException e) {
1323 }
1324 }
1325 }
1326
1327 Looper.loop();
1328 }
1329 }
1330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 static class MemBinder extends Binder {
1332 ActivityManagerService mActivityManagerService;
1333 MemBinder(ActivityManagerService activityManagerService) {
1334 mActivityManagerService = activityManagerService;
1335 }
1336
1337 @Override
1338 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1339 ActivityManagerService service = mActivityManagerService;
1340 ArrayList<ProcessRecord> procs;
1341 synchronized (mActivityManagerService) {
1342 if (args != null && args.length > 0
1343 && args[0].charAt(0) != '-') {
1344 procs = new ArrayList<ProcessRecord>();
1345 int pid = -1;
1346 try {
1347 pid = Integer.parseInt(args[0]);
1348 } catch (NumberFormatException e) {
1349
1350 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001351 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1352 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 if (proc.pid == pid) {
1354 procs.add(proc);
1355 } else if (proc.processName.equals(args[0])) {
1356 procs.add(proc);
1357 }
1358 }
1359 if (procs.size() <= 0) {
1360 pw.println("No process found for: " + args[0]);
1361 return;
1362 }
1363 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001364 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 }
1366 }
1367 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1368 }
1369 }
1370
1371 static class CpuBinder extends Binder {
1372 ActivityManagerService mActivityManagerService;
1373 CpuBinder(ActivityManagerService activityManagerService) {
1374 mActivityManagerService = activityManagerService;
1375 }
1376
1377 @Override
1378 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1379 synchronized (mActivityManagerService.mProcessStatsThread) {
1380 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1381 }
1382 }
1383 }
1384
1385 private ActivityManagerService() {
1386 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1387 if (v != null && Integer.getInteger(v) != 0) {
1388 mSimpleProcessManagement = true;
1389 }
1390 v = System.getenv("ANDROID_DEBUG_APP");
1391 if (v != null) {
1392 mSimpleProcessManagement = true;
1393 }
1394
Joe Onorato8a9b2202010-02-26 18:56:32 -08001395 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 File dataDir = Environment.getDataDirectory();
1398 File systemDir = new File(dataDir, "system");
1399 systemDir.mkdirs();
1400 mBatteryStatsService = new BatteryStatsService(new File(
1401 systemDir, "batterystats.bin").toString());
1402 mBatteryStatsService.getActiveStatistics().readLocked();
1403 mBatteryStatsService.getActiveStatistics().writeLocked();
1404
1405 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001406 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407
Jack Palevichb90d28c2009-07-22 15:35:24 -07001408 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1409 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1410
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001411 mConfiguration.setToDefaults();
1412 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 mProcessStats.init();
1414
1415 // Add ourself to the Watchdog monitors.
1416 Watchdog.getInstance().addMonitor(this);
1417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 mProcessStatsThread = new Thread("ProcessStats") {
1419 public void run() {
1420 while (true) {
1421 try {
1422 try {
1423 synchronized(this) {
1424 final long now = SystemClock.uptimeMillis();
1425 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1426 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001427 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 // + ", write delay=" + nextWriteDelay);
1429 if (nextWriteDelay < nextCpuDelay) {
1430 nextCpuDelay = nextWriteDelay;
1431 }
1432 if (nextCpuDelay > 0) {
1433 this.wait(nextCpuDelay);
1434 }
1435 }
1436 } catch (InterruptedException e) {
1437 }
1438
1439 updateCpuStatsNow();
1440 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001441 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 }
1443 }
1444 }
1445 };
1446 mProcessStatsThread.start();
1447 }
1448
1449 @Override
1450 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1451 throws RemoteException {
1452 try {
1453 return super.onTransact(code, data, reply, flags);
1454 } catch (RuntimeException e) {
1455 // The activity manager only throws security exceptions, so let's
1456 // log all others.
1457 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001458 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 }
1460 throw e;
1461 }
1462 }
1463
1464 void updateCpuStats() {
1465 synchronized (mProcessStatsThread) {
1466 final long now = SystemClock.uptimeMillis();
1467 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1468 mProcessStatsThread.notify();
1469 }
1470 }
1471 }
1472
1473 void updateCpuStatsNow() {
1474 synchronized (mProcessStatsThread) {
1475 final long now = SystemClock.uptimeMillis();
1476 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 if (MONITOR_CPU_USAGE &&
1479 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1480 mLastCpuTime = now;
1481 haveNewCpuStats = true;
1482 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001483 //Slog.i(TAG, mProcessStats.printCurrentState());
1484 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 // + mProcessStats.getTotalCpuPercent() + "%");
1486
Joe Onorato8a9b2202010-02-26 18:56:32 -08001487 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 if ("true".equals(SystemProperties.get("events.cpu"))) {
1489 int user = mProcessStats.getLastUserTime();
1490 int system = mProcessStats.getLastSystemTime();
1491 int iowait = mProcessStats.getLastIoWaitTime();
1492 int irq = mProcessStats.getLastIrqTime();
1493 int softIrq = mProcessStats.getLastSoftIrqTime();
1494 int idle = mProcessStats.getLastIdleTime();
1495
1496 int total = user + system + iowait + irq + softIrq + idle;
1497 if (total == 0) total = 1;
1498
Doug Zongker2bec3d42009-12-04 12:52:44 -08001499 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 ((user+system+iowait+irq+softIrq) * 100) / total,
1501 (user * 100) / total,
1502 (system * 100) / total,
1503 (iowait * 100) / total,
1504 (irq * 100) / total,
1505 (softIrq * 100) / total);
1506 }
1507 }
1508
Amith Yamasanie43530a2009-08-21 13:11:37 -07001509 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001510 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001511 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 synchronized(mPidsSelfLocked) {
1513 if (haveNewCpuStats) {
1514 if (mBatteryStatsService.isOnBattery()) {
1515 final int N = mProcessStats.countWorkingStats();
1516 for (int i=0; i<N; i++) {
1517 ProcessStats.Stats st
1518 = mProcessStats.getWorkingStats(i);
1519 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1520 if (pr != null) {
1521 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1522 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001523 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001524 } else {
1525 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001526 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001527 if (ps != null) {
1528 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001529 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 }
1532 }
1533 }
1534 }
1535 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1538 mLastWriteTime = now;
1539 mBatteryStatsService.getActiveStatistics().writeLocked();
1540 }
1541 }
1542 }
1543 }
1544
1545 /**
1546 * Initialize the application bind args. These are passed to each
1547 * process when the bindApplication() IPC is sent to the process. They're
1548 * lazily setup to make sure the services are running when they're asked for.
1549 */
1550 private HashMap<String, IBinder> getCommonServicesLocked() {
1551 if (mAppBindArgs == null) {
1552 mAppBindArgs = new HashMap<String, IBinder>();
1553
1554 // Setup the application init args
1555 mAppBindArgs.put("package", ServiceManager.getService("package"));
1556 mAppBindArgs.put("window", ServiceManager.getService("window"));
1557 mAppBindArgs.put(Context.ALARM_SERVICE,
1558 ServiceManager.getService(Context.ALARM_SERVICE));
1559 }
1560 return mAppBindArgs;
1561 }
1562
1563 private final void setFocusedActivityLocked(HistoryRecord r) {
1564 if (mFocusedActivity != r) {
1565 mFocusedActivity = r;
1566 mWindowManager.setFocusedApp(r, true);
1567 }
1568 }
1569
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001570 private final void updateLruProcessLocked(ProcessRecord app,
1571 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001573 int lrui = mLruProcesses.indexOf(app);
1574 if (lrui >= 0) mLruProcesses.remove(lrui);
1575
1576 int i = mLruProcesses.size()-1;
1577 int skipTop = 0;
1578
1579 // compute the new weight for this process.
1580 if (updateActivityTime) {
1581 app.lastActivityTime = SystemClock.uptimeMillis();
1582 }
1583 if (app.activities.size() > 0) {
1584 // If this process has activities, we more strongly want to keep
1585 // it around.
1586 app.lruWeight = app.lastActivityTime;
1587 } else if (app.pubProviders.size() > 0) {
1588 // If this process contains content providers, we want to keep
1589 // it a little more strongly.
1590 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1591 // Also don't let it kick out the first few "real" hidden processes.
1592 skipTop = MIN_HIDDEN_APPS;
1593 } else {
1594 // If this process doesn't have activities, we less strongly
1595 // want to keep it around, and generally want to avoid getting
1596 // in front of any very recently used activities.
1597 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1598 // Also don't let it kick out the first few "real" hidden processes.
1599 skipTop = MIN_HIDDEN_APPS;
1600 }
1601 while (i >= 0) {
1602 ProcessRecord p = mLruProcesses.get(i);
1603 // If this app shouldn't be in front of the first N background
1604 // apps, then skip over that many that are currently hidden.
1605 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1606 skipTop--;
1607 }
1608 if (p.lruWeight <= app.lruWeight){
1609 mLruProcesses.add(i+1, app);
1610 break;
1611 }
1612 i--;
1613 }
1614 if (i < 0) {
1615 mLruProcesses.add(0, app);
1616 }
1617
Joe Onorato8a9b2202010-02-26 18:56:32 -08001618 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 if (oomAdj) {
1620 updateOomAdjLocked();
1621 }
1622 }
1623
1624 private final boolean updateLRUListLocked(HistoryRecord r) {
1625 final boolean hadit = mLRUActivities.remove(r);
1626 mLRUActivities.add(r);
1627 return hadit;
1628 }
1629
1630 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1631 int i = mHistory.size()-1;
1632 while (i >= 0) {
1633 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1634 if (!r.finishing && r != notTop) {
1635 return r;
1636 }
1637 i--;
1638 }
1639 return null;
1640 }
1641
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001642 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1643 int i = mHistory.size()-1;
1644 while (i >= 0) {
1645 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1646 if (!r.finishing && !r.delayedResume && r != notTop) {
1647 return r;
1648 }
1649 i--;
1650 }
1651 return null;
1652 }
1653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 /**
1655 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001656 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 *
1658 * @param token If non-null, any history records matching this token will be skipped.
1659 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1660 *
1661 * @return Returns the HistoryRecord of the next activity on the stack.
1662 */
1663 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1664 int i = mHistory.size()-1;
1665 while (i >= 0) {
1666 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1667 // Note: the taskId check depends on real taskId fields being non-zero
1668 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1669 return r;
1670 }
1671 i--;
1672 }
1673 return null;
1674 }
1675
1676 private final ProcessRecord getProcessRecordLocked(
1677 String processName, int uid) {
1678 if (uid == Process.SYSTEM_UID) {
1679 // The system gets to run in any process. If there are multiple
1680 // processes with the same uid, just pick the first (this
1681 // should never happen).
1682 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1683 processName);
1684 return procs != null ? procs.valueAt(0) : null;
1685 }
1686 ProcessRecord proc = mProcessNames.get(processName, uid);
1687 return proc;
1688 }
1689
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001690 private void ensurePackageDexOpt(String packageName) {
1691 IPackageManager pm = ActivityThread.getPackageManager();
1692 try {
1693 if (pm.performDexOpt(packageName)) {
1694 mDidDexOpt = true;
1695 }
1696 } catch (RemoteException e) {
1697 }
1698 }
1699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 private boolean isNextTransitionForward() {
1701 int transit = mWindowManager.getPendingAppTransition();
1702 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1703 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1704 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1705 }
1706
1707 private final boolean realStartActivityLocked(HistoryRecord r,
1708 ProcessRecord app, boolean andResume, boolean checkConfig)
1709 throws RemoteException {
1710
1711 r.startFreezingScreenLocked(app, 0);
1712 mWindowManager.setAppVisibility(r, true);
1713
1714 // Have the window manager re-evaluate the orientation of
1715 // the screen based on the new activity order. Note that
1716 // as a result of this, it can call back into the activity
1717 // manager with a new orientation. We don't care about that,
1718 // because the activity is not currently running so we are
1719 // just restarting it anyway.
1720 if (checkConfig) {
1721 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001722 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 r.mayFreezeScreenLocked(app) ? r : null);
1724 updateConfigurationLocked(config, r);
1725 }
1726
1727 r.app = app;
1728
Joe Onorato8a9b2202010-02-26 18:56:32 -08001729 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730
1731 int idx = app.activities.indexOf(r);
1732 if (idx < 0) {
1733 app.activities.add(r);
1734 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001735 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736
1737 try {
1738 if (app.thread == null) {
1739 throw new RemoteException();
1740 }
1741 List<ResultInfo> results = null;
1742 List<Intent> newIntents = null;
1743 if (andResume) {
1744 results = r.results;
1745 newIntents = r.newIntents;
1746 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001747 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 + " icicle=" + r.icicle
1749 + " with results=" + results + " newIntents=" + newIntents
1750 + " andResume=" + andResume);
1751 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001752 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 System.identityHashCode(r),
1754 r.task.taskId, r.shortComponentName);
1755 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001756 if (r.isHomeActivity) {
1757 mHomeProcess = app;
1758 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001759 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001761 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 r.info, r.icicle, results, newIntents, !andResume,
1763 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 } catch (RemoteException e) {
1765 if (r.launchFailed) {
1766 // This is the second time we failed -- finish activity
1767 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001768 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 + r.intent.getComponent().flattenToShortString()
1770 + ", giving up", e);
1771 appDiedLocked(app, app.pid, app.thread);
1772 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1773 "2nd-crash");
1774 return false;
1775 }
1776
1777 // This is the first time we failed -- restart process and
1778 // retry.
1779 app.activities.remove(r);
1780 throw e;
1781 }
1782
1783 r.launchFailed = false;
1784 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001785 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 + " being launched, but already in LRU list");
1787 }
1788
1789 if (andResume) {
1790 // As part of the process of launching, ActivityThread also performs
1791 // a resume.
1792 r.state = ActivityState.RESUMED;
1793 r.icicle = null;
1794 r.haveState = false;
1795 r.stopped = false;
1796 mResumedActivity = r;
1797 r.task.touchActiveTime();
1798 completeResumeLocked(r);
1799 pauseIfSleepingLocked();
1800 } else {
1801 // This activity is not starting in the resumed state... which
1802 // should look like we asked it to pause+stop (but remain visible),
1803 // and it has done so and reported back the current icicle and
1804 // other state.
1805 r.state = ActivityState.STOPPED;
1806 r.stopped = true;
1807 }
1808
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001809 // Launch the new version setup screen if needed. We do this -after-
1810 // launching the initial activity (that is, home), so that it can have
1811 // a chance to initialize itself while in the background, making the
1812 // switch back to it faster and look better.
1813 startSetupActivityLocked();
1814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 return true;
1816 }
1817
1818 private final void startSpecificActivityLocked(HistoryRecord r,
1819 boolean andResume, boolean checkConfig) {
1820 // Is this activity's application already running?
1821 ProcessRecord app = getProcessRecordLocked(r.processName,
1822 r.info.applicationInfo.uid);
1823
1824 if (r.startTime == 0) {
1825 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001826 if (mInitialStartTime == 0) {
1827 mInitialStartTime = r.startTime;
1828 }
1829 } else if (mInitialStartTime == 0) {
1830 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 }
1832
1833 if (app != null && app.thread != null) {
1834 try {
1835 realStartActivityLocked(r, app, andResume, checkConfig);
1836 return;
1837 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001838 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 + r.intent.getComponent().flattenToShortString(), e);
1840 }
1841
1842 // If a dead object exception was thrown -- fall through to
1843 // restart the application.
1844 }
1845
1846 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001847 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 }
1849
1850 private final ProcessRecord startProcessLocked(String processName,
1851 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001852 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1854 // We don't have to do anything more if:
1855 // (1) There is an existing application record; and
1856 // (2) The caller doesn't think it is dead, OR there is no thread
1857 // object attached to it so we know it couldn't have crashed; and
1858 // (3) There is a pid assigned to it, so it is either starting or
1859 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001860 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 + " app=" + app + " knownToBeDead=" + knownToBeDead
1862 + " thread=" + (app != null ? app.thread : null)
1863 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001864 if (app != null && app.pid > 0) {
1865 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001866 // We already have the app running, or are waiting for it to
1867 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001868 return app;
1869 } else {
1870 // An application record is attached to a previous process,
1871 // clean it up now.
1872 handleAppDiedLocked(app, true);
1873 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 String hostingNameStr = hostingName != null
1877 ? hostingName.flattenToShortString() : null;
1878
1879 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1880 // If we are in the background, then check to see if this process
1881 // is bad. If so, we will just silently fail.
1882 if (mBadProcesses.get(info.processName, info.uid) != null) {
1883 return null;
1884 }
1885 } else {
1886 // When the user is explicitly starting a process, then clear its
1887 // crash count so that we won't make it bad until they see at
1888 // least one crash dialog again, and make the process good again
1889 // if it had been bad.
1890 mProcessCrashTimes.remove(info.processName, info.uid);
1891 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001892 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 info.processName);
1894 mBadProcesses.remove(info.processName, info.uid);
1895 if (app != null) {
1896 app.bad = false;
1897 }
1898 }
1899 }
1900
1901 if (app == null) {
1902 app = newProcessRecordLocked(null, info, processName);
1903 mProcessNames.put(processName, info.uid, app);
1904 } else {
1905 // If this is a new package in the process, add the package to the list
1906 app.addPackage(info.packageName);
1907 }
1908
1909 // If the system is not ready yet, then hold off on starting this
1910 // process until it is.
1911 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001912 && !isAllowedWhileBooting(info)
1913 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 if (!mProcessesOnHold.contains(app)) {
1915 mProcessesOnHold.add(app);
1916 }
1917 return app;
1918 }
1919
1920 startProcessLocked(app, hostingType, hostingNameStr);
1921 return (app.pid != 0) ? app : null;
1922 }
1923
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001924 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1925 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1926 }
1927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001928 private final void startProcessLocked(ProcessRecord app,
1929 String hostingType, String hostingNameStr) {
1930 if (app.pid > 0 && app.pid != MY_PID) {
1931 synchronized (mPidsSelfLocked) {
1932 mPidsSelfLocked.remove(app.pid);
1933 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1934 }
1935 app.pid = 0;
1936 }
1937
1938 mProcessesOnHold.remove(app);
1939
1940 updateCpuStats();
1941
1942 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1943 mProcDeaths[0] = 0;
1944
1945 try {
1946 int uid = app.info.uid;
1947 int[] gids = null;
1948 try {
1949 gids = mContext.getPackageManager().getPackageGids(
1950 app.info.packageName);
1951 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001952 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001953 }
1954 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1955 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1956 && mTopComponent != null
1957 && app.processName.equals(mTopComponent.getPackageName())) {
1958 uid = 0;
1959 }
1960 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1961 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1962 uid = 0;
1963 }
1964 }
1965 int debugFlags = 0;
1966 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1967 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1968 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001969 // Run the app in safe mode if its manifest requests so or the
1970 // system is booted in safe mode.
1971 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1972 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001973 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1976 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1977 }
1978 if ("1".equals(SystemProperties.get("debug.assert"))) {
1979 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1980 }
1981 int pid = Process.start("android.app.ActivityThread",
1982 mSimpleProcessManagement ? app.processName : null, uid, uid,
1983 gids, debugFlags, null);
1984 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1985 synchronized (bs) {
1986 if (bs.isOnBattery()) {
1987 app.batteryStats.incStartsLocked();
1988 }
1989 }
1990
Doug Zongker2bec3d42009-12-04 12:52:44 -08001991 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001992 app.processName, hostingType,
1993 hostingNameStr != null ? hostingNameStr : "");
1994
1995 if (app.persistent) {
1996 Watchdog.getInstance().processStarted(app, app.processName, pid);
1997 }
1998
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001999 StringBuilder buf = mStringBuilder;
2000 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 buf.append("Start proc ");
2002 buf.append(app.processName);
2003 buf.append(" for ");
2004 buf.append(hostingType);
2005 if (hostingNameStr != null) {
2006 buf.append(" ");
2007 buf.append(hostingNameStr);
2008 }
2009 buf.append(": pid=");
2010 buf.append(pid);
2011 buf.append(" uid=");
2012 buf.append(uid);
2013 buf.append(" gids={");
2014 if (gids != null) {
2015 for (int gi=0; gi<gids.length; gi++) {
2016 if (gi != 0) buf.append(", ");
2017 buf.append(gids[gi]);
2018
2019 }
2020 }
2021 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002022 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002023 if (pid == 0 || pid == MY_PID) {
2024 // Processes are being emulated with threads.
2025 app.pid = MY_PID;
2026 app.removed = false;
2027 mStartingProcesses.add(app);
2028 } else if (pid > 0) {
2029 app.pid = pid;
2030 app.removed = false;
2031 synchronized (mPidsSelfLocked) {
2032 this.mPidsSelfLocked.put(pid, app);
2033 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2034 msg.obj = app;
2035 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2036 }
2037 } else {
2038 app.pid = 0;
2039 RuntimeException e = new RuntimeException(
2040 "Failure starting process " + app.processName
2041 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002042 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 }
2044 } catch (RuntimeException e) {
2045 // XXX do better error recovery.
2046 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002047 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 }
2049 }
2050
2051 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2052 if (mPausingActivity != null) {
2053 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002054 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 + mPausingActivity, e);
2056 }
2057 HistoryRecord prev = mResumedActivity;
2058 if (prev == null) {
2059 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002060 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 resumeTopActivityLocked(null);
2062 return;
2063 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002064 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 mResumedActivity = null;
2066 mPausingActivity = prev;
2067 mLastPausedActivity = prev;
2068 prev.state = ActivityState.PAUSING;
2069 prev.task.touchActiveTime();
2070
2071 updateCpuStats();
2072
2073 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002074 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002076 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 System.identityHashCode(prev),
2078 prev.shortComponentName);
2079 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2080 prev.configChangeFlags);
2081 updateUsageStats(prev, false);
2082 } catch (Exception e) {
2083 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002084 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 mPausingActivity = null;
2086 mLastPausedActivity = null;
2087 }
2088 } else {
2089 mPausingActivity = null;
2090 mLastPausedActivity = null;
2091 }
2092
2093 // If we are not going to sleep, we want to ensure the device is
2094 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002095 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 mLaunchingActivity.acquire();
2097 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2098 // To be safe, don't allow the wake lock to be held for too long.
2099 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2100 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2101 }
2102 }
2103
2104
2105 if (mPausingActivity != null) {
2106 // Have the window manager pause its key dispatching until the new
2107 // activity has started. If we're pausing the activity just because
2108 // the screen is being turned off and the UI is sleeping, don't interrupt
2109 // key dispatch; the same activity will pick it up again on wakeup.
2110 if (!uiSleeping) {
2111 prev.pauseKeyDispatchingLocked();
2112 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002113 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114 }
2115
2116 // Schedule a pause timeout in case the app doesn't respond.
2117 // We don't give it much time because this directly impacts the
2118 // responsiveness seen by the user.
2119 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2120 msg.obj = prev;
2121 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002122 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 } else {
2124 // This activity failed to schedule the
2125 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002126 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 resumeTopActivityLocked(null);
2128 }
2129 }
2130
2131 private final void completePauseLocked() {
2132 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002133 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002134
2135 if (prev != null) {
2136 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002137 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2139 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002140 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 if (prev.waitingVisible) {
2142 prev.waitingVisible = false;
2143 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002144 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145 TAG, "Complete pause, no longer waiting: " + prev);
2146 }
2147 if (prev.configDestroy) {
2148 // The previous is being paused because the configuration
2149 // is changing, which means it is actually stopping...
2150 // To juggle the fact that we are also starting a new
2151 // instance right now, we need to first completely stop
2152 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002153 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 destroyActivityLocked(prev, true);
2155 } else {
2156 mStoppingActivities.add(prev);
2157 if (mStoppingActivities.size() > 3) {
2158 // If we already have a few activities waiting to stop,
2159 // then give up on things going idle and start clearing
2160 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002161 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 Message msg = Message.obtain();
2163 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2164 mHandler.sendMessage(msg);
2165 }
2166 }
2167 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002168 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002169 prev = null;
2170 }
2171 mPausingActivity = null;
2172 }
2173
Dianne Hackborn55280a92009-05-07 15:53:46 -07002174 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 resumeTopActivityLocked(prev);
2176 } else {
2177 if (mGoingToSleep.isHeld()) {
2178 mGoingToSleep.release();
2179 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002180 if (mShuttingDown) {
2181 notifyAll();
2182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 }
2184
2185 if (prev != null) {
2186 prev.resumeKeyDispatchingLocked();
2187 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002188
2189 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2190 long diff = 0;
2191 synchronized (mProcessStatsThread) {
2192 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2193 }
2194 if (diff > 0) {
2195 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2196 synchronized (bsi) {
2197 BatteryStatsImpl.Uid.Proc ps =
2198 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2199 prev.info.packageName);
2200 if (ps != null) {
2201 ps.addForegroundTimeLocked(diff);
2202 }
2203 }
2204 }
2205 }
2206 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 }
2208
2209 /**
2210 * Once we know that we have asked an application to put an activity in
2211 * the resumed state (either by launching it or explicitly telling it),
2212 * this function updates the rest of our state to match that fact.
2213 */
2214 private final void completeResumeLocked(HistoryRecord next) {
2215 next.idle = false;
2216 next.results = null;
2217 next.newIntents = null;
2218
2219 // schedule an idle timeout in case the app doesn't do it for us.
2220 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2221 msg.obj = next;
2222 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2223
2224 if (false) {
2225 // The activity was never told to pause, so just keep
2226 // things going as-is. To maintain our own state,
2227 // we need to emulate it coming back and saying it is
2228 // idle.
2229 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2230 msg.obj = next;
2231 mHandler.sendMessage(msg);
2232 }
2233
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002234 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 next.thumbnail = null;
2237 setFocusedActivityLocked(next);
2238 next.resumeKeyDispatchingLocked();
2239 ensureActivitiesVisibleLocked(null, 0);
2240 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002241 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002242
2243 // Mark the point when the activity is resuming
2244 // TODO: To be more accurate, the mark should be before the onCreate,
2245 // not after the onResume. But for subsequent starts, onResume is fine.
2246 if (next.app != null) {
2247 synchronized (mProcessStatsThread) {
2248 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2249 }
2250 } else {
2251 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 }
2254
2255 /**
2256 * Make sure that all activities that need to be visible (that is, they
2257 * currently can be seen by the user) actually are.
2258 */
2259 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2260 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002261 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262 TAG, "ensureActivitiesVisible behind " + top
2263 + " configChanges=0x" + Integer.toHexString(configChanges));
2264
2265 // If the top activity is not fullscreen, then we need to
2266 // make sure any activities under it are now visible.
2267 final int count = mHistory.size();
2268 int i = count-1;
2269 while (mHistory.get(i) != top) {
2270 i--;
2271 }
2272 HistoryRecord r;
2273 boolean behindFullscreen = false;
2274 for (; i>=0; i--) {
2275 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002276 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 TAG, "Make visible? " + r + " finishing=" + r.finishing
2278 + " state=" + r.state);
2279 if (r.finishing) {
2280 continue;
2281 }
2282
2283 final boolean doThisProcess = onlyThisProcess == null
2284 || onlyThisProcess.equals(r.processName);
2285
2286 // First: if this is not the current activity being started, make
2287 // sure it matches the current configuration.
2288 if (r != starting && doThisProcess) {
2289 ensureActivityConfigurationLocked(r, 0);
2290 }
2291
2292 if (r.app == null || r.app.thread == null) {
2293 if (onlyThisProcess == null
2294 || onlyThisProcess.equals(r.processName)) {
2295 // This activity needs to be visible, but isn't even
2296 // running... get it started, but don't resume it
2297 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002298 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002299 TAG, "Start and freeze screen for " + r);
2300 if (r != starting) {
2301 r.startFreezingScreenLocked(r.app, configChanges);
2302 }
2303 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002304 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 TAG, "Starting and making visible: " + r);
2306 mWindowManager.setAppVisibility(r, true);
2307 }
2308 if (r != starting) {
2309 startSpecificActivityLocked(r, false, false);
2310 }
2311 }
2312
2313 } else if (r.visible) {
2314 // If this activity is already visible, then there is nothing
2315 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002316 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 TAG, "Skipping: already visible at " + r);
2318 r.stopFreezingScreenLocked(false);
2319
2320 } else if (onlyThisProcess == null) {
2321 // This activity is not currently visible, but is running.
2322 // Tell it to become visible.
2323 r.visible = true;
2324 if (r.state != ActivityState.RESUMED && r != starting) {
2325 // If this activity is paused, tell it
2326 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002327 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 TAG, "Making visible and scheduling visibility: " + r);
2329 try {
2330 mWindowManager.setAppVisibility(r, true);
2331 r.app.thread.scheduleWindowVisibility(r, true);
2332 r.stopFreezingScreenLocked(false);
2333 } catch (Exception e) {
2334 // Just skip on any failure; we'll make it
2335 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002336 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 + r.intent.getComponent(), e);
2338 }
2339 }
2340 }
2341
2342 // Aggregate current change flags.
2343 configChanges |= r.configChangeFlags;
2344
2345 if (r.fullscreen) {
2346 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002347 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 TAG, "Stopping: fullscreen at " + r);
2349 behindFullscreen = true;
2350 i--;
2351 break;
2352 }
2353 }
2354
2355 // Now for any activities that aren't visible to the user, make
2356 // sure they no longer are keeping the screen frozen.
2357 while (i >= 0) {
2358 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002359 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2361 + " state=" + r.state
2362 + " behindFullscreen=" + behindFullscreen);
2363 if (!r.finishing) {
2364 if (behindFullscreen) {
2365 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002366 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 TAG, "Making invisible: " + r);
2368 r.visible = false;
2369 try {
2370 mWindowManager.setAppVisibility(r, false);
2371 if ((r.state == ActivityState.STOPPING
2372 || r.state == ActivityState.STOPPED)
2373 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002374 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 TAG, "Scheduling invisibility: " + r);
2376 r.app.thread.scheduleWindowVisibility(r, false);
2377 }
2378 } catch (Exception e) {
2379 // Just skip on any failure; we'll make it
2380 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002381 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002382 + r.intent.getComponent(), e);
2383 }
2384 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002385 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002386 TAG, "Already invisible: " + r);
2387 }
2388 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002389 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 TAG, "Now behindFullscreen: " + r);
2391 behindFullscreen = true;
2392 }
2393 }
2394 i--;
2395 }
2396 }
2397
2398 /**
2399 * Version of ensureActivitiesVisible that can easily be called anywhere.
2400 */
2401 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2402 int configChanges) {
2403 HistoryRecord r = topRunningActivityLocked(null);
2404 if (r != null) {
2405 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2406 }
2407 }
2408
2409 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2410 if (resumed) {
2411 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2412 } else {
2413 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2414 }
2415 }
2416
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002417 private boolean startHomeActivityLocked() {
2418 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2419 && mTopAction == null) {
2420 // We are running in factory test mode, but unable to find
2421 // the factory test app, so just sit around displaying the
2422 // error message and don't try to start anything.
2423 return false;
2424 }
2425 Intent intent = new Intent(
2426 mTopAction,
2427 mTopData != null ? Uri.parse(mTopData) : null);
2428 intent.setComponent(mTopComponent);
2429 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2430 intent.addCategory(Intent.CATEGORY_HOME);
2431 }
2432 ActivityInfo aInfo =
2433 intent.resolveActivityInfo(mContext.getPackageManager(),
2434 STOCK_PM_FLAGS);
2435 if (aInfo != null) {
2436 intent.setComponent(new ComponentName(
2437 aInfo.applicationInfo.packageName, aInfo.name));
2438 // Don't do this if the home app is currently being
2439 // instrumented.
2440 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2441 aInfo.applicationInfo.uid);
2442 if (app == null || app.instrumentationClass == null) {
2443 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2444 startActivityLocked(null, intent, null, null, 0, aInfo,
2445 null, null, 0, 0, 0, false, false);
2446 }
2447 }
2448
2449
2450 return true;
2451 }
2452
2453 /**
2454 * Starts the "new version setup screen" if appropriate.
2455 */
2456 private void startSetupActivityLocked() {
2457 // Only do this once per boot.
2458 if (mCheckedForSetup) {
2459 return;
2460 }
2461
2462 // We will show this screen if the current one is a different
2463 // version than the last one shown, and we are not running in
2464 // low-level factory test mode.
2465 final ContentResolver resolver = mContext.getContentResolver();
2466 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2467 Settings.Secure.getInt(resolver,
2468 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2469 mCheckedForSetup = true;
2470
2471 // See if we should be showing the platform update setup UI.
2472 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2473 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2474 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2475
2476 // We don't allow third party apps to replace this.
2477 ResolveInfo ri = null;
2478 for (int i=0; ris != null && i<ris.size(); i++) {
2479 if ((ris.get(i).activityInfo.applicationInfo.flags
2480 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2481 ri = ris.get(i);
2482 break;
2483 }
2484 }
2485
2486 if (ri != null) {
2487 String vers = ri.activityInfo.metaData != null
2488 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2489 : null;
2490 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2491 vers = ri.activityInfo.applicationInfo.metaData.getString(
2492 Intent.METADATA_SETUP_VERSION);
2493 }
2494 String lastVers = Settings.Secure.getString(
2495 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2496 if (vers != null && !vers.equals(lastVers)) {
2497 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2498 intent.setComponent(new ComponentName(
2499 ri.activityInfo.packageName, ri.activityInfo.name));
2500 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2501 null, null, 0, 0, 0, false, false);
2502 }
2503 }
2504 }
2505 }
2506
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002507 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002508 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002509
2510 final int identHash = System.identityHashCode(r);
2511 updateUsageStats(r, true);
2512
2513 int i = mWatchers.beginBroadcast();
2514 while (i > 0) {
2515 i--;
2516 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2517 if (w != null) {
2518 try {
2519 w.activityResuming(identHash);
2520 } catch (RemoteException e) {
2521 }
2522 }
2523 }
2524 mWatchers.finishBroadcast();
2525 }
2526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 /**
2528 * Ensure that the top activity in the stack is resumed.
2529 *
2530 * @param prev The previously resumed activity, for when in the process
2531 * of pausing; can be null to call from elsewhere.
2532 *
2533 * @return Returns true if something is being resumed, or false if
2534 * nothing happened.
2535 */
2536 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2537 // Find the first activity that is not finishing.
2538 HistoryRecord next = topRunningActivityLocked(null);
2539
2540 // Remember how we'll process this pause/resume situation, and ensure
2541 // that the state is reset however we wind up proceeding.
2542 final boolean userLeaving = mUserLeaving;
2543 mUserLeaving = false;
2544
2545 if (next == null) {
2546 // There are no more activities! Let's just start up the
2547 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002548 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002549 }
2550
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002551 next.delayedResume = false;
2552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 // If the top activity is the resumed one, nothing to do.
2554 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2555 // Make sure we have executed any pending transitions, since there
2556 // should be nothing left to do at this point.
2557 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002558 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002559 return false;
2560 }
2561
2562 // If we are sleeping, and there is no resumed activity, and the top
2563 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002564 if ((mSleeping || mShuttingDown)
2565 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 // Make sure we have executed any pending transitions, since there
2567 // should be nothing left to do at this point.
2568 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002569 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 return false;
2571 }
2572
2573 // The activity may be waiting for stop, but that is no longer
2574 // appropriate for it.
2575 mStoppingActivities.remove(next);
2576 mWaitingVisibleActivities.remove(next);
2577
Joe Onorato8a9b2202010-02-26 18:56:32 -08002578 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579
2580 // If we are currently pausing an activity, then don't do anything
2581 // until that is done.
2582 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002583 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 return false;
2585 }
2586
2587 // We need to start pausing the current activity so the top one
2588 // can be resumed...
2589 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002590 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 startPausingLocked(userLeaving, false);
2592 return true;
2593 }
2594
2595 if (prev != null && prev != next) {
2596 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2597 prev.waitingVisible = true;
2598 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002599 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 TAG, "Resuming top, waiting visible to hide: " + prev);
2601 } else {
2602 // The next activity is already visible, so hide the previous
2603 // activity's windows right now so we can show the new one ASAP.
2604 // We only do this if the previous is finishing, which should mean
2605 // it is on top of the one being resumed so hiding it quickly
2606 // is good. Otherwise, we want to do the normal route of allowing
2607 // the resumed activity to be shown so we can decide if the
2608 // previous should actually be hidden depending on whether the
2609 // new one is found to be full-screen or not.
2610 if (prev.finishing) {
2611 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002612 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 + prev + ", waitingVisible="
2614 + (prev != null ? prev.waitingVisible : null)
2615 + ", nowVisible=" + next.nowVisible);
2616 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002617 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 + prev + ", waitingVisible="
2619 + (prev != null ? prev.waitingVisible : null)
2620 + ", nowVisible=" + next.nowVisible);
2621 }
2622 }
2623 }
2624
2625 // We are starting up the next activity, so tell the window manager
2626 // that the previous one will be hidden soon. This way it can know
2627 // to ignore it when computing the desired screen orientation.
2628 if (prev != null) {
2629 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002630 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002632 if (mNoAnimActivities.contains(prev)) {
2633 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2634 } else {
2635 mWindowManager.prepareAppTransition(prev.task == next.task
2636 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2637 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002639 mWindowManager.setAppWillBeHidden(prev);
2640 mWindowManager.setAppVisibility(prev, false);
2641 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002642 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002644 if (mNoAnimActivities.contains(next)) {
2645 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2646 } else {
2647 mWindowManager.prepareAppTransition(prev.task == next.task
2648 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2649 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2650 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 }
2652 if (false) {
2653 mWindowManager.setAppWillBeHidden(prev);
2654 mWindowManager.setAppVisibility(prev, false);
2655 }
2656 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002657 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002658 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002659 if (mNoAnimActivities.contains(next)) {
2660 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2661 } else {
2662 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2663 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 }
2665
2666 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002667 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668
2669 // This activity is now becoming visible.
2670 mWindowManager.setAppVisibility(next, true);
2671
2672 HistoryRecord lastResumedActivity = mResumedActivity;
2673 ActivityState lastState = next.state;
2674
2675 updateCpuStats();
2676
2677 next.state = ActivityState.RESUMED;
2678 mResumedActivity = next;
2679 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002680 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 updateLRUListLocked(next);
2682
2683 // Have the window manager re-evaluate the orientation of
2684 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002685 boolean updated;
2686 synchronized (this) {
2687 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2688 mConfiguration,
2689 next.mayFreezeScreenLocked(next.app) ? next : null);
2690 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002691 next.frozenBeforeDestroy = true;
2692 }
2693 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002695 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 // The configuration update wasn't able to keep the existing
2697 // instance of the activity, and instead started a new one.
2698 // We should be all done, but let's just make sure our activity
2699 // is still at the top and schedule another run if something
2700 // weird happened.
2701 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002702 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002703 "Activity config changed during resume: " + next
2704 + ", new next: " + nextNext);
2705 if (nextNext != next) {
2706 // Do over!
2707 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2708 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002709 setFocusedActivityLocked(next);
2710 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002712 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 return true;
2714 }
2715
2716 try {
2717 // Deliver all pending results.
2718 ArrayList a = next.results;
2719 if (a != null) {
2720 final int N = a.size();
2721 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002722 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723 TAG, "Delivering results to " + next
2724 + ": " + a);
2725 next.app.thread.scheduleSendResult(next, a);
2726 }
2727 }
2728
2729 if (next.newIntents != null) {
2730 next.app.thread.scheduleNewIntent(next.newIntents, next);
2731 }
2732
Doug Zongker2bec3d42009-12-04 12:52:44 -08002733 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 System.identityHashCode(next),
2735 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736
2737 next.app.thread.scheduleResumeActivity(next,
2738 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002740 pauseIfSleepingLocked();
2741
2742 } catch (Exception e) {
2743 // Whoops, need to restart this activity!
2744 next.state = lastState;
2745 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002746 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 if (!next.hasBeenLaunched) {
2748 next.hasBeenLaunched = true;
2749 } else {
2750 if (SHOW_APP_STARTING_ICON) {
2751 mWindowManager.setAppStartingWindow(
2752 next, next.packageName, next.theme,
2753 next.nonLocalizedLabel,
2754 next.labelRes, next.icon, null, true);
2755 }
2756 }
2757 startSpecificActivityLocked(next, true, false);
2758 return true;
2759 }
2760
2761 // From this point on, if something goes wrong there is no way
2762 // to recover the activity.
2763 try {
2764 next.visible = true;
2765 completeResumeLocked(next);
2766 } catch (Exception e) {
2767 // If any exception gets thrown, toss away this
2768 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002769 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002770 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2771 "resume-exception");
2772 return true;
2773 }
2774
2775 // Didn't need to use the icicle, and it is now out of date.
2776 next.icicle = null;
2777 next.haveState = false;
2778 next.stopped = false;
2779
2780 } else {
2781 // Whoops, need to restart this activity!
2782 if (!next.hasBeenLaunched) {
2783 next.hasBeenLaunched = true;
2784 } else {
2785 if (SHOW_APP_STARTING_ICON) {
2786 mWindowManager.setAppStartingWindow(
2787 next, next.packageName, next.theme,
2788 next.nonLocalizedLabel,
2789 next.labelRes, next.icon, null, true);
2790 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002791 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792 }
2793 startSpecificActivityLocked(next, true, true);
2794 }
2795
2796 return true;
2797 }
2798
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002799 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2800 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002801 final int NH = mHistory.size();
2802
2803 int addPos = -1;
2804
2805 if (!newTask) {
2806 // If starting in an existing task, find where that is...
2807 HistoryRecord next = null;
2808 boolean startIt = true;
2809 for (int i = NH-1; i >= 0; i--) {
2810 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2811 if (p.finishing) {
2812 continue;
2813 }
2814 if (p.task == r.task) {
2815 // Here it is! Now, if this is not yet visible to the
2816 // user, then just add it without starting; it will
2817 // get started when the user navigates back to it.
2818 addPos = i+1;
2819 if (!startIt) {
2820 mHistory.add(addPos, r);
2821 r.inHistory = true;
2822 r.task.numActivities++;
2823 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2824 r.info.screenOrientation, r.fullscreen);
2825 if (VALIDATE_TOKENS) {
2826 mWindowManager.validateAppTokens(mHistory);
2827 }
2828 return;
2829 }
2830 break;
2831 }
2832 if (p.fullscreen) {
2833 startIt = false;
2834 }
2835 next = p;
2836 }
2837 }
2838
2839 // Place a new activity at top of stack, so it is next to interact
2840 // with the user.
2841 if (addPos < 0) {
2842 addPos = mHistory.size();
2843 }
2844
2845 // If we are not placing the new activity frontmost, we do not want
2846 // to deliver the onUserLeaving callback to the actual frontmost
2847 // activity
2848 if (addPos < NH) {
2849 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002850 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 }
2852
2853 // Slot the activity into the history stack and proceed
2854 mHistory.add(addPos, r);
2855 r.inHistory = true;
2856 r.frontOfTask = newTask;
2857 r.task.numActivities++;
2858 if (NH > 0) {
2859 // We want to show the starting preview window if we are
2860 // switching to a new task, or the next activity's process is
2861 // not currently running.
2862 boolean showStartingIcon = newTask;
2863 ProcessRecord proc = r.app;
2864 if (proc == null) {
2865 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2866 }
2867 if (proc == null || proc.thread == null) {
2868 showStartingIcon = true;
2869 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002870 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002872 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2873 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2874 mNoAnimActivities.add(r);
2875 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2876 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2877 mNoAnimActivities.remove(r);
2878 } else {
2879 mWindowManager.prepareAppTransition(newTask
2880 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2881 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2882 mNoAnimActivities.remove(r);
2883 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 mWindowManager.addAppToken(
2885 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2886 boolean doShow = true;
2887 if (newTask) {
2888 // Even though this activity is starting fresh, we still need
2889 // to reset it to make sure we apply affinities to move any
2890 // existing activities from other tasks in to it.
2891 // If the caller has requested that the target task be
2892 // reset, then do so.
2893 if ((r.intent.getFlags()
2894 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2895 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002896 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 }
2898 }
2899 if (SHOW_APP_STARTING_ICON && doShow) {
2900 // Figure out if we are transitioning from another activity that is
2901 // "has the same starting icon" as the next one. This allows the
2902 // window manager to keep the previous window it had previously
2903 // created, if it still had one.
2904 HistoryRecord prev = mResumedActivity;
2905 if (prev != null) {
2906 // We don't want to reuse the previous starting preview if:
2907 // (1) The current activity is in a different task.
2908 if (prev.task != r.task) prev = null;
2909 // (2) The current activity is already displayed.
2910 else if (prev.nowVisible) prev = null;
2911 }
2912 mWindowManager.setAppStartingWindow(
2913 r, r.packageName, r.theme, r.nonLocalizedLabel,
2914 r.labelRes, r.icon, prev, showStartingIcon);
2915 }
2916 } else {
2917 // If this is the first activity, don't do any fancy animations,
2918 // because there is nothing for it to animate on top of.
2919 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2920 r.info.screenOrientation, r.fullscreen);
2921 }
2922 if (VALIDATE_TOKENS) {
2923 mWindowManager.validateAppTokens(mHistory);
2924 }
2925
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002926 if (doResume) {
2927 resumeTopActivityLocked(null);
2928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 }
2930
2931 /**
2932 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002933 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2934 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 * an instance of that activity in the stack and, if found, finish all
2936 * activities on top of it and return the instance.
2937 *
2938 * @param newR Description of the new activity being started.
2939 * @return Returns the old activity that should be continue to be used,
2940 * or null if none was found.
2941 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002942 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002943 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002945
2946 // First find the requested task.
2947 while (i > 0) {
2948 i--;
2949 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2950 if (r.task.taskId == taskId) {
2951 i++;
2952 break;
2953 }
2954 }
2955
2956 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002957 while (i > 0) {
2958 i--;
2959 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2960 if (r.finishing) {
2961 continue;
2962 }
2963 if (r.task.taskId != taskId) {
2964 return null;
2965 }
2966 if (r.realActivity.equals(newR.realActivity)) {
2967 // Here it is! Now finish everything in front...
2968 HistoryRecord ret = r;
2969 if (doClear) {
2970 while (i < (mHistory.size()-1)) {
2971 i++;
2972 r = (HistoryRecord)mHistory.get(i);
2973 if (r.finishing) {
2974 continue;
2975 }
2976 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2977 null, "clear")) {
2978 i--;
2979 }
2980 }
2981 }
2982
2983 // Finally, if this is a normal launch mode (that is, not
2984 // expecting onNewIntent()), then we will finish the current
2985 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002986 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2987 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002988 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002989 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 if (index >= 0) {
2991 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2992 null, "clear");
2993 }
2994 return null;
2995 }
2996 }
2997
2998 return ret;
2999 }
3000 }
3001
3002 return null;
3003 }
3004
3005 /**
3006 * Find the activity in the history stack within the given task. Returns
3007 * the index within the history at which it's found, or < 0 if not found.
3008 */
3009 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3010 int i = mHistory.size();
3011 while (i > 0) {
3012 i--;
3013 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3014 if (candidate.task.taskId != task) {
3015 break;
3016 }
3017 if (candidate.realActivity.equals(r.realActivity)) {
3018 return i;
3019 }
3020 }
3021
3022 return -1;
3023 }
3024
3025 /**
3026 * Reorder the history stack so that the activity at the given index is
3027 * brought to the front.
3028 */
3029 private final HistoryRecord moveActivityToFrontLocked(int where) {
3030 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3031 int top = mHistory.size();
3032 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3033 mHistory.add(top, newTop);
3034 oldTop.frontOfTask = false;
3035 newTop.frontOfTask = true;
3036 return newTop;
3037 }
3038
3039 /**
3040 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3041 * method will be called at the proper time.
3042 */
3043 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3044 boolean sent = false;
3045 if (r.state == ActivityState.RESUMED
3046 && r.app != null && r.app.thread != null) {
3047 try {
3048 ArrayList<Intent> ar = new ArrayList<Intent>();
3049 ar.add(new Intent(intent));
3050 r.app.thread.scheduleNewIntent(ar, r);
3051 sent = true;
3052 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003053 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 }
3055 }
3056 if (!sent) {
3057 r.addNewIntentLocked(new Intent(intent));
3058 }
3059 }
3060
3061 private final void logStartActivity(int tag, HistoryRecord r,
3062 TaskRecord task) {
3063 EventLog.writeEvent(tag,
3064 System.identityHashCode(r), task.taskId,
3065 r.shortComponentName, r.intent.getAction(),
3066 r.intent.getType(), r.intent.getDataString(),
3067 r.intent.getFlags());
3068 }
3069
3070 private final int startActivityLocked(IApplicationThread caller,
3071 Intent intent, String resolvedType,
3072 Uri[] grantedUriPermissions,
3073 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3074 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003075 int callingPid, int callingUid, boolean onlyIfNeeded,
3076 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003077 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078
3079 HistoryRecord sourceRecord = null;
3080 HistoryRecord resultRecord = null;
3081 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003082 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003083 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3085 if (index >= 0) {
3086 sourceRecord = (HistoryRecord)mHistory.get(index);
3087 if (requestCode >= 0 && !sourceRecord.finishing) {
3088 resultRecord = sourceRecord;
3089 }
3090 }
3091 }
3092
3093 int launchFlags = intent.getFlags();
3094
3095 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3096 && sourceRecord != null) {
3097 // Transfer the result target from the source activity to the new
3098 // one being started, including any failures.
3099 if (requestCode >= 0) {
3100 return START_FORWARD_AND_REQUEST_CONFLICT;
3101 }
3102 resultRecord = sourceRecord.resultTo;
3103 resultWho = sourceRecord.resultWho;
3104 requestCode = sourceRecord.requestCode;
3105 sourceRecord.resultTo = null;
3106 if (resultRecord != null) {
3107 resultRecord.removeResultsLocked(
3108 sourceRecord, resultWho, requestCode);
3109 }
3110 }
3111
3112 int err = START_SUCCESS;
3113
3114 if (intent.getComponent() == null) {
3115 // We couldn't find a class that can handle the given Intent.
3116 // That's the end of that!
3117 err = START_INTENT_NOT_RESOLVED;
3118 }
3119
3120 if (err == START_SUCCESS && aInfo == null) {
3121 // We couldn't find the specific class specified in the Intent.
3122 // Also the end of the line.
3123 err = START_CLASS_NOT_FOUND;
3124 }
3125
3126 ProcessRecord callerApp = null;
3127 if (err == START_SUCCESS && caller != null) {
3128 callerApp = getRecordForAppLocked(caller);
3129 if (callerApp != null) {
3130 callingPid = callerApp.pid;
3131 callingUid = callerApp.info.uid;
3132 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003133 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134 + " (pid=" + callingPid + ") when starting: "
3135 + intent.toString());
3136 err = START_PERMISSION_DENIED;
3137 }
3138 }
3139
3140 if (err != START_SUCCESS) {
3141 if (resultRecord != null) {
3142 sendActivityResultLocked(-1,
3143 resultRecord, resultWho, requestCode,
3144 Activity.RESULT_CANCELED, null);
3145 }
3146 return err;
3147 }
3148
3149 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3150 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3151 if (perm != PackageManager.PERMISSION_GRANTED) {
3152 if (resultRecord != null) {
3153 sendActivityResultLocked(-1,
3154 resultRecord, resultWho, requestCode,
3155 Activity.RESULT_CANCELED, null);
3156 }
3157 String msg = "Permission Denial: starting " + intent.toString()
3158 + " from " + callerApp + " (pid=" + callingPid
3159 + ", uid=" + callingUid + ")"
3160 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003161 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 throw new SecurityException(msg);
3163 }
3164
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003165 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 boolean abort = false;
3167 try {
3168 // The Intent we give to the watcher has the extra data
3169 // stripped off, since it can contain private information.
3170 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003171 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003172 aInfo.applicationInfo.packageName);
3173 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003174 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 }
3176
3177 if (abort) {
3178 if (resultRecord != null) {
3179 sendActivityResultLocked(-1,
3180 resultRecord, resultWho, requestCode,
3181 Activity.RESULT_CANCELED, null);
3182 }
3183 // We pretend to the caller that it was really started, but
3184 // they will just get a cancel result.
3185 return START_SUCCESS;
3186 }
3187 }
3188
3189 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3190 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003191 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003193 if (mResumedActivity == null
3194 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3195 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3196 PendingActivityLaunch pal = new PendingActivityLaunch();
3197 pal.r = r;
3198 pal.sourceRecord = sourceRecord;
3199 pal.grantedUriPermissions = grantedUriPermissions;
3200 pal.grantedMode = grantedMode;
3201 pal.onlyIfNeeded = onlyIfNeeded;
3202 mPendingActivityLaunches.add(pal);
3203 return START_SWITCHES_CANCELED;
3204 }
3205 }
3206
3207 if (mDidAppSwitch) {
3208 // This is the second allowed switch since we stopped switches,
3209 // so now just generally allow switches. Use case: user presses
3210 // home (switches disabled, switch to home, mDidAppSwitch now true);
3211 // user taps a home icon (coming from home so allowed, we hit here
3212 // and now allow anyone to switch again).
3213 mAppSwitchesAllowedTime = 0;
3214 } else {
3215 mDidAppSwitch = true;
3216 }
3217
3218 doPendingActivityLaunchesLocked(false);
3219
3220 return startActivityUncheckedLocked(r, sourceRecord,
3221 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3222 }
3223
3224 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3225 final int N = mPendingActivityLaunches.size();
3226 if (N <= 0) {
3227 return;
3228 }
3229 for (int i=0; i<N; i++) {
3230 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3231 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3232 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3233 doResume && i == (N-1));
3234 }
3235 mPendingActivityLaunches.clear();
3236 }
3237
3238 private final int startActivityUncheckedLocked(HistoryRecord r,
3239 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3240 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3241 final Intent intent = r.intent;
3242 final int callingUid = r.launchedFromUid;
3243
3244 int launchFlags = intent.getFlags();
3245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003246 // We'll invoke onUserLeaving before onPause only if the launching
3247 // activity did not explicitly state that this is an automated launch.
3248 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003249 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 "startActivity() => mUserLeaving=" + mUserLeaving);
3251
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003252 // If the caller has asked not to resume at this point, we make note
3253 // of this in the record so that we can skip it when trying to find
3254 // the top running activity.
3255 if (!doResume) {
3256 r.delayedResume = true;
3257 }
3258
3259 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3260 != 0 ? r : null;
3261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 // If the onlyIfNeeded flag is set, then we can do this if the activity
3263 // being launched is the same as the one making the call... or, as
3264 // a special case, if we do not know the caller then we count the
3265 // current top activity as the caller.
3266 if (onlyIfNeeded) {
3267 HistoryRecord checkedCaller = sourceRecord;
3268 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003269 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 }
3271 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3272 // Caller is not the same as launcher, so always needed.
3273 onlyIfNeeded = false;
3274 }
3275 }
3276
3277 if (grantedUriPermissions != null && callingUid > 0) {
3278 for (int i=0; i<grantedUriPermissions.length; i++) {
3279 grantUriPermissionLocked(callingUid, r.packageName,
3280 grantedUriPermissions[i], grantedMode, r);
3281 }
3282 }
3283
3284 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3285 intent, r);
3286
3287 if (sourceRecord == null) {
3288 // This activity is not being started from another... in this
3289 // case we -always- start a new task.
3290 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003291 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003292 + intent);
3293 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3294 }
3295 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3296 // The original activity who is starting us is running as a single
3297 // instance... this new activity it is starting must go on its
3298 // own task.
3299 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3300 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3301 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3302 // The activity being started is a single instance... it always
3303 // gets launched into its own task.
3304 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3305 }
3306
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003307 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 // For whatever reason this activity is being launched into a new
3309 // task... yet the caller has requested a result back. Well, that
3310 // is pretty messed up, so instead immediately send back a cancel
3311 // and let the new task continue launched as normal without a
3312 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003313 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003315 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 Activity.RESULT_CANCELED, null);
3317 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003318 }
3319
3320 boolean addingToTask = false;
3321 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3322 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3323 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3324 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3325 // If bring to front is requested, and no result is requested, and
3326 // we can find a task that was started with this same
3327 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003328 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 // See if there is a task to bring to the front. If this is
3330 // a SINGLE_INSTANCE activity, there can be one and only one
3331 // instance of it in the history, and it is always in its own
3332 // unique task, so we do a special search.
3333 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3334 ? findTaskLocked(intent, r.info)
3335 : findActivityLocked(intent, r.info);
3336 if (taskTop != null) {
3337 if (taskTop.task.intent == null) {
3338 // This task was started because of movement of
3339 // the activity based on affinity... now that we
3340 // are actually launching it, we can assign the
3341 // base intent.
3342 taskTop.task.setIntent(intent, r.info);
3343 }
3344 // If the target task is not in the front, then we need
3345 // to bring it to the front... except... well, with
3346 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3347 // to have the same behavior as if a new instance was
3348 // being started, which means not bringing it to the front
3349 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003350 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 if (curTop.task != taskTop.task) {
3352 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3353 boolean callerAtFront = sourceRecord == null
3354 || curTop.task == sourceRecord.task;
3355 if (callerAtFront) {
3356 // We really do want to push this one into the
3357 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003358 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 }
3360 }
3361 // If the caller has requested that the target task be
3362 // reset, then do so.
3363 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3364 taskTop = resetTaskIfNeededLocked(taskTop, r);
3365 }
3366 if (onlyIfNeeded) {
3367 // We don't need to start a new activity, and
3368 // the client said not to do anything if that
3369 // is the case, so this is it! And for paranoia, make
3370 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003371 if (doResume) {
3372 resumeTopActivityLocked(null);
3373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 return START_RETURN_INTENT_TO_CALLER;
3375 }
3376 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3377 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3378 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3379 // In this situation we want to remove all activities
3380 // from the task up to the one being started. In most
3381 // cases this means we are resetting the task to its
3382 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003383 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003384 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 if (top != null) {
3386 if (top.frontOfTask) {
3387 // Activity aliases may mean we use different
3388 // intents for the top activity, so make sure
3389 // the task now has the identity of the new
3390 // intent.
3391 top.task.setIntent(r.intent, r.info);
3392 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003393 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003394 deliverNewIntentLocked(top, r.intent);
3395 } else {
3396 // A special case: we need to
3397 // start the activity because it is not currently
3398 // running, and the caller has asked to clear the
3399 // current task to have this activity at the top.
3400 addingToTask = true;
3401 // Now pretend like this activity is being started
3402 // by the top of its task, so it is put in the
3403 // right place.
3404 sourceRecord = taskTop;
3405 }
3406 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3407 // In this case the top activity on the task is the
3408 // same as the one being launched, so we take that
3409 // as a request to bring the task to the foreground.
3410 // If the top activity in the task is the root
3411 // activity, deliver this new intent to it if it
3412 // desires.
3413 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3414 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003415 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003416 if (taskTop.frontOfTask) {
3417 taskTop.task.setIntent(r.intent, r.info);
3418 }
3419 deliverNewIntentLocked(taskTop, r.intent);
3420 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3421 // In this case we are launching the root activity
3422 // of the task, but with a different intent. We
3423 // should start a new instance on top.
3424 addingToTask = true;
3425 sourceRecord = taskTop;
3426 }
3427 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3428 // In this case an activity is being launched in to an
3429 // existing task, without resetting that task. This
3430 // is typically the situation of launching an activity
3431 // from a notification or shortcut. We want to place
3432 // the new activity on top of the current task.
3433 addingToTask = true;
3434 sourceRecord = taskTop;
3435 } else if (!taskTop.task.rootWasReset) {
3436 // In this case we are launching in to an existing task
3437 // that has not yet been started from its front door.
3438 // The current task has been brought to the front.
3439 // Ideally, we'd probably like to place this new task
3440 // at the bottom of its stack, but that's a little hard
3441 // to do with the current organization of the code so
3442 // for now we'll just drop it.
3443 taskTop.task.setIntent(r.intent, r.info);
3444 }
3445 if (!addingToTask) {
3446 // We didn't do anything... but it was needed (a.k.a., client
3447 // don't use that intent!) And for paranoia, make
3448 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003449 if (doResume) {
3450 resumeTopActivityLocked(null);
3451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 return START_TASK_TO_FRONT;
3453 }
3454 }
3455 }
3456 }
3457
3458 //String uri = r.intent.toURI();
3459 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003460 //Slog.i(TAG, "Given intent: " + r.intent);
3461 //Slog.i(TAG, "URI is: " + uri);
3462 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003463
3464 if (r.packageName != null) {
3465 // If the activity being launched is the same as the one currently
3466 // at the top, then we need to check if it should only be launched
3467 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003468 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3469 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 if (top.realActivity.equals(r.realActivity)) {
3471 if (top.app != null && top.app.thread != null) {
3472 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3473 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3474 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003475 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 // For paranoia, make sure we have correctly
3477 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003478 if (doResume) {
3479 resumeTopActivityLocked(null);
3480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 if (onlyIfNeeded) {
3482 // We don't need to start a new activity, and
3483 // the client said not to do anything if that
3484 // is the case, so this is it!
3485 return START_RETURN_INTENT_TO_CALLER;
3486 }
3487 deliverNewIntentLocked(top, r.intent);
3488 return START_DELIVERED_TO_TOP;
3489 }
3490 }
3491 }
3492 }
3493
3494 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003495 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003497 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 Activity.RESULT_CANCELED, null);
3499 }
3500 return START_CLASS_NOT_FOUND;
3501 }
3502
3503 boolean newTask = false;
3504
3505 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003506 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3508 // todo: should do better management of integers.
3509 mCurTask++;
3510 if (mCurTask <= 0) {
3511 mCurTask = 1;
3512 }
3513 r.task = new TaskRecord(mCurTask, r.info, intent,
3514 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003515 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516 + " in new task " + r.task);
3517 newTask = true;
3518 addRecentTask(r.task);
3519
3520 } else if (sourceRecord != null) {
3521 if (!addingToTask &&
3522 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3523 // In this case, we are adding the activity to an existing
3524 // task, but the caller has asked to clear that task if the
3525 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003526 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003527 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003529 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003530 deliverNewIntentLocked(top, r.intent);
3531 // For paranoia, make sure we have correctly
3532 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003533 if (doResume) {
3534 resumeTopActivityLocked(null);
3535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 return START_DELIVERED_TO_TOP;
3537 }
3538 } else if (!addingToTask &&
3539 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3540 // In this case, we are launching an activity in our own task
3541 // that may already be running somewhere in the history, and
3542 // we want to shuffle it to the front of the stack if so.
3543 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3544 if (where >= 0) {
3545 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003546 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003547 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003548 if (doResume) {
3549 resumeTopActivityLocked(null);
3550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 return START_DELIVERED_TO_TOP;
3552 }
3553 }
3554 // An existing activity is starting this new activity, so we want
3555 // to keep the new one in the same task as the one that is starting
3556 // it.
3557 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003558 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 + " in existing task " + r.task);
3560
3561 } else {
3562 // This not being started from an existing activity, and not part
3563 // of a new task... just put it in the top task, though these days
3564 // this case should never happen.
3565 final int N = mHistory.size();
3566 HistoryRecord prev =
3567 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3568 r.task = prev != null
3569 ? prev.task
3570 : new TaskRecord(mCurTask, r.info, intent,
3571 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003572 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 + " in new guessed " + r.task);
3574 }
3575 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003576 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003578 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003579 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 return START_SUCCESS;
3581 }
3582
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003583 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3584 long thisTime, long totalTime) {
3585 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3586 WaitResult w = mWaitingActivityLaunched.get(i);
3587 w.timeout = timeout;
3588 if (r != null) {
3589 w.who = new ComponentName(r.info.packageName, r.info.name);
3590 }
3591 w.thisTime = thisTime;
3592 w.totalTime = totalTime;
3593 }
3594 notify();
3595 }
3596
3597 void reportActivityVisibleLocked(HistoryRecord r) {
3598 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3599 WaitResult w = mWaitingActivityVisible.get(i);
3600 w.timeout = false;
3601 if (r != null) {
3602 w.who = new ComponentName(r.info.packageName, r.info.name);
3603 }
3604 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3605 w.thisTime = w.totalTime;
3606 }
3607 notify();
3608 }
3609
3610 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3612 int grantedMode, IBinder resultTo,
3613 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003614 boolean debug, WaitResult outResult) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 // Refuse possible leaked file descriptors
3616 if (intent != null && intent.hasFileDescriptors()) {
3617 throw new IllegalArgumentException("File descriptors passed in Intent");
3618 }
3619
The Android Open Source Project4df24232009-03-05 14:34:35 -08003620 final boolean componentSpecified = intent.getComponent() != null;
3621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622 // Don't modify the client's object!
3623 intent = new Intent(intent);
3624
3625 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 ActivityInfo aInfo;
3627 try {
3628 ResolveInfo rInfo =
3629 ActivityThread.getPackageManager().resolveIntent(
3630 intent, resolvedType,
3631 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003632 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 aInfo = rInfo != null ? rInfo.activityInfo : null;
3634 } catch (RemoteException e) {
3635 aInfo = null;
3636 }
3637
3638 if (aInfo != null) {
3639 // Store the found target back into the intent, because now that
3640 // we have it we never want to do this again. For example, if the
3641 // user navigates back to this point in the history, we should
3642 // always restart the exact same activity.
3643 intent.setComponent(new ComponentName(
3644 aInfo.applicationInfo.packageName, aInfo.name));
3645
3646 // Don't debug things in the system process
3647 if (debug) {
3648 if (!aInfo.processName.equals("system")) {
3649 setDebugApp(aInfo.processName, true, false);
3650 }
3651 }
3652 }
3653
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003654 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003655 int callingPid;
3656 int callingUid;
3657 if (caller == null) {
3658 callingPid = Binder.getCallingPid();
3659 callingUid = Binder.getCallingUid();
3660 } else {
3661 callingPid = callingUid = -1;
3662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 final long origId = Binder.clearCallingIdentity();
3664 int res = startActivityLocked(caller, intent, resolvedType,
3665 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003666 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003667 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003669
3670 if (outResult != null) {
3671 outResult.result = res;
3672 if (res == IActivityManager.START_SUCCESS) {
3673 mWaitingActivityLaunched.add(outResult);
3674 do {
3675 try {
3676 wait();
3677 } catch (InterruptedException e) {
3678 }
3679 } while (!outResult.timeout && outResult.who == null);
3680 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3681 HistoryRecord r = this.topRunningActivityLocked(null);
3682 if (r.nowVisible) {
3683 outResult.timeout = false;
3684 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3685 outResult.totalTime = 0;
3686 outResult.thisTime = 0;
3687 } else {
3688 outResult.thisTime = SystemClock.uptimeMillis();
3689 mWaitingActivityVisible.add(outResult);
3690 do {
3691 try {
3692 wait();
3693 } catch (InterruptedException e) {
3694 }
3695 } while (!outResult.timeout && outResult.who == null);
3696 }
3697 }
3698 }
3699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003700 return res;
3701 }
3702 }
3703
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003704 public final int startActivity(IApplicationThread caller,
3705 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3706 int grantedMode, IBinder resultTo,
3707 String resultWho, int requestCode, boolean onlyIfNeeded,
3708 boolean debug) {
3709 return startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3710 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, null);
3711 }
3712
3713 public final WaitResult startActivityAndWait(IApplicationThread caller,
3714 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3715 int grantedMode, IBinder resultTo,
3716 String resultWho, int requestCode, boolean onlyIfNeeded,
3717 boolean debug) {
3718 WaitResult res = new WaitResult();
3719 startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3720 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, res);
3721 return res;
3722 }
3723
3724 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003725 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003726 IBinder resultTo, String resultWho, int requestCode,
3727 int flagsMask, int flagsValues) {
3728 // Refuse possible leaked file descriptors
3729 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3730 throw new IllegalArgumentException("File descriptors passed in Intent");
3731 }
3732
3733 IIntentSender sender = intent.getTarget();
3734 if (!(sender instanceof PendingIntentRecord)) {
3735 throw new IllegalArgumentException("Bad PendingIntent object");
3736 }
3737
3738 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003739
3740 synchronized (this) {
3741 // If this is coming from the currently resumed activity, it is
3742 // effectively saying that app switches are allowed at this point.
3743 if (mResumedActivity != null
3744 && mResumedActivity.info.applicationInfo.uid ==
3745 Binder.getCallingUid()) {
3746 mAppSwitchesAllowedTime = 0;
3747 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003748 }
3749
3750 return pir.sendInner(0, fillInIntent, resolvedType,
3751 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3752 }
3753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 public boolean startNextMatchingActivity(IBinder callingActivity,
3755 Intent intent) {
3756 // Refuse possible leaked file descriptors
3757 if (intent != null && intent.hasFileDescriptors() == true) {
3758 throw new IllegalArgumentException("File descriptors passed in Intent");
3759 }
3760
3761 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003762 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 if (index < 0) {
3764 return false;
3765 }
3766 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3767 if (r.app == null || r.app.thread == null) {
3768 // The caller is not running... d'oh!
3769 return false;
3770 }
3771 intent = new Intent(intent);
3772 // The caller is not allowed to change the data.
3773 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3774 // And we are resetting to find the next component...
3775 intent.setComponent(null);
3776
3777 ActivityInfo aInfo = null;
3778 try {
3779 List<ResolveInfo> resolves =
3780 ActivityThread.getPackageManager().queryIntentActivities(
3781 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003782 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783
3784 // Look for the original activity in the list...
3785 final int N = resolves != null ? resolves.size() : 0;
3786 for (int i=0; i<N; i++) {
3787 ResolveInfo rInfo = resolves.get(i);
3788 if (rInfo.activityInfo.packageName.equals(r.packageName)
3789 && rInfo.activityInfo.name.equals(r.info.name)) {
3790 // We found the current one... the next matching is
3791 // after it.
3792 i++;
3793 if (i<N) {
3794 aInfo = resolves.get(i).activityInfo;
3795 }
3796 break;
3797 }
3798 }
3799 } catch (RemoteException e) {
3800 }
3801
3802 if (aInfo == null) {
3803 // Nobody who is next!
3804 return false;
3805 }
3806
3807 intent.setComponent(new ComponentName(
3808 aInfo.applicationInfo.packageName, aInfo.name));
3809 intent.setFlags(intent.getFlags()&~(
3810 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3811 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3812 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3813 Intent.FLAG_ACTIVITY_NEW_TASK));
3814
3815 // Okay now we need to start the new activity, replacing the
3816 // currently running activity. This is a little tricky because
3817 // we want to start the new one as if the current one is finished,
3818 // but not finish the current one first so that there is no flicker.
3819 // And thus...
3820 final boolean wasFinishing = r.finishing;
3821 r.finishing = true;
3822
3823 // Propagate reply information over to the new activity.
3824 final HistoryRecord resultTo = r.resultTo;
3825 final String resultWho = r.resultWho;
3826 final int requestCode = r.requestCode;
3827 r.resultTo = null;
3828 if (resultTo != null) {
3829 resultTo.removeResultsLocked(r, resultWho, requestCode);
3830 }
3831
3832 final long origId = Binder.clearCallingIdentity();
3833 // XXX we are not dealing with propagating grantedUriPermissions...
3834 // those are not yet exposed to user code, so there is no need.
3835 int res = startActivityLocked(r.app.thread, intent,
3836 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003837 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 Binder.restoreCallingIdentity(origId);
3839
3840 r.finishing = wasFinishing;
3841 if (res != START_SUCCESS) {
3842 return false;
3843 }
3844 return true;
3845 }
3846 }
3847
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003848 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003849 Intent intent, String resolvedType, IBinder resultTo,
3850 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003851
3852 // This is so super not safe, that only the system (or okay root)
3853 // can do it.
3854 final int callingUid = Binder.getCallingUid();
3855 if (callingUid != 0 && callingUid != Process.myUid()) {
3856 throw new SecurityException(
3857 "startActivityInPackage only available to the system");
3858 }
3859
The Android Open Source Project4df24232009-03-05 14:34:35 -08003860 final boolean componentSpecified = intent.getComponent() != null;
3861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 // Don't modify the client's object!
3863 intent = new Intent(intent);
3864
3865 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 ActivityInfo aInfo;
3867 try {
3868 ResolveInfo rInfo =
3869 ActivityThread.getPackageManager().resolveIntent(
3870 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003871 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 aInfo = rInfo != null ? rInfo.activityInfo : null;
3873 } catch (RemoteException e) {
3874 aInfo = null;
3875 }
3876
3877 if (aInfo != null) {
3878 // Store the found target back into the intent, because now that
3879 // we have it we never want to do this again. For example, if the
3880 // user navigates back to this point in the history, we should
3881 // always restart the exact same activity.
3882 intent.setComponent(new ComponentName(
3883 aInfo.applicationInfo.packageName, aInfo.name));
3884 }
3885
3886 synchronized(this) {
3887 return startActivityLocked(null, intent, resolvedType,
3888 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003889 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 }
3891 }
3892
3893 private final void addRecentTask(TaskRecord task) {
3894 // Remove any existing entries that are the same kind of task.
3895 int N = mRecentTasks.size();
3896 for (int i=0; i<N; i++) {
3897 TaskRecord tr = mRecentTasks.get(i);
3898 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3899 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3900 mRecentTasks.remove(i);
3901 i--;
3902 N--;
3903 if (task.intent == null) {
3904 // If the new recent task we are adding is not fully
3905 // specified, then replace it with the existing recent task.
3906 task = tr;
3907 }
3908 }
3909 }
3910 if (N >= MAX_RECENT_TASKS) {
3911 mRecentTasks.remove(N-1);
3912 }
3913 mRecentTasks.add(0, task);
3914 }
3915
3916 public void setRequestedOrientation(IBinder token,
3917 int requestedOrientation) {
3918 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003919 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 if (index < 0) {
3921 return;
3922 }
3923 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3924 final long origId = Binder.clearCallingIdentity();
3925 mWindowManager.setAppOrientation(r, requestedOrientation);
3926 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003927 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 r.mayFreezeScreenLocked(r.app) ? r : null);
3929 if (config != null) {
3930 r.frozenBeforeDestroy = true;
3931 if (!updateConfigurationLocked(config, r)) {
3932 resumeTopActivityLocked(null);
3933 }
3934 }
3935 Binder.restoreCallingIdentity(origId);
3936 }
3937 }
3938
3939 public int getRequestedOrientation(IBinder token) {
3940 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003941 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 if (index < 0) {
3943 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3944 }
3945 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3946 return mWindowManager.getAppOrientation(r);
3947 }
3948 }
3949
3950 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003951 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3953 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3954 if (!r.finishing) {
3955 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3956 "no-history");
3957 }
3958 } else if (r.app != null && r.app.thread != null) {
3959 if (mFocusedActivity == r) {
3960 setFocusedActivityLocked(topRunningActivityLocked(null));
3961 }
3962 r.resumeKeyDispatchingLocked();
3963 try {
3964 r.stopped = false;
3965 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003966 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967 TAG, "Stopping visible=" + r.visible + " for " + r);
3968 if (!r.visible) {
3969 mWindowManager.setAppVisibility(r, false);
3970 }
3971 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3972 } catch (Exception e) {
3973 // Maybe just ignore exceptions here... if the process
3974 // has crashed, our death notification will clean things
3975 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003976 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 // Just in case, assume it to be stopped.
3978 r.stopped = true;
3979 r.state = ActivityState.STOPPED;
3980 if (r.configDestroy) {
3981 destroyActivityLocked(r, true);
3982 }
3983 }
3984 }
3985 }
3986
3987 /**
3988 * @return Returns true if the activity is being finished, false if for
3989 * some reason it is being left as-is.
3990 */
3991 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3992 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003993 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003994 TAG, "Finishing activity: token=" + token
3995 + ", result=" + resultCode + ", data=" + resultData);
3996
Dianne Hackborn75b03852009-06-12 15:43:26 -07003997 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003998 if (index < 0) {
3999 return false;
4000 }
4001 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4002
4003 // Is this the last activity left?
4004 boolean lastActivity = true;
4005 for (int i=mHistory.size()-1; i>=0; i--) {
4006 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4007 if (!p.finishing && p != r) {
4008 lastActivity = false;
4009 break;
4010 }
4011 }
4012
4013 // If this is the last activity, but it is the home activity, then
4014 // just don't finish it.
4015 if (lastActivity) {
4016 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4017 return false;
4018 }
4019 }
4020
4021 finishActivityLocked(r, index, resultCode, resultData, reason);
4022 return true;
4023 }
4024
4025 /**
4026 * @return Returns true if this activity has been removed from the history
4027 * list, or false if it is still in the list and will be removed later.
4028 */
4029 private final boolean finishActivityLocked(HistoryRecord r, int index,
4030 int resultCode, Intent resultData, String reason) {
4031 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004032 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 return false;
4034 }
4035
4036 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004037 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 System.identityHashCode(r),
4039 r.task.taskId, r.shortComponentName, reason);
4040 r.task.numActivities--;
4041 if (r.frontOfTask && index < (mHistory.size()-1)) {
4042 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4043 if (next.task == r.task) {
4044 next.frontOfTask = true;
4045 }
4046 }
4047
4048 r.pauseKeyDispatchingLocked();
4049 if (mFocusedActivity == r) {
4050 setFocusedActivityLocked(topRunningActivityLocked(null));
4051 }
4052
4053 // send the result
4054 HistoryRecord resultTo = r.resultTo;
4055 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004056 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004057 + " who=" + r.resultWho + " req=" + r.requestCode
4058 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004059 if (r.info.applicationInfo.uid > 0) {
4060 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4061 r.packageName, resultData, r);
4062 }
4063 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4064 resultData);
4065 r.resultTo = null;
4066 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004067 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004068
4069 // Make sure this HistoryRecord is not holding on to other resources,
4070 // because clients have remote IPC references to this object so we
4071 // can't assume that will go away and want to avoid circular IPC refs.
4072 r.results = null;
4073 r.pendingResults = null;
4074 r.newIntents = null;
4075 r.icicle = null;
4076
4077 if (mPendingThumbnails.size() > 0) {
4078 // There are clients waiting to receive thumbnails so, in case
4079 // this is an activity that someone is waiting for, add it
4080 // to the pending list so we can correctly update the clients.
4081 mCancelledThumbnails.add(r);
4082 }
4083
4084 if (mResumedActivity == r) {
4085 boolean endTask = index <= 0
4086 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004087 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 "Prepare close transition: finishing " + r);
4089 mWindowManager.prepareAppTransition(endTask
4090 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4091 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4092
4093 // Tell window manager to prepare for this one to be removed.
4094 mWindowManager.setAppVisibility(r, false);
4095
4096 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004097 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4098 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 startPausingLocked(false, false);
4100 }
4101
4102 } else if (r.state != ActivityState.PAUSING) {
4103 // If the activity is PAUSING, we will complete the finish once
4104 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004105 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 return finishCurrentActivityLocked(r, index,
4107 FINISH_AFTER_PAUSE) == null;
4108 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004109 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004110 }
4111
4112 return false;
4113 }
4114
4115 private static final int FINISH_IMMEDIATELY = 0;
4116 private static final int FINISH_AFTER_PAUSE = 1;
4117 private static final int FINISH_AFTER_VISIBLE = 2;
4118
4119 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4120 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004121 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004122 if (index < 0) {
4123 return null;
4124 }
4125
4126 return finishCurrentActivityLocked(r, index, mode);
4127 }
4128
4129 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4130 int index, int mode) {
4131 // First things first: if this activity is currently visible,
4132 // and the resumed activity is not yet visible, then hold off on
4133 // finishing until the resumed one becomes visible.
4134 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4135 if (!mStoppingActivities.contains(r)) {
4136 mStoppingActivities.add(r);
4137 if (mStoppingActivities.size() > 3) {
4138 // If we already have a few activities waiting to stop,
4139 // then give up on things going idle and start clearing
4140 // them out.
4141 Message msg = Message.obtain();
4142 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4143 mHandler.sendMessage(msg);
4144 }
4145 }
4146 r.state = ActivityState.STOPPING;
4147 updateOomAdjLocked();
4148 return r;
4149 }
4150
4151 // make sure the record is cleaned out of other places.
4152 mStoppingActivities.remove(r);
4153 mWaitingVisibleActivities.remove(r);
4154 if (mResumedActivity == r) {
4155 mResumedActivity = null;
4156 }
4157 final ActivityState prevState = r.state;
4158 r.state = ActivityState.FINISHING;
4159
4160 if (mode == FINISH_IMMEDIATELY
4161 || prevState == ActivityState.STOPPED
4162 || prevState == ActivityState.INITIALIZING) {
4163 // If this activity is already stopped, we can just finish
4164 // it right now.
4165 return destroyActivityLocked(r, true) ? null : r;
4166 } else {
4167 // Need to go through the full pause cycle to get this
4168 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004169 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 mFinishingActivities.add(r);
4171 resumeTopActivityLocked(null);
4172 }
4173 return r;
4174 }
4175
4176 /**
4177 * This is the internal entry point for handling Activity.finish().
4178 *
4179 * @param token The Binder token referencing the Activity we want to finish.
4180 * @param resultCode Result code, if any, from this Activity.
4181 * @param resultData Result data (Intent), if any, from this Activity.
4182 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004183 * @return Returns true if the activity successfully finished, or false if it is still running.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004184 */
4185 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4186 // Refuse possible leaked file descriptors
4187 if (resultData != null && resultData.hasFileDescriptors() == true) {
4188 throw new IllegalArgumentException("File descriptors passed in Intent");
4189 }
4190
4191 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004192 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 // Find the first activity that is not finishing.
4194 HistoryRecord next = topRunningActivityLocked(token, 0);
4195 if (next != null) {
4196 // ask watcher if this is allowed
4197 boolean resumeOK = true;
4198 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004199 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004201 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 }
4203
4204 if (!resumeOK) {
4205 return false;
4206 }
4207 }
4208 }
4209 final long origId = Binder.clearCallingIdentity();
4210 boolean res = requestFinishActivityLocked(token, resultCode,
4211 resultData, "app-request");
4212 Binder.restoreCallingIdentity(origId);
4213 return res;
4214 }
4215 }
4216
4217 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4218 String resultWho, int requestCode, int resultCode, Intent data) {
4219
4220 if (callingUid > 0) {
4221 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4222 data, r);
4223 }
4224
Joe Onorato8a9b2202010-02-26 18:56:32 -08004225 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004226 + " : who=" + resultWho + " req=" + requestCode
4227 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004228 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4229 try {
4230 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4231 list.add(new ResultInfo(resultWho, requestCode,
4232 resultCode, data));
4233 r.app.thread.scheduleSendResult(r, list);
4234 return;
4235 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004236 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 }
4238 }
4239
4240 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4241 }
4242
4243 public final void finishSubActivity(IBinder token, String resultWho,
4244 int requestCode) {
4245 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004246 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 if (index < 0) {
4248 return;
4249 }
4250 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4251
4252 final long origId = Binder.clearCallingIdentity();
4253
4254 int i;
4255 for (i=mHistory.size()-1; i>=0; i--) {
4256 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4257 if (r.resultTo == self && r.requestCode == requestCode) {
4258 if ((r.resultWho == null && resultWho == null) ||
4259 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4260 finishActivityLocked(r, i,
4261 Activity.RESULT_CANCELED, null, "request-sub");
4262 }
4263 }
4264 }
4265
4266 Binder.restoreCallingIdentity(origId);
4267 }
4268 }
4269
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004270 public void overridePendingTransition(IBinder token, String packageName,
4271 int enterAnim, int exitAnim) {
4272 synchronized(this) {
4273 int index = indexOfTokenLocked(token);
4274 if (index < 0) {
4275 return;
4276 }
4277 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4278
4279 final long origId = Binder.clearCallingIdentity();
4280
4281 if (self.state == ActivityState.RESUMED
4282 || self.state == ActivityState.PAUSING) {
4283 mWindowManager.overridePendingAppTransition(packageName,
4284 enterAnim, exitAnim);
4285 }
4286
4287 Binder.restoreCallingIdentity(origId);
4288 }
4289 }
4290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004291 /**
4292 * Perform clean-up of service connections in an activity record.
4293 */
4294 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4295 // Throw away any services that have been bound by this activity.
4296 if (r.connections != null) {
4297 Iterator<ConnectionRecord> it = r.connections.iterator();
4298 while (it.hasNext()) {
4299 ConnectionRecord c = it.next();
4300 removeConnectionLocked(c, null, r);
4301 }
4302 r.connections = null;
4303 }
4304 }
4305
4306 /**
4307 * Perform the common clean-up of an activity record. This is called both
4308 * as part of destroyActivityLocked() (when destroying the client-side
4309 * representation) and cleaning things up as a result of its hosting
4310 * processing going away, in which case there is no remaining client-side
4311 * state to destroy so only the cleanup here is needed.
4312 */
4313 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4314 if (mResumedActivity == r) {
4315 mResumedActivity = null;
4316 }
4317 if (mFocusedActivity == r) {
4318 mFocusedActivity = null;
4319 }
4320
4321 r.configDestroy = false;
4322 r.frozenBeforeDestroy = false;
4323
4324 // Make sure this record is no longer in the pending finishes list.
4325 // This could happen, for example, if we are trimming activities
4326 // down to the max limit while they are still waiting to finish.
4327 mFinishingActivities.remove(r);
4328 mWaitingVisibleActivities.remove(r);
4329
4330 // Remove any pending results.
4331 if (r.finishing && r.pendingResults != null) {
4332 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4333 PendingIntentRecord rec = apr.get();
4334 if (rec != null) {
4335 cancelIntentSenderLocked(rec, false);
4336 }
4337 }
4338 r.pendingResults = null;
4339 }
4340
4341 if (cleanServices) {
4342 cleanUpActivityServicesLocked(r);
4343 }
4344
4345 if (mPendingThumbnails.size() > 0) {
4346 // There are clients waiting to receive thumbnails so, in case
4347 // this is an activity that someone is waiting for, add it
4348 // to the pending list so we can correctly update the clients.
4349 mCancelledThumbnails.add(r);
4350 }
4351
4352 // Get rid of any pending idle timeouts.
4353 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4354 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4355 }
4356
4357 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4358 if (r.state != ActivityState.DESTROYED) {
4359 mHistory.remove(r);
4360 r.inHistory = false;
4361 r.state = ActivityState.DESTROYED;
4362 mWindowManager.removeAppToken(r);
4363 if (VALIDATE_TOKENS) {
4364 mWindowManager.validateAppTokens(mHistory);
4365 }
4366 cleanUpActivityServicesLocked(r);
4367 removeActivityUriPermissionsLocked(r);
4368 }
4369 }
4370
4371 /**
4372 * Destroy the current CLIENT SIDE instance of an activity. This may be
4373 * called both when actually finishing an activity, or when performing
4374 * a configuration switch where we destroy the current client-side object
4375 * but then create a new client-side object for this same HistoryRecord.
4376 */
4377 private final boolean destroyActivityLocked(HistoryRecord r,
4378 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004379 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 TAG, "Removing activity: token=" + r
4381 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004382 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 System.identityHashCode(r),
4384 r.task.taskId, r.shortComponentName);
4385
4386 boolean removedFromHistory = false;
4387
4388 cleanUpActivityLocked(r, false);
4389
Dianne Hackborn03abb812010-01-04 18:43:19 -08004390 final boolean hadApp = r.app != null;
4391
4392 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393 if (removeFromApp) {
4394 int idx = r.app.activities.indexOf(r);
4395 if (idx >= 0) {
4396 r.app.activities.remove(idx);
4397 }
4398 if (r.persistent) {
4399 decPersistentCountLocked(r.app);
4400 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004401 if (r.app.activities.size() == 0) {
4402 // No longer have activities, so update location in
4403 // LRU list.
4404 updateLruProcessLocked(r.app, true, false);
4405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 }
4407
4408 boolean skipDestroy = false;
4409
4410 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004411 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4413 r.configChangeFlags);
4414 } catch (Exception e) {
4415 // We can just ignore exceptions here... if the process
4416 // has crashed, our death notification will clean things
4417 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004418 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004419 if (r.finishing) {
4420 removeActivityFromHistoryLocked(r);
4421 removedFromHistory = true;
4422 skipDestroy = true;
4423 }
4424 }
4425
4426 r.app = null;
4427 r.nowVisible = false;
4428
4429 if (r.finishing && !skipDestroy) {
4430 r.state = ActivityState.DESTROYING;
4431 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4432 msg.obj = r;
4433 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4434 } else {
4435 r.state = ActivityState.DESTROYED;
4436 }
4437 } else {
4438 // remove this record from the history.
4439 if (r.finishing) {
4440 removeActivityFromHistoryLocked(r);
4441 removedFromHistory = true;
4442 } else {
4443 r.state = ActivityState.DESTROYED;
4444 }
4445 }
4446
4447 r.configChangeFlags = 0;
4448
Dianne Hackborn03abb812010-01-04 18:43:19 -08004449 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004450 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 }
4452
4453 return removedFromHistory;
4454 }
4455
Dianne Hackborn03abb812010-01-04 18:43:19 -08004456 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004458 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004459 TAG, "Removing app " + app + " from list " + list
4460 + " with " + i + " entries");
4461 while (i > 0) {
4462 i--;
4463 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004464 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4466 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004467 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 list.remove(i);
4469 }
4470 }
4471 }
4472
4473 /**
4474 * Main function for removing an existing process from the activity manager
4475 * as a result of that process going away. Clears out all connections
4476 * to the process.
4477 */
4478 private final void handleAppDiedLocked(ProcessRecord app,
4479 boolean restarting) {
4480 cleanUpApplicationRecordLocked(app, restarting, -1);
4481 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004482 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004483 }
4484
4485 // Just in case...
4486 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004487 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 mPausingActivity = null;
4489 }
4490 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4491 mLastPausedActivity = null;
4492 }
4493
4494 // Remove this application's activities from active lists.
4495 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4496 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4497 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4498 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4499
4500 boolean atTop = true;
4501 boolean hasVisibleActivities = false;
4502
4503 // Clean out the history list.
4504 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004505 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 TAG, "Removing app " + app + " from history with " + i + " entries");
4507 while (i > 0) {
4508 i--;
4509 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004510 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4512 if (r.app == app) {
4513 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004514 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515 TAG, "Removing this entry! frozen=" + r.haveState
4516 + " finishing=" + r.finishing);
4517 mHistory.remove(i);
4518
4519 r.inHistory = false;
4520 mWindowManager.removeAppToken(r);
4521 if (VALIDATE_TOKENS) {
4522 mWindowManager.validateAppTokens(mHistory);
4523 }
4524 removeActivityUriPermissionsLocked(r);
4525
4526 } else {
4527 // We have the current state for this activity, so
4528 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004529 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004530 TAG, "Keeping entry, setting app to null");
4531 if (r.visible) {
4532 hasVisibleActivities = true;
4533 }
4534 r.app = null;
4535 r.nowVisible = false;
4536 if (!r.haveState) {
4537 r.icicle = null;
4538 }
4539 }
4540
4541 cleanUpActivityLocked(r, true);
4542 r.state = ActivityState.STOPPED;
4543 }
4544 atTop = false;
4545 }
4546
4547 app.activities.clear();
4548
4549 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004550 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 + " running instrumentation " + app.instrumentationClass);
4552 Bundle info = new Bundle();
4553 info.putString("shortMsg", "Process crashed.");
4554 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4555 }
4556
4557 if (!restarting) {
4558 if (!resumeTopActivityLocked(null)) {
4559 // If there was nothing to resume, and we are not already
4560 // restarting this process, but there is a visible activity that
4561 // is hosted by the process... then make sure all visible
4562 // activities are running, taking care of restarting this
4563 // process.
4564 if (hasVisibleActivities) {
4565 ensureActivitiesVisibleLocked(null, 0);
4566 }
4567 }
4568 }
4569 }
4570
4571 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4572 IBinder threadBinder = thread.asBinder();
4573
4574 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004575 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4576 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004577 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4578 return i;
4579 }
4580 }
4581 return -1;
4582 }
4583
4584 private final ProcessRecord getRecordForAppLocked(
4585 IApplicationThread thread) {
4586 if (thread == null) {
4587 return null;
4588 }
4589
4590 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004591 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004592 }
4593
4594 private final void appDiedLocked(ProcessRecord app, int pid,
4595 IApplicationThread thread) {
4596
4597 mProcDeaths[0]++;
4598
Magnus Edlund7bb25812010-02-24 15:45:06 +01004599 // Clean up already done if the process has been re-started.
4600 if (app.pid == pid && app.thread != null &&
4601 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004602 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004604 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004605 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 TAG, "Dying app: " + app + ", pid: " + pid
4607 + ", thread: " + thread.asBinder());
4608 boolean doLowMem = app.instrumentationClass == null;
4609 handleAppDiedLocked(app, false);
4610
4611 if (doLowMem) {
4612 // If there are no longer any background processes running,
4613 // and the app that died was not running instrumentation,
4614 // then tell everyone we are now low on memory.
4615 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004616 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4617 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4619 haveBg = true;
4620 break;
4621 }
4622 }
4623
4624 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004625 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004626 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004627 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004628 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4629 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004630 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004631 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4632 // The low memory report is overriding any current
4633 // state for a GC request. Make sure to do
4634 // visible/foreground processes first.
4635 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4636 rec.lastRequestedGc = 0;
4637 } else {
4638 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004639 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004640 rec.reportLowMemory = true;
4641 rec.lastLowMemory = now;
4642 mProcessesToGc.remove(rec);
4643 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 }
4645 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004646 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647 }
4648 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004649 } else if (app.pid != pid) {
4650 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004651 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004652 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004653 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004654 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004655 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 + thread.asBinder());
4657 }
4658 }
4659
Dan Egnor42471dd2010-01-07 17:25:22 -08004660 /**
4661 * If a stack trace dump file is configured, dump process stack traces.
4662 * @param pids of dalvik VM processes to dump stack traces for
4663 * @return file containing stack traces, or null if no dump file is configured
4664 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004665 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004666 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4667 if (tracesPath == null || tracesPath.length() == 0) {
4668 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004669 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004670
4671 File tracesFile = new File(tracesPath);
4672 try {
4673 File tracesDir = tracesFile.getParentFile();
4674 if (!tracesDir.exists()) tracesFile.mkdirs();
4675 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4676
4677 if (tracesFile.exists()) tracesFile.delete();
4678 tracesFile.createNewFile();
4679 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4680 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004681 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004682 return null;
4683 }
4684
4685 // Use a FileObserver to detect when traces finish writing.
4686 // The order of traces is considered important to maintain for legibility.
4687 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4688 public synchronized void onEvent(int event, String path) { notify(); }
4689 };
4690
4691 try {
4692 observer.startWatching();
4693 int num = pids.size();
4694 for (int i = 0; i < num; i++) {
4695 synchronized (observer) {
4696 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4697 observer.wait(200); // Wait for write-close, give up after 200msec
4698 }
4699 }
4700 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004701 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004702 } finally {
4703 observer.stopWatching();
4704 }
4705
4706 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 }
4708
Dan Egnor42471dd2010-01-07 17:25:22 -08004709 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4710 HistoryRecord parent, final String annotation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 if (app.notResponding || app.crashing) {
4712 return;
4713 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004716 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4717 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004718
Dan Egnor42471dd2010-01-07 17:25:22 -08004719 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4720 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4721 pids.add(app.pid);
4722
4723 int parentPid = app.pid;
4724 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4725 if (parentPid != app.pid) pids.add(parentPid);
4726
4727 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4728
4729 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4730 ProcessRecord r = mLruProcesses.get(i);
4731 if (r != null && r.thread != null) {
4732 int pid = r.pid;
4733 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 }
4735 }
4736
Dan Egnor42471dd2010-01-07 17:25:22 -08004737 File tracesFile = dumpStackTraces(pids);
4738
4739 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004740 StringBuilder info = mStringBuilder;
4741 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004742 info.append("ANR in ").append(app.processName);
4743 if (activity != null && activity.shortComponentName != null) {
4744 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004745 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004746 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004748 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004750 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004751 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004753
Dan Egnor42471dd2010-01-07 17:25:22 -08004754 String cpuInfo = null;
4755 if (MONITOR_CPU_USAGE) {
4756 updateCpuStatsNow();
4757 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4758 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759 }
4760
Joe Onorato8a9b2202010-02-26 18:56:32 -08004761 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004762 if (tracesFile == null) {
4763 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4764 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4765 }
4766
4767 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4768
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004769 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004771 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4772 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004774 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4775 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004776 }
4777 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004778 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004779 }
4780 }
4781
Dan Egnor42471dd2010-01-07 17:25:22 -08004782 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4783 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4784 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4785 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4786 Process.killProcess(app.pid);
4787 return;
4788 }
4789
4790 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 makeAppNotRespondingLocked(app,
4792 activity != null ? activity.shortComponentName : null,
4793 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004794 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004795
4796 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 Message msg = Message.obtain();
4798 HashMap map = new HashMap();
4799 msg.what = SHOW_NOT_RESPONDING_MSG;
4800 msg.obj = map;
4801 map.put("app", app);
4802 if (activity != null) {
4803 map.put("activity", activity);
4804 }
4805
4806 mHandler.sendMessage(msg);
4807 return;
4808 }
4809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004810 private final void decPersistentCountLocked(ProcessRecord app)
4811 {
4812 app.persistentActivities--;
4813 if (app.persistentActivities > 0) {
4814 // Still more of 'em...
4815 return;
4816 }
4817 if (app.persistent) {
4818 // Ah, but the application itself is persistent. Whatever!
4819 return;
4820 }
4821
4822 // App is no longer persistent... make sure it and the ones
4823 // following it in the LRU list have the correc oom_adj.
4824 updateOomAdjLocked();
4825 }
4826
4827 public void setPersistent(IBinder token, boolean isPersistent) {
4828 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4829 != PackageManager.PERMISSION_GRANTED) {
4830 String msg = "Permission Denial: setPersistent() from pid="
4831 + Binder.getCallingPid()
4832 + ", uid=" + Binder.getCallingUid()
4833 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004834 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 throw new SecurityException(msg);
4836 }
4837
4838 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004839 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 if (index < 0) {
4841 return;
4842 }
4843 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4844 ProcessRecord app = r.app;
4845
Joe Onorato8a9b2202010-02-26 18:56:32 -08004846 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 TAG, "Setting persistence " + isPersistent + ": " + r);
4848
4849 if (isPersistent) {
4850 if (r.persistent) {
4851 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004852 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 return;
4854 }
4855 r.persistent = true;
4856 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004857 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 if (app.persistentActivities > 1) {
4859 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004860 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004861 return;
4862 }
4863 if (app.persistent) {
4864 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004865 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 return;
4867 }
4868
4869 // App is now persistent... make sure it and the ones
4870 // following it now have the correct oom_adj.
4871 final long origId = Binder.clearCallingIdentity();
4872 updateOomAdjLocked();
4873 Binder.restoreCallingIdentity(origId);
4874
4875 } else {
4876 if (!r.persistent) {
4877 // Okay okay, I heard you already!
4878 return;
4879 }
4880 r.persistent = false;
4881 final long origId = Binder.clearCallingIdentity();
4882 decPersistentCountLocked(app);
4883 Binder.restoreCallingIdentity(origId);
4884
4885 }
4886 }
4887 }
4888
4889 public boolean clearApplicationUserData(final String packageName,
4890 final IPackageDataObserver observer) {
4891 int uid = Binder.getCallingUid();
4892 int pid = Binder.getCallingPid();
4893 long callingId = Binder.clearCallingIdentity();
4894 try {
4895 IPackageManager pm = ActivityThread.getPackageManager();
4896 int pkgUid = -1;
4897 synchronized(this) {
4898 try {
4899 pkgUid = pm.getPackageUid(packageName);
4900 } catch (RemoteException e) {
4901 }
4902 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004903 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004904 return false;
4905 }
4906 if (uid == pkgUid || checkComponentPermission(
4907 android.Manifest.permission.CLEAR_APP_USER_DATA,
4908 pid, uid, -1)
4909 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004910 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004911 } else {
4912 throw new SecurityException(pid+" does not have permission:"+
4913 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4914 "for process:"+packageName);
4915 }
4916 }
4917
4918 try {
4919 //clear application user data
4920 pm.clearApplicationUserData(packageName, observer);
4921 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4922 Uri.fromParts("package", packageName, null));
4923 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4924 broadcastIntentLocked(null, null, intent,
4925 null, null, 0, null, null, null,
4926 false, false, MY_PID, Process.SYSTEM_UID);
4927 } catch (RemoteException e) {
4928 }
4929 } finally {
4930 Binder.restoreCallingIdentity(callingId);
4931 }
4932 return true;
4933 }
4934
Dianne Hackborn03abb812010-01-04 18:43:19 -08004935 public void killBackgroundProcesses(final String packageName) {
4936 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4937 != PackageManager.PERMISSION_GRANTED &&
4938 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4939 != PackageManager.PERMISSION_GRANTED) {
4940 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 + Binder.getCallingPid()
4942 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004943 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004944 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 throw new SecurityException(msg);
4946 }
4947
4948 long callingId = Binder.clearCallingIdentity();
4949 try {
4950 IPackageManager pm = ActivityThread.getPackageManager();
4951 int pkgUid = -1;
4952 synchronized(this) {
4953 try {
4954 pkgUid = pm.getPackageUid(packageName);
4955 } catch (RemoteException e) {
4956 }
4957 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004958 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 return;
4960 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004961 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004962 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004963 }
4964 } finally {
4965 Binder.restoreCallingIdentity(callingId);
4966 }
4967 }
4968
4969 public void forceStopPackage(final String packageName) {
4970 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4971 != PackageManager.PERMISSION_GRANTED) {
4972 String msg = "Permission Denial: forceStopPackage() from pid="
4973 + Binder.getCallingPid()
4974 + ", uid=" + Binder.getCallingUid()
4975 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004976 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004977 throw new SecurityException(msg);
4978 }
4979
4980 long callingId = Binder.clearCallingIdentity();
4981 try {
4982 IPackageManager pm = ActivityThread.getPackageManager();
4983 int pkgUid = -1;
4984 synchronized(this) {
4985 try {
4986 pkgUid = pm.getPackageUid(packageName);
4987 } catch (RemoteException e) {
4988 }
4989 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004990 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004991 return;
4992 }
4993 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004994 }
4995 } finally {
4996 Binder.restoreCallingIdentity(callingId);
4997 }
4998 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004999
5000 /*
5001 * The pkg name and uid have to be specified.
5002 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5003 */
5004 public void killApplicationWithUid(String pkg, int uid) {
5005 if (pkg == null) {
5006 return;
5007 }
5008 // Make sure the uid is valid.
5009 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005010 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005011 return;
5012 }
5013 int callerUid = Binder.getCallingUid();
5014 // Only the system server can kill an application
5015 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005016 // Post an aysnc message to kill the application
5017 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5018 msg.arg1 = uid;
5019 msg.arg2 = 0;
5020 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005021 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005022 } else {
5023 throw new SecurityException(callerUid + " cannot kill pkg: " +
5024 pkg);
5025 }
5026 }
5027
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005028 public void closeSystemDialogs(String reason) {
5029 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5030 if (reason != null) {
5031 intent.putExtra("reason", reason);
5032 }
5033
5034 final int uid = Binder.getCallingUid();
5035 final long origId = Binder.clearCallingIdentity();
5036 synchronized (this) {
5037 int i = mWatchers.beginBroadcast();
5038 while (i > 0) {
5039 i--;
5040 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5041 if (w != null) {
5042 try {
5043 w.closingSystemDialogs(reason);
5044 } catch (RemoteException e) {
5045 }
5046 }
5047 }
5048 mWatchers.finishBroadcast();
5049
Dianne Hackbornffa42482009-09-23 22:20:11 -07005050 mWindowManager.closeSystemDialogs(reason);
5051
5052 for (i=mHistory.size()-1; i>=0; i--) {
5053 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5054 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5055 finishActivityLocked(r, i,
5056 Activity.RESULT_CANCELED, null, "close-sys");
5057 }
5058 }
5059
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005060 broadcastIntentLocked(null, null, intent, null,
5061 null, 0, null, null, null, false, false, -1, uid);
5062 }
5063 Binder.restoreCallingIdentity(origId);
5064 }
5065
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005066 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005067 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005068 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5069 for (int i=pids.length-1; i>=0; i--) {
5070 infos[i] = new Debug.MemoryInfo();
5071 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005072 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005073 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005074 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005075
5076 public void killApplicationProcess(String processName, int uid) {
5077 if (processName == null) {
5078 return;
5079 }
5080
5081 int callerUid = Binder.getCallingUid();
5082 // Only the system server can kill an application
5083 if (callerUid == Process.SYSTEM_UID) {
5084 synchronized (this) {
5085 ProcessRecord app = getProcessRecordLocked(processName, uid);
5086 if (app != null) {
5087 try {
5088 app.thread.scheduleSuicide();
5089 } catch (RemoteException e) {
5090 // If the other end already died, then our work here is done.
5091 }
5092 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005093 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005094 + processName + " / " + uid);
5095 }
5096 }
5097 } else {
5098 throw new SecurityException(callerUid + " cannot kill app process: " +
5099 processName);
5100 }
5101 }
5102
Dianne Hackborn03abb812010-01-04 18:43:19 -08005103 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005104 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5106 Uri.fromParts("package", packageName, null));
5107 intent.putExtra(Intent.EXTRA_UID, uid);
5108 broadcastIntentLocked(null, null, intent,
5109 null, null, 0, null, null, null,
5110 false, false, MY_PID, Process.SYSTEM_UID);
5111 }
5112
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005113 private final boolean killPackageProcessesLocked(String packageName, int uid,
5114 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005115 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116
Dianne Hackborn03abb812010-01-04 18:43:19 -08005117 // Remove all processes this package may have touched: all with the
5118 // same UID (except for the system or root user), and all whose name
5119 // matches the package name.
5120 final String procNamePrefix = packageName + ":";
5121 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5122 final int NA = apps.size();
5123 for (int ia=0; ia<NA; ia++) {
5124 ProcessRecord app = apps.valueAt(ia);
5125 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005126 if (doit) {
5127 procs.add(app);
5128 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005129 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5130 || app.processName.equals(packageName)
5131 || app.processName.startsWith(procNamePrefix)) {
5132 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005133 if (!doit) {
5134 return true;
5135 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005136 app.removed = true;
5137 procs.add(app);
5138 }
5139 }
5140 }
5141 }
5142
5143 int N = procs.size();
5144 for (int i=0; i<N; i++) {
5145 removeProcessLocked(procs.get(i), callerWillRestart);
5146 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005147 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005148 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005149
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005150 private final boolean forceStopPackageLocked(String name, int uid,
5151 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 int i, N;
5153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 if (uid < 0) {
5155 try {
5156 uid = ActivityThread.getPackageManager().getPackageUid(name);
5157 } catch (RemoteException e) {
5158 }
5159 }
5160
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005161 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005162 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005163
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005164 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5165 while (badApps.hasNext()) {
5166 SparseArray<Long> ba = badApps.next();
5167 if (ba.get(uid) != null) {
5168 badApps.remove();
5169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005170 }
5171 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005172
5173 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5174 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175
5176 for (i=mHistory.size()-1; i>=0; i--) {
5177 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5178 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005179 if (!doit) {
5180 return true;
5181 }
5182 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005183 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184 if (r.app != null) {
5185 r.app.removed = true;
5186 }
5187 r.app = null;
5188 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5189 }
5190 }
5191
5192 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5193 for (ServiceRecord service : mServices.values()) {
5194 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005195 if (!doit) {
5196 return true;
5197 }
5198 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005199 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 if (service.app != null) {
5201 service.app.removed = true;
5202 }
5203 service.app = null;
5204 services.add(service);
5205 }
5206 }
5207
5208 N = services.size();
5209 for (i=0; i<N; i++) {
5210 bringDownServiceLocked(services.get(i), true);
5211 }
5212
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005213 if (doit) {
5214 if (purgeCache) {
5215 AttributeCache ac = AttributeCache.instance();
5216 if (ac != null) {
5217 ac.removePackage(name);
5218 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005219 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005220 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005221 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005222
5223 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 }
5225
5226 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5227 final String name = app.processName;
5228 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005229 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005230 TAG, "Force removing process " + app + " (" + name
5231 + "/" + uid + ")");
5232
5233 mProcessNames.remove(name, uid);
5234 boolean needRestart = false;
5235 if (app.pid > 0 && app.pid != MY_PID) {
5236 int pid = app.pid;
5237 synchronized (mPidsSelfLocked) {
5238 mPidsSelfLocked.remove(pid);
5239 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5240 }
5241 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005242 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 Process.killProcess(pid);
5244
5245 if (app.persistent) {
5246 if (!callerWillRestart) {
5247 addAppLocked(app.info);
5248 } else {
5249 needRestart = true;
5250 }
5251 }
5252 } else {
5253 mRemovedProcesses.add(app);
5254 }
5255
5256 return needRestart;
5257 }
5258
5259 private final void processStartTimedOutLocked(ProcessRecord app) {
5260 final int pid = app.pid;
5261 boolean gone = false;
5262 synchronized (mPidsSelfLocked) {
5263 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5264 if (knownApp != null && knownApp.thread == null) {
5265 mPidsSelfLocked.remove(pid);
5266 gone = true;
5267 }
5268 }
5269
5270 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005271 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005272 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005273 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005275 // Take care of any launching providers waiting for this process.
5276 checkAppInLaunchingProvidersLocked(app, true);
5277 // Take care of any services that are waiting for the process.
5278 for (int i=0; i<mPendingServices.size(); i++) {
5279 ServiceRecord sr = mPendingServices.get(i);
5280 if (app.info.uid == sr.appInfo.uid
5281 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005282 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005283 mPendingServices.remove(i);
5284 i--;
5285 bringDownServiceLocked(sr, true);
5286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005288 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005289 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005290 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005291 try {
5292 IBackupManager bm = IBackupManager.Stub.asInterface(
5293 ServiceManager.getService(Context.BACKUP_SERVICE));
5294 bm.agentDisconnected(app.info.packageName);
5295 } catch (RemoteException e) {
5296 // Can't happen; the backup manager is local
5297 }
5298 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005299 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005300 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005301 mPendingBroadcast = null;
5302 scheduleBroadcastsLocked();
5303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005305 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005306 }
5307 }
5308
5309 private final boolean attachApplicationLocked(IApplicationThread thread,
5310 int pid) {
5311
5312 // Find the application record that is being attached... either via
5313 // the pid if we are running in multiple processes, or just pull the
5314 // next app record if we are emulating process with anonymous threads.
5315 ProcessRecord app;
5316 if (pid != MY_PID && pid >= 0) {
5317 synchronized (mPidsSelfLocked) {
5318 app = mPidsSelfLocked.get(pid);
5319 }
5320 } else if (mStartingProcesses.size() > 0) {
5321 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005322 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 } else {
5324 app = null;
5325 }
5326
5327 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005328 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005330 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 if (pid > 0 && pid != MY_PID) {
5332 Process.killProcess(pid);
5333 } else {
5334 try {
5335 thread.scheduleExit();
5336 } catch (Exception e) {
5337 // Ignore exceptions.
5338 }
5339 }
5340 return false;
5341 }
5342
5343 // If this application record is still attached to a previous
5344 // process, clean it up now.
5345 if (app.thread != null) {
5346 handleAppDiedLocked(app, true);
5347 }
5348
5349 // Tell the process all about itself.
5350
Joe Onorato8a9b2202010-02-26 18:56:32 -08005351 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 TAG, "Binding process pid " + pid + " to record " + app);
5353
5354 String processName = app.processName;
5355 try {
5356 thread.asBinder().linkToDeath(new AppDeathRecipient(
5357 app, pid, thread), 0);
5358 } catch (RemoteException e) {
5359 app.resetPackageList();
5360 startProcessLocked(app, "link fail", processName);
5361 return false;
5362 }
5363
Doug Zongker2bec3d42009-12-04 12:52:44 -08005364 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365
5366 app.thread = thread;
5367 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005368 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5369 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005370 app.forcingToForeground = null;
5371 app.foregroundServices = false;
5372 app.debugging = false;
5373
5374 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5375
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005376 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5377 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005378
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005379 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005380 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005381 }
5382
Joe Onorato8a9b2202010-02-26 18:56:32 -08005383 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005384 TAG, "New app record " + app
5385 + " thread=" + thread.asBinder() + " pid=" + pid);
5386 try {
5387 int testMode = IApplicationThread.DEBUG_OFF;
5388 if (mDebugApp != null && mDebugApp.equals(processName)) {
5389 testMode = mWaitForDebugger
5390 ? IApplicationThread.DEBUG_WAIT
5391 : IApplicationThread.DEBUG_ON;
5392 app.debugging = true;
5393 if (mDebugTransient) {
5394 mDebugApp = mOrigDebugApp;
5395 mWaitForDebugger = mOrigWaitForDebugger;
5396 }
5397 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005398
Christopher Tate181fafa2009-05-14 11:12:14 -07005399 // If the app is being launched for restore or full backup, set it up specially
5400 boolean isRestrictedBackupMode = false;
5401 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5402 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5403 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5404 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005405
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005406 ensurePackageDexOpt(app.instrumentationInfo != null
5407 ? app.instrumentationInfo.packageName
5408 : app.info.packageName);
5409 if (app.instrumentationClass != null) {
5410 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005411 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005412 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005413 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005414 thread.bindApplication(processName, app.instrumentationInfo != null
5415 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005416 app.instrumentationClass, app.instrumentationProfileFile,
5417 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005418 isRestrictedBackupMode || !normalMode,
5419 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005420 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005421 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005422 } catch (Exception e) {
5423 // todo: Yikes! What should we do? For now we will try to
5424 // start another process, but that could easily get us in
5425 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005426 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427
5428 app.resetPackageList();
5429 startProcessLocked(app, "bind fail", processName);
5430 return false;
5431 }
5432
5433 // Remove this record from the list of starting applications.
5434 mPersistentStartingProcesses.remove(app);
5435 mProcessesOnHold.remove(app);
5436
5437 boolean badApp = false;
5438 boolean didSomething = false;
5439
5440 // See if the top visible activity is waiting to run in this process...
5441 HistoryRecord hr = topRunningActivityLocked(null);
5442 if (hr != null) {
5443 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5444 && processName.equals(hr.processName)) {
5445 try {
5446 if (realStartActivityLocked(hr, app, true, true)) {
5447 didSomething = true;
5448 }
5449 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005450 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 + hr.intent.getComponent().flattenToShortString(), e);
5452 badApp = true;
5453 }
5454 } else {
5455 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5456 }
5457 }
5458
5459 // Find any services that should be running in this process...
5460 if (!badApp && mPendingServices.size() > 0) {
5461 ServiceRecord sr = null;
5462 try {
5463 for (int i=0; i<mPendingServices.size(); i++) {
5464 sr = mPendingServices.get(i);
5465 if (app.info.uid != sr.appInfo.uid
5466 || !processName.equals(sr.processName)) {
5467 continue;
5468 }
5469
5470 mPendingServices.remove(i);
5471 i--;
5472 realStartServiceLocked(sr, app);
5473 didSomething = true;
5474 }
5475 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005476 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005477 + sr.shortName, e);
5478 badApp = true;
5479 }
5480 }
5481
5482 // Check if the next broadcast receiver is in this process...
5483 BroadcastRecord br = mPendingBroadcast;
5484 if (!badApp && br != null && br.curApp == app) {
5485 try {
5486 mPendingBroadcast = null;
5487 processCurBroadcastLocked(br, app);
5488 didSomething = true;
5489 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005490 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005491 + br.curComponent.flattenToShortString(), e);
5492 badApp = true;
5493 logBroadcastReceiverDiscard(br);
5494 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5495 br.resultExtras, br.resultAbort, true);
5496 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005497 // We need to reset the state if we fails to start the receiver.
5498 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 }
5500 }
5501
Christopher Tate181fafa2009-05-14 11:12:14 -07005502 // Check whether the next backup agent is in this process...
5503 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005504 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005505 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005506 try {
5507 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5508 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005509 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005510 e.printStackTrace();
5511 }
5512 }
5513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 if (badApp) {
5515 // todo: Also need to kill application to deal with all
5516 // kinds of exceptions.
5517 handleAppDiedLocked(app, false);
5518 return false;
5519 }
5520
5521 if (!didSomething) {
5522 updateOomAdjLocked();
5523 }
5524
5525 return true;
5526 }
5527
5528 public final void attachApplication(IApplicationThread thread) {
5529 synchronized (this) {
5530 int callingPid = Binder.getCallingPid();
5531 final long origId = Binder.clearCallingIdentity();
5532 attachApplicationLocked(thread, callingPid);
5533 Binder.restoreCallingIdentity(origId);
5534 }
5535 }
5536
Dianne Hackborne88846e2009-09-30 21:34:25 -07005537 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005538 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005539 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005540 Binder.restoreCallingIdentity(origId);
5541 }
5542
5543 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5544 boolean remove) {
5545 int N = mStoppingActivities.size();
5546 if (N <= 0) return null;
5547
5548 ArrayList<HistoryRecord> stops = null;
5549
5550 final boolean nowVisible = mResumedActivity != null
5551 && mResumedActivity.nowVisible
5552 && !mResumedActivity.waitingVisible;
5553 for (int i=0; i<N; i++) {
5554 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005555 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005556 + nowVisible + " waitingVisible=" + s.waitingVisible
5557 + " finishing=" + s.finishing);
5558 if (s.waitingVisible && nowVisible) {
5559 mWaitingVisibleActivities.remove(s);
5560 s.waitingVisible = false;
5561 if (s.finishing) {
5562 // If this activity is finishing, it is sitting on top of
5563 // everyone else but we now know it is no longer needed...
5564 // so get rid of it. Otherwise, we need to go through the
5565 // normal flow and hide it once we determine that it is
5566 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005567 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005568 mWindowManager.setAppVisibility(s, false);
5569 }
5570 }
5571 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005572 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 if (stops == null) {
5574 stops = new ArrayList<HistoryRecord>();
5575 }
5576 stops.add(s);
5577 mStoppingActivities.remove(i);
5578 N--;
5579 i--;
5580 }
5581 }
5582
5583 return stops;
5584 }
5585
5586 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005587 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005588 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005589 mWindowManager.enableScreenAfterBoot();
5590 }
5591
Dianne Hackborne88846e2009-09-30 21:34:25 -07005592 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5593 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005594 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005595
5596 ArrayList<HistoryRecord> stops = null;
5597 ArrayList<HistoryRecord> finishes = null;
5598 ArrayList<HistoryRecord> thumbnails = null;
5599 int NS = 0;
5600 int NF = 0;
5601 int NT = 0;
5602 IApplicationThread sendThumbnail = null;
5603 boolean booting = false;
5604 boolean enableScreen = false;
5605
5606 synchronized (this) {
5607 if (token != null) {
5608 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5609 }
5610
5611 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005612 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 if (index >= 0) {
5614 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5615
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005616 if (fromTimeout) {
5617 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5618 }
5619
Dianne Hackborne88846e2009-09-30 21:34:25 -07005620 // This is a hack to semi-deal with a race condition
5621 // in the client where it can be constructed with a
5622 // newer configuration from when we asked it to launch.
5623 // We'll update with whatever configuration it now says
5624 // it used to launch.
5625 if (config != null) {
5626 r.configuration = config;
5627 }
5628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629 // No longer need to keep the device awake.
5630 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5631 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5632 mLaunchingActivity.release();
5633 }
5634
5635 // We are now idle. If someone is waiting for a thumbnail from
5636 // us, we can now deliver.
5637 r.idle = true;
5638 scheduleAppGcsLocked();
5639 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5640 sendThumbnail = r.app.thread;
5641 r.thumbnailNeeded = false;
5642 }
5643
5644 // If this activity is fullscreen, set up to hide those under it.
5645
Joe Onorato8a9b2202010-02-26 18:56:32 -08005646 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 ensureActivitiesVisibleLocked(null, 0);
5648
Joe Onorato8a9b2202010-02-26 18:56:32 -08005649 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005650 if (!mBooted && !fromTimeout) {
5651 mBooted = true;
5652 enableScreen = true;
5653 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005654
5655 } else if (fromTimeout) {
5656 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005657 }
5658
5659 // Atomically retrieve all of the other things to do.
5660 stops = processStoppingActivitiesLocked(true);
5661 NS = stops != null ? stops.size() : 0;
5662 if ((NF=mFinishingActivities.size()) > 0) {
5663 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5664 mFinishingActivities.clear();
5665 }
5666 if ((NT=mCancelledThumbnails.size()) > 0) {
5667 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5668 mCancelledThumbnails.clear();
5669 }
5670
5671 booting = mBooting;
5672 mBooting = false;
5673 }
5674
5675 int i;
5676
5677 // Send thumbnail if requested.
5678 if (sendThumbnail != null) {
5679 try {
5680 sendThumbnail.requestThumbnail(token);
5681 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005682 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005683 sendPendingThumbnail(null, token, null, null, true);
5684 }
5685 }
5686
5687 // Stop any activities that are scheduled to do so but have been
5688 // waiting for the next one to start.
5689 for (i=0; i<NS; i++) {
5690 HistoryRecord r = (HistoryRecord)stops.get(i);
5691 synchronized (this) {
5692 if (r.finishing) {
5693 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5694 } else {
5695 stopActivityLocked(r);
5696 }
5697 }
5698 }
5699
5700 // Finish any activities that are scheduled to do so but have been
5701 // waiting for the next one to start.
5702 for (i=0; i<NF; i++) {
5703 HistoryRecord r = (HistoryRecord)finishes.get(i);
5704 synchronized (this) {
5705 destroyActivityLocked(r, true);
5706 }
5707 }
5708
5709 // Report back to any thumbnail receivers.
5710 for (i=0; i<NT; i++) {
5711 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5712 sendPendingThumbnail(r, null, null, null, true);
5713 }
5714
5715 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005716 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 }
5718
5719 trimApplications();
5720 //dump();
5721 //mWindowManager.dump();
5722
5723 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 enableScreenAfterBoot();
5725 }
5726 }
5727
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005728 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005729 IntentFilter pkgFilter = new IntentFilter();
5730 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5731 pkgFilter.addDataScheme("package");
5732 mContext.registerReceiver(new BroadcastReceiver() {
5733 @Override
5734 public void onReceive(Context context, Intent intent) {
5735 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5736 if (pkgs != null) {
5737 for (String pkg : pkgs) {
5738 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5739 setResultCode(Activity.RESULT_OK);
5740 return;
5741 }
5742 }
5743 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005744 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005745 }, pkgFilter);
5746
5747 synchronized (this) {
5748 // Ensure that any processes we had put on hold are now started
5749 // up.
5750 final int NP = mProcessesOnHold.size();
5751 if (NP > 0) {
5752 ArrayList<ProcessRecord> procs =
5753 new ArrayList<ProcessRecord>(mProcessesOnHold);
5754 for (int ip=0; ip<NP; ip++) {
5755 this.startProcessLocked(procs.get(ip), "on-hold", null);
5756 }
5757 }
5758
5759 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5760 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005761 broadcastIntentLocked(null, null,
5762 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5763 null, null, 0, null, null,
5764 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5765 false, false, MY_PID, Process.SYSTEM_UID);
5766 }
5767 }
5768 }
5769
5770 final void ensureBootCompleted() {
5771 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005772 boolean enableScreen;
5773 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005774 booting = mBooting;
5775 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005776 enableScreen = !mBooted;
5777 mBooted = true;
5778 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005779
5780 if (booting) {
5781 finishBooting();
5782 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005783
5784 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005785 enableScreenAfterBoot();
5786 }
5787 }
5788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005789 public final void activityPaused(IBinder token, Bundle icicle) {
5790 // Refuse possible leaked file descriptors
5791 if (icicle != null && icicle.hasFileDescriptors()) {
5792 throw new IllegalArgumentException("File descriptors passed in Bundle");
5793 }
5794
5795 final long origId = Binder.clearCallingIdentity();
5796 activityPaused(token, icicle, false);
5797 Binder.restoreCallingIdentity(origId);
5798 }
5799
5800 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005801 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005802 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5803 + ", timeout=" + timeout);
5804
5805 HistoryRecord r = null;
5806
5807 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005808 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005809 if (index >= 0) {
5810 r = (HistoryRecord)mHistory.get(index);
5811 if (!timeout) {
5812 r.icicle = icicle;
5813 r.haveState = true;
5814 }
5815 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5816 if (mPausingActivity == r) {
5817 r.state = ActivityState.PAUSED;
5818 completePauseLocked();
5819 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005820 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005821 System.identityHashCode(r), r.shortComponentName,
5822 mPausingActivity != null
5823 ? mPausingActivity.shortComponentName : "(none)");
5824 }
5825 }
5826 }
5827 }
5828
5829 public final void activityStopped(IBinder token, Bitmap thumbnail,
5830 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005831 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 TAG, "Activity stopped: token=" + token);
5833
5834 HistoryRecord r = null;
5835
5836 final long origId = Binder.clearCallingIdentity();
5837
5838 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005839 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 if (index >= 0) {
5841 r = (HistoryRecord)mHistory.get(index);
5842 r.thumbnail = thumbnail;
5843 r.description = description;
5844 r.stopped = true;
5845 r.state = ActivityState.STOPPED;
5846 if (!r.finishing) {
5847 if (r.configDestroy) {
5848 destroyActivityLocked(r, true);
5849 resumeTopActivityLocked(null);
5850 }
5851 }
5852 }
5853 }
5854
5855 if (r != null) {
5856 sendPendingThumbnail(r, null, null, null, false);
5857 }
5858
5859 trimApplications();
5860
5861 Binder.restoreCallingIdentity(origId);
5862 }
5863
5864 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005865 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 synchronized (this) {
5867 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5868
Dianne Hackborn75b03852009-06-12 15:43:26 -07005869 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005870 if (index >= 0) {
5871 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5872 if (r.state == ActivityState.DESTROYING) {
5873 final long origId = Binder.clearCallingIdentity();
5874 removeActivityFromHistoryLocked(r);
5875 Binder.restoreCallingIdentity(origId);
5876 }
5877 }
5878 }
5879 }
5880
5881 public String getCallingPackage(IBinder token) {
5882 synchronized (this) {
5883 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005884 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005885 }
5886 }
5887
5888 public ComponentName getCallingActivity(IBinder token) {
5889 synchronized (this) {
5890 HistoryRecord r = getCallingRecordLocked(token);
5891 return r != null ? r.intent.getComponent() : null;
5892 }
5893 }
5894
5895 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005896 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 if (index >= 0) {
5898 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5899 if (r != null) {
5900 return r.resultTo;
5901 }
5902 }
5903 return null;
5904 }
5905
5906 public ComponentName getActivityClassForToken(IBinder token) {
5907 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005908 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005909 if (index >= 0) {
5910 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5911 return r.intent.getComponent();
5912 }
5913 return null;
5914 }
5915 }
5916
5917 public String getPackageForToken(IBinder token) {
5918 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005919 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005920 if (index >= 0) {
5921 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5922 return r.packageName;
5923 }
5924 return null;
5925 }
5926 }
5927
5928 public IIntentSender getIntentSender(int type,
5929 String packageName, IBinder token, String resultWho,
5930 int requestCode, Intent intent, String resolvedType, int flags) {
5931 // Refuse possible leaked file descriptors
5932 if (intent != null && intent.hasFileDescriptors() == true) {
5933 throw new IllegalArgumentException("File descriptors passed in Intent");
5934 }
5935
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005936 if (type == INTENT_SENDER_BROADCAST) {
5937 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5938 throw new IllegalArgumentException(
5939 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5940 }
5941 }
5942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943 synchronized(this) {
5944 int callingUid = Binder.getCallingUid();
5945 try {
5946 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5947 Process.supportsProcesses()) {
5948 int uid = ActivityThread.getPackageManager()
5949 .getPackageUid(packageName);
5950 if (uid != Binder.getCallingUid()) {
5951 String msg = "Permission Denial: getIntentSender() from pid="
5952 + Binder.getCallingPid()
5953 + ", uid=" + Binder.getCallingUid()
5954 + ", (need uid=" + uid + ")"
5955 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005956 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 throw new SecurityException(msg);
5958 }
5959 }
5960 } catch (RemoteException e) {
5961 throw new SecurityException(e);
5962 }
5963 HistoryRecord activity = null;
5964 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005965 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005966 if (index < 0) {
5967 return null;
5968 }
5969 activity = (HistoryRecord)mHistory.get(index);
5970 if (activity.finishing) {
5971 return null;
5972 }
5973 }
5974
5975 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5976 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5977 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5978 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5979 |PendingIntent.FLAG_UPDATE_CURRENT);
5980
5981 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5982 type, packageName, activity, resultWho,
5983 requestCode, intent, resolvedType, flags);
5984 WeakReference<PendingIntentRecord> ref;
5985 ref = mIntentSenderRecords.get(key);
5986 PendingIntentRecord rec = ref != null ? ref.get() : null;
5987 if (rec != null) {
5988 if (!cancelCurrent) {
5989 if (updateCurrent) {
5990 rec.key.requestIntent.replaceExtras(intent);
5991 }
5992 return rec;
5993 }
5994 rec.canceled = true;
5995 mIntentSenderRecords.remove(key);
5996 }
5997 if (noCreate) {
5998 return rec;
5999 }
6000 rec = new PendingIntentRecord(this, key, callingUid);
6001 mIntentSenderRecords.put(key, rec.ref);
6002 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6003 if (activity.pendingResults == null) {
6004 activity.pendingResults
6005 = new HashSet<WeakReference<PendingIntentRecord>>();
6006 }
6007 activity.pendingResults.add(rec.ref);
6008 }
6009 return rec;
6010 }
6011 }
6012
6013 public void cancelIntentSender(IIntentSender sender) {
6014 if (!(sender instanceof PendingIntentRecord)) {
6015 return;
6016 }
6017 synchronized(this) {
6018 PendingIntentRecord rec = (PendingIntentRecord)sender;
6019 try {
6020 int uid = ActivityThread.getPackageManager()
6021 .getPackageUid(rec.key.packageName);
6022 if (uid != Binder.getCallingUid()) {
6023 String msg = "Permission Denial: cancelIntentSender() from pid="
6024 + Binder.getCallingPid()
6025 + ", uid=" + Binder.getCallingUid()
6026 + " is not allowed to cancel packges "
6027 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006028 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006029 throw new SecurityException(msg);
6030 }
6031 } catch (RemoteException e) {
6032 throw new SecurityException(e);
6033 }
6034 cancelIntentSenderLocked(rec, true);
6035 }
6036 }
6037
6038 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6039 rec.canceled = true;
6040 mIntentSenderRecords.remove(rec.key);
6041 if (cleanActivity && rec.key.activity != null) {
6042 rec.key.activity.pendingResults.remove(rec.ref);
6043 }
6044 }
6045
6046 public String getPackageForIntentSender(IIntentSender pendingResult) {
6047 if (!(pendingResult instanceof PendingIntentRecord)) {
6048 return null;
6049 }
6050 synchronized(this) {
6051 try {
6052 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6053 return res.key.packageName;
6054 } catch (ClassCastException e) {
6055 }
6056 }
6057 return null;
6058 }
6059
6060 public void setProcessLimit(int max) {
6061 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6062 "setProcessLimit()");
6063 mProcessLimit = max;
6064 }
6065
6066 public int getProcessLimit() {
6067 return mProcessLimit;
6068 }
6069
6070 void foregroundTokenDied(ForegroundToken token) {
6071 synchronized (ActivityManagerService.this) {
6072 synchronized (mPidsSelfLocked) {
6073 ForegroundToken cur
6074 = mForegroundProcesses.get(token.pid);
6075 if (cur != token) {
6076 return;
6077 }
6078 mForegroundProcesses.remove(token.pid);
6079 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6080 if (pr == null) {
6081 return;
6082 }
6083 pr.forcingToForeground = null;
6084 pr.foregroundServices = false;
6085 }
6086 updateOomAdjLocked();
6087 }
6088 }
6089
6090 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6091 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6092 "setProcessForeground()");
6093 synchronized(this) {
6094 boolean changed = false;
6095
6096 synchronized (mPidsSelfLocked) {
6097 ProcessRecord pr = mPidsSelfLocked.get(pid);
6098 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006099 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 return;
6101 }
6102 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6103 if (oldToken != null) {
6104 oldToken.token.unlinkToDeath(oldToken, 0);
6105 mForegroundProcesses.remove(pid);
6106 pr.forcingToForeground = null;
6107 changed = true;
6108 }
6109 if (isForeground && token != null) {
6110 ForegroundToken newToken = new ForegroundToken() {
6111 public void binderDied() {
6112 foregroundTokenDied(this);
6113 }
6114 };
6115 newToken.pid = pid;
6116 newToken.token = token;
6117 try {
6118 token.linkToDeath(newToken, 0);
6119 mForegroundProcesses.put(pid, newToken);
6120 pr.forcingToForeground = token;
6121 changed = true;
6122 } catch (RemoteException e) {
6123 // If the process died while doing this, we will later
6124 // do the cleanup with the process death link.
6125 }
6126 }
6127 }
6128
6129 if (changed) {
6130 updateOomAdjLocked();
6131 }
6132 }
6133 }
6134
6135 // =========================================================
6136 // PERMISSIONS
6137 // =========================================================
6138
6139 static class PermissionController extends IPermissionController.Stub {
6140 ActivityManagerService mActivityManagerService;
6141 PermissionController(ActivityManagerService activityManagerService) {
6142 mActivityManagerService = activityManagerService;
6143 }
6144
6145 public boolean checkPermission(String permission, int pid, int uid) {
6146 return mActivityManagerService.checkPermission(permission, pid,
6147 uid) == PackageManager.PERMISSION_GRANTED;
6148 }
6149 }
6150
6151 /**
6152 * This can be called with or without the global lock held.
6153 */
6154 int checkComponentPermission(String permission, int pid, int uid,
6155 int reqUid) {
6156 // We might be performing an operation on behalf of an indirect binder
6157 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6158 // client identity accordingly before proceeding.
6159 Identity tlsIdentity = sCallerIdentity.get();
6160 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006161 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006162 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6163 uid = tlsIdentity.uid;
6164 pid = tlsIdentity.pid;
6165 }
6166
6167 // Root, system server and our own process get to do everything.
6168 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6169 !Process.supportsProcesses()) {
6170 return PackageManager.PERMISSION_GRANTED;
6171 }
6172 // If the target requires a specific UID, always fail for others.
6173 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006174 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006175 return PackageManager.PERMISSION_DENIED;
6176 }
6177 if (permission == null) {
6178 return PackageManager.PERMISSION_GRANTED;
6179 }
6180 try {
6181 return ActivityThread.getPackageManager()
6182 .checkUidPermission(permission, uid);
6183 } catch (RemoteException e) {
6184 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006185 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006186 }
6187 return PackageManager.PERMISSION_DENIED;
6188 }
6189
6190 /**
6191 * As the only public entry point for permissions checking, this method
6192 * can enforce the semantic that requesting a check on a null global
6193 * permission is automatically denied. (Internally a null permission
6194 * string is used when calling {@link #checkComponentPermission} in cases
6195 * when only uid-based security is needed.)
6196 *
6197 * This can be called with or without the global lock held.
6198 */
6199 public int checkPermission(String permission, int pid, int uid) {
6200 if (permission == null) {
6201 return PackageManager.PERMISSION_DENIED;
6202 }
6203 return checkComponentPermission(permission, pid, uid, -1);
6204 }
6205
6206 /**
6207 * Binder IPC calls go through the public entry point.
6208 * This can be called with or without the global lock held.
6209 */
6210 int checkCallingPermission(String permission) {
6211 return checkPermission(permission,
6212 Binder.getCallingPid(),
6213 Binder.getCallingUid());
6214 }
6215
6216 /**
6217 * This can be called with or without the global lock held.
6218 */
6219 void enforceCallingPermission(String permission, String func) {
6220 if (checkCallingPermission(permission)
6221 == PackageManager.PERMISSION_GRANTED) {
6222 return;
6223 }
6224
6225 String msg = "Permission Denial: " + func + " from pid="
6226 + Binder.getCallingPid()
6227 + ", uid=" + Binder.getCallingUid()
6228 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006229 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230 throw new SecurityException(msg);
6231 }
6232
6233 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6234 ProviderInfo pi, int uid, int modeFlags) {
6235 try {
6236 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6237 if ((pi.readPermission != null) &&
6238 (pm.checkUidPermission(pi.readPermission, uid)
6239 != PackageManager.PERMISSION_GRANTED)) {
6240 return false;
6241 }
6242 }
6243 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6244 if ((pi.writePermission != null) &&
6245 (pm.checkUidPermission(pi.writePermission, uid)
6246 != PackageManager.PERMISSION_GRANTED)) {
6247 return false;
6248 }
6249 }
6250 return true;
6251 } catch (RemoteException e) {
6252 return false;
6253 }
6254 }
6255
6256 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6257 int modeFlags) {
6258 // Root gets to do everything.
6259 if (uid == 0 || !Process.supportsProcesses()) {
6260 return true;
6261 }
6262 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6263 if (perms == null) return false;
6264 UriPermission perm = perms.get(uri);
6265 if (perm == null) return false;
6266 return (modeFlags&perm.modeFlags) == modeFlags;
6267 }
6268
6269 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6270 // Another redirected-binder-call permissions check as in
6271 // {@link checkComponentPermission}.
6272 Identity tlsIdentity = sCallerIdentity.get();
6273 if (tlsIdentity != null) {
6274 uid = tlsIdentity.uid;
6275 pid = tlsIdentity.pid;
6276 }
6277
6278 // Our own process gets to do everything.
6279 if (pid == MY_PID) {
6280 return PackageManager.PERMISSION_GRANTED;
6281 }
6282 synchronized(this) {
6283 return checkUriPermissionLocked(uri, uid, modeFlags)
6284 ? PackageManager.PERMISSION_GRANTED
6285 : PackageManager.PERMISSION_DENIED;
6286 }
6287 }
6288
6289 private void grantUriPermissionLocked(int callingUid,
6290 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6291 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6292 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6293 if (modeFlags == 0) {
6294 return;
6295 }
6296
Joe Onorato8a9b2202010-02-26 18:56:32 -08006297 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006298 "Requested grant " + targetPkg + " permission to " + uri);
6299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006300 final IPackageManager pm = ActivityThread.getPackageManager();
6301
6302 // If this is not a content: uri, we can't do anything with it.
6303 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006304 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006305 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006306 return;
6307 }
6308
6309 String name = uri.getAuthority();
6310 ProviderInfo pi = null;
6311 ContentProviderRecord cpr
6312 = (ContentProviderRecord)mProvidersByName.get(name);
6313 if (cpr != null) {
6314 pi = cpr.info;
6315 } else {
6316 try {
6317 pi = pm.resolveContentProvider(name,
6318 PackageManager.GET_URI_PERMISSION_PATTERNS);
6319 } catch (RemoteException ex) {
6320 }
6321 }
6322 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006323 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006324 return;
6325 }
6326
6327 int targetUid;
6328 try {
6329 targetUid = pm.getPackageUid(targetPkg);
6330 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006331 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006332 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006333 return;
6334 }
6335 } catch (RemoteException ex) {
6336 return;
6337 }
6338
6339 // First... does the target actually need this permission?
6340 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6341 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006342 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006343 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006344 return;
6345 }
6346
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006347 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006348 if (!pi.grantUriPermissions) {
6349 throw new SecurityException("Provider " + pi.packageName
6350 + "/" + pi.name
6351 + " does not allow granting of Uri permissions (uri "
6352 + uri + ")");
6353 }
6354 if (pi.uriPermissionPatterns != null) {
6355 final int N = pi.uriPermissionPatterns.length;
6356 boolean allowed = false;
6357 for (int i=0; i<N; i++) {
6358 if (pi.uriPermissionPatterns[i] != null
6359 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6360 allowed = true;
6361 break;
6362 }
6363 }
6364 if (!allowed) {
6365 throw new SecurityException("Provider " + pi.packageName
6366 + "/" + pi.name
6367 + " does not allow granting of permission to path of Uri "
6368 + uri);
6369 }
6370 }
6371
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006372 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006373 // this uri?
6374 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6375 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6376 throw new SecurityException("Uid " + callingUid
6377 + " does not have permission to uri " + uri);
6378 }
6379 }
6380
6381 // Okay! So here we are: the caller has the assumed permission
6382 // to the uri, and the target doesn't. Let's now give this to
6383 // the target.
6384
Joe Onorato8a9b2202010-02-26 18:56:32 -08006385 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006386 "Granting " + targetPkg + " permission to " + uri);
6387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006388 HashMap<Uri, UriPermission> targetUris
6389 = mGrantedUriPermissions.get(targetUid);
6390 if (targetUris == null) {
6391 targetUris = new HashMap<Uri, UriPermission>();
6392 mGrantedUriPermissions.put(targetUid, targetUris);
6393 }
6394
6395 UriPermission perm = targetUris.get(uri);
6396 if (perm == null) {
6397 perm = new UriPermission(targetUid, uri);
6398 targetUris.put(uri, perm);
6399
6400 }
6401 perm.modeFlags |= modeFlags;
6402 if (activity == null) {
6403 perm.globalModeFlags |= modeFlags;
6404 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6405 perm.readActivities.add(activity);
6406 if (activity.readUriPermissions == null) {
6407 activity.readUriPermissions = new HashSet<UriPermission>();
6408 }
6409 activity.readUriPermissions.add(perm);
6410 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6411 perm.writeActivities.add(activity);
6412 if (activity.writeUriPermissions == null) {
6413 activity.writeUriPermissions = new HashSet<UriPermission>();
6414 }
6415 activity.writeUriPermissions.add(perm);
6416 }
6417 }
6418
6419 private void grantUriPermissionFromIntentLocked(int callingUid,
6420 String targetPkg, Intent intent, HistoryRecord activity) {
6421 if (intent == null) {
6422 return;
6423 }
6424 Uri data = intent.getData();
6425 if (data == null) {
6426 return;
6427 }
6428 grantUriPermissionLocked(callingUid, targetPkg, data,
6429 intent.getFlags(), activity);
6430 }
6431
6432 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6433 Uri uri, int modeFlags) {
6434 synchronized(this) {
6435 final ProcessRecord r = getRecordForAppLocked(caller);
6436 if (r == null) {
6437 throw new SecurityException("Unable to find app for caller "
6438 + caller
6439 + " when granting permission to uri " + uri);
6440 }
6441 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006442 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006443 return;
6444 }
6445 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006446 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006447 return;
6448 }
6449
6450 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6451 null);
6452 }
6453 }
6454
6455 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6456 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6457 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6458 HashMap<Uri, UriPermission> perms
6459 = mGrantedUriPermissions.get(perm.uid);
6460 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006461 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006462 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006463 perms.remove(perm.uri);
6464 if (perms.size() == 0) {
6465 mGrantedUriPermissions.remove(perm.uid);
6466 }
6467 }
6468 }
6469 }
6470
6471 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6472 if (activity.readUriPermissions != null) {
6473 for (UriPermission perm : activity.readUriPermissions) {
6474 perm.readActivities.remove(activity);
6475 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6476 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6477 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6478 removeUriPermissionIfNeededLocked(perm);
6479 }
6480 }
6481 }
6482 if (activity.writeUriPermissions != null) {
6483 for (UriPermission perm : activity.writeUriPermissions) {
6484 perm.writeActivities.remove(activity);
6485 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6486 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6487 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6488 removeUriPermissionIfNeededLocked(perm);
6489 }
6490 }
6491 }
6492 }
6493
6494 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6495 int modeFlags) {
6496 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6497 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6498 if (modeFlags == 0) {
6499 return;
6500 }
6501
Joe Onorato8a9b2202010-02-26 18:56:32 -08006502 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006503 "Revoking all granted permissions to " + uri);
6504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006505 final IPackageManager pm = ActivityThread.getPackageManager();
6506
6507 final String authority = uri.getAuthority();
6508 ProviderInfo pi = null;
6509 ContentProviderRecord cpr
6510 = (ContentProviderRecord)mProvidersByName.get(authority);
6511 if (cpr != null) {
6512 pi = cpr.info;
6513 } else {
6514 try {
6515 pi = pm.resolveContentProvider(authority,
6516 PackageManager.GET_URI_PERMISSION_PATTERNS);
6517 } catch (RemoteException ex) {
6518 }
6519 }
6520 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006521 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006522 return;
6523 }
6524
6525 // Does the caller have this permission on the URI?
6526 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6527 // Right now, if you are not the original owner of the permission,
6528 // you are not allowed to revoke it.
6529 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6530 throw new SecurityException("Uid " + callingUid
6531 + " does not have permission to uri " + uri);
6532 //}
6533 }
6534
6535 // Go through all of the permissions and remove any that match.
6536 final List<String> SEGMENTS = uri.getPathSegments();
6537 if (SEGMENTS != null) {
6538 final int NS = SEGMENTS.size();
6539 int N = mGrantedUriPermissions.size();
6540 for (int i=0; i<N; i++) {
6541 HashMap<Uri, UriPermission> perms
6542 = mGrantedUriPermissions.valueAt(i);
6543 Iterator<UriPermission> it = perms.values().iterator();
6544 toploop:
6545 while (it.hasNext()) {
6546 UriPermission perm = it.next();
6547 Uri targetUri = perm.uri;
6548 if (!authority.equals(targetUri.getAuthority())) {
6549 continue;
6550 }
6551 List<String> targetSegments = targetUri.getPathSegments();
6552 if (targetSegments == null) {
6553 continue;
6554 }
6555 if (targetSegments.size() < NS) {
6556 continue;
6557 }
6558 for (int j=0; j<NS; j++) {
6559 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6560 continue toploop;
6561 }
6562 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006563 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006564 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006565 perm.clearModes(modeFlags);
6566 if (perm.modeFlags == 0) {
6567 it.remove();
6568 }
6569 }
6570 if (perms.size() == 0) {
6571 mGrantedUriPermissions.remove(
6572 mGrantedUriPermissions.keyAt(i));
6573 N--;
6574 i--;
6575 }
6576 }
6577 }
6578 }
6579
6580 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6581 int modeFlags) {
6582 synchronized(this) {
6583 final ProcessRecord r = getRecordForAppLocked(caller);
6584 if (r == null) {
6585 throw new SecurityException("Unable to find app for caller "
6586 + caller
6587 + " when revoking permission to uri " + uri);
6588 }
6589 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006590 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006591 return;
6592 }
6593
6594 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6595 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6596 if (modeFlags == 0) {
6597 return;
6598 }
6599
6600 final IPackageManager pm = ActivityThread.getPackageManager();
6601
6602 final String authority = uri.getAuthority();
6603 ProviderInfo pi = null;
6604 ContentProviderRecord cpr
6605 = (ContentProviderRecord)mProvidersByName.get(authority);
6606 if (cpr != null) {
6607 pi = cpr.info;
6608 } else {
6609 try {
6610 pi = pm.resolveContentProvider(authority,
6611 PackageManager.GET_URI_PERMISSION_PATTERNS);
6612 } catch (RemoteException ex) {
6613 }
6614 }
6615 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006616 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006617 return;
6618 }
6619
6620 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6621 }
6622 }
6623
6624 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6625 synchronized (this) {
6626 ProcessRecord app =
6627 who != null ? getRecordForAppLocked(who) : null;
6628 if (app == null) return;
6629
6630 Message msg = Message.obtain();
6631 msg.what = WAIT_FOR_DEBUGGER_MSG;
6632 msg.obj = app;
6633 msg.arg1 = waiting ? 1 : 0;
6634 mHandler.sendMessage(msg);
6635 }
6636 }
6637
6638 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6639 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006640 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006641 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006642 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006643 }
6644
6645 // =========================================================
6646 // TASK MANAGEMENT
6647 // =========================================================
6648
6649 public List getTasks(int maxNum, int flags,
6650 IThumbnailReceiver receiver) {
6651 ArrayList list = new ArrayList();
6652
6653 PendingThumbnailsRecord pending = null;
6654 IApplicationThread topThumbnail = null;
6655 HistoryRecord topRecord = null;
6656
6657 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006658 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006659 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6660 + ", receiver=" + receiver);
6661
6662 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6663 != PackageManager.PERMISSION_GRANTED) {
6664 if (receiver != null) {
6665 // If the caller wants to wait for pending thumbnails,
6666 // it ain't gonna get them.
6667 try {
6668 receiver.finished();
6669 } catch (RemoteException ex) {
6670 }
6671 }
6672 String msg = "Permission Denial: getTasks() from pid="
6673 + Binder.getCallingPid()
6674 + ", uid=" + Binder.getCallingUid()
6675 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006676 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006677 throw new SecurityException(msg);
6678 }
6679
6680 int pos = mHistory.size()-1;
6681 HistoryRecord next =
6682 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6683 HistoryRecord top = null;
6684 CharSequence topDescription = null;
6685 TaskRecord curTask = null;
6686 int numActivities = 0;
6687 int numRunning = 0;
6688 while (pos >= 0 && maxNum > 0) {
6689 final HistoryRecord r = next;
6690 pos--;
6691 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6692
6693 // Initialize state for next task if needed.
6694 if (top == null ||
6695 (top.state == ActivityState.INITIALIZING
6696 && top.task == r.task)) {
6697 top = r;
6698 topDescription = r.description;
6699 curTask = r.task;
6700 numActivities = numRunning = 0;
6701 }
6702
6703 // Add 'r' into the current task.
6704 numActivities++;
6705 if (r.app != null && r.app.thread != null) {
6706 numRunning++;
6707 }
6708 if (topDescription == null) {
6709 topDescription = r.description;
6710 }
6711
Joe Onorato8a9b2202010-02-26 18:56:32 -08006712 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006713 TAG, r.intent.getComponent().flattenToShortString()
6714 + ": task=" + r.task);
6715
6716 // If the next one is a different task, generate a new
6717 // TaskInfo entry for what we have.
6718 if (next == null || next.task != curTask) {
6719 ActivityManager.RunningTaskInfo ci
6720 = new ActivityManager.RunningTaskInfo();
6721 ci.id = curTask.taskId;
6722 ci.baseActivity = r.intent.getComponent();
6723 ci.topActivity = top.intent.getComponent();
6724 ci.thumbnail = top.thumbnail;
6725 ci.description = topDescription;
6726 ci.numActivities = numActivities;
6727 ci.numRunning = numRunning;
6728 //System.out.println(
6729 // "#" + maxNum + ": " + " descr=" + ci.description);
6730 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006731 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 TAG, "State=" + top.state + "Idle=" + top.idle
6733 + " app=" + top.app
6734 + " thr=" + (top.app != null ? top.app.thread : null));
6735 if (top.state == ActivityState.RESUMED
6736 || top.state == ActivityState.PAUSING) {
6737 if (top.idle && top.app != null
6738 && top.app.thread != null) {
6739 topRecord = top;
6740 topThumbnail = top.app.thread;
6741 } else {
6742 top.thumbnailNeeded = true;
6743 }
6744 }
6745 if (pending == null) {
6746 pending = new PendingThumbnailsRecord(receiver);
6747 }
6748 pending.pendingRecords.add(top);
6749 }
6750 list.add(ci);
6751 maxNum--;
6752 top = null;
6753 }
6754 }
6755
6756 if (pending != null) {
6757 mPendingThumbnails.add(pending);
6758 }
6759 }
6760
Joe Onorato8a9b2202010-02-26 18:56:32 -08006761 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006762
6763 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006764 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006765 try {
6766 topThumbnail.requestThumbnail(topRecord);
6767 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006768 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769 sendPendingThumbnail(null, topRecord, null, null, true);
6770 }
6771 }
6772
6773 if (pending == null && receiver != null) {
6774 // In this case all thumbnails were available and the client
6775 // is being asked to be told when the remaining ones come in...
6776 // which is unusually, since the top-most currently running
6777 // activity should never have a canned thumbnail! Oh well.
6778 try {
6779 receiver.finished();
6780 } catch (RemoteException ex) {
6781 }
6782 }
6783
6784 return list;
6785 }
6786
6787 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6788 int flags) {
6789 synchronized (this) {
6790 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6791 "getRecentTasks()");
6792
6793 final int N = mRecentTasks.size();
6794 ArrayList<ActivityManager.RecentTaskInfo> res
6795 = new ArrayList<ActivityManager.RecentTaskInfo>(
6796 maxNum < N ? maxNum : N);
6797 for (int i=0; i<N && maxNum > 0; i++) {
6798 TaskRecord tr = mRecentTasks.get(i);
6799 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6800 || (tr.intent == null)
6801 || ((tr.intent.getFlags()
6802 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6803 ActivityManager.RecentTaskInfo rti
6804 = new ActivityManager.RecentTaskInfo();
6805 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6806 rti.baseIntent = new Intent(
6807 tr.intent != null ? tr.intent : tr.affinityIntent);
6808 rti.origActivity = tr.origActivity;
6809 res.add(rti);
6810 maxNum--;
6811 }
6812 }
6813 return res;
6814 }
6815 }
6816
6817 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6818 int j;
6819 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6820 TaskRecord jt = startTask;
6821
6822 // First look backwards
6823 for (j=startIndex-1; j>=0; j--) {
6824 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6825 if (r.task != jt) {
6826 jt = r.task;
6827 if (affinity.equals(jt.affinity)) {
6828 return j;
6829 }
6830 }
6831 }
6832
6833 // Now look forwards
6834 final int N = mHistory.size();
6835 jt = startTask;
6836 for (j=startIndex+1; j<N; j++) {
6837 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6838 if (r.task != jt) {
6839 if (affinity.equals(jt.affinity)) {
6840 return j;
6841 }
6842 jt = r.task;
6843 }
6844 }
6845
6846 // Might it be at the top?
6847 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6848 return N-1;
6849 }
6850
6851 return -1;
6852 }
6853
6854 /**
6855 * Perform a reset of the given task, if needed as part of launching it.
6856 * Returns the new HistoryRecord at the top of the task.
6857 */
6858 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6859 HistoryRecord newActivity) {
6860 boolean forceReset = (newActivity.info.flags
6861 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6862 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6863 if ((newActivity.info.flags
6864 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6865 forceReset = true;
6866 }
6867 }
6868
6869 final TaskRecord task = taskTop.task;
6870
6871 // We are going to move through the history list so that we can look
6872 // at each activity 'target' with 'below' either the interesting
6873 // activity immediately below it in the stack or null.
6874 HistoryRecord target = null;
6875 int targetI = 0;
6876 int taskTopI = -1;
6877 int replyChainEnd = -1;
6878 int lastReparentPos = -1;
6879 for (int i=mHistory.size()-1; i>=-1; i--) {
6880 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6881
6882 if (below != null && below.finishing) {
6883 continue;
6884 }
6885 if (target == null) {
6886 target = below;
6887 targetI = i;
6888 // If we were in the middle of a reply chain before this
6889 // task, it doesn't appear like the root of the chain wants
6890 // anything interesting, so drop it.
6891 replyChainEnd = -1;
6892 continue;
6893 }
6894
6895 final int flags = target.info.flags;
6896
6897 final boolean finishOnTaskLaunch =
6898 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6899 final boolean allowTaskReparenting =
6900 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6901
6902 if (target.task == task) {
6903 // We are inside of the task being reset... we'll either
6904 // finish this activity, push it out for another task,
6905 // or leave it as-is. We only do this
6906 // for activities that are not the root of the task (since
6907 // if we finish the root, we may no longer have the task!).
6908 if (taskTopI < 0) {
6909 taskTopI = targetI;
6910 }
6911 if (below != null && below.task == task) {
6912 final boolean clearWhenTaskReset =
6913 (target.intent.getFlags()
6914 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006915 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006916 // If this activity is sending a reply to a previous
6917 // activity, we can't do anything with it now until
6918 // we reach the start of the reply chain.
6919 // XXX note that we are assuming the result is always
6920 // to the previous activity, which is almost always
6921 // the case but we really shouldn't count on.
6922 if (replyChainEnd < 0) {
6923 replyChainEnd = targetI;
6924 }
Ed Heyl73798232009-03-24 21:32:21 -07006925 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006926 && target.taskAffinity != null
6927 && !target.taskAffinity.equals(task.affinity)) {
6928 // If this activity has an affinity for another
6929 // task, then we need to move it out of here. We will
6930 // move it as far out of the way as possible, to the
6931 // bottom of the activity stack. This also keeps it
6932 // correctly ordered with any activities we previously
6933 // moved.
6934 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6935 if (target.taskAffinity != null
6936 && target.taskAffinity.equals(p.task.affinity)) {
6937 // If the activity currently at the bottom has the
6938 // same task affinity as the one we are moving,
6939 // then merge it into the same task.
6940 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006941 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006942 + " out to bottom task " + p.task);
6943 } else {
6944 mCurTask++;
6945 if (mCurTask <= 0) {
6946 mCurTask = 1;
6947 }
6948 target.task = new TaskRecord(mCurTask, target.info, null,
6949 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6950 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006951 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006952 + " out to new task " + target.task);
6953 }
6954 mWindowManager.setAppGroupId(target, task.taskId);
6955 if (replyChainEnd < 0) {
6956 replyChainEnd = targetI;
6957 }
6958 int dstPos = 0;
6959 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6960 p = (HistoryRecord)mHistory.get(srcPos);
6961 if (p.finishing) {
6962 continue;
6963 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006964 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 + " out to target's task " + target.task);
6966 task.numActivities--;
6967 p.task = target.task;
6968 target.task.numActivities++;
6969 mHistory.remove(srcPos);
6970 mHistory.add(dstPos, p);
6971 mWindowManager.moveAppToken(dstPos, p);
6972 mWindowManager.setAppGroupId(p, p.task.taskId);
6973 dstPos++;
6974 if (VALIDATE_TOKENS) {
6975 mWindowManager.validateAppTokens(mHistory);
6976 }
6977 i++;
6978 }
6979 if (taskTop == p) {
6980 taskTop = below;
6981 }
6982 if (taskTopI == replyChainEnd) {
6983 taskTopI = -1;
6984 }
6985 replyChainEnd = -1;
6986 addRecentTask(target.task);
6987 } else if (forceReset || finishOnTaskLaunch
6988 || clearWhenTaskReset) {
6989 // If the activity should just be removed -- either
6990 // because it asks for it, or the task should be
6991 // cleared -- then finish it and anything that is
6992 // part of its reply chain.
6993 if (clearWhenTaskReset) {
6994 // In this case, we want to finish this activity
6995 // and everything above it, so be sneaky and pretend
6996 // like these are all in the reply chain.
6997 replyChainEnd = targetI+1;
6998 while (replyChainEnd < mHistory.size() &&
6999 ((HistoryRecord)mHistory.get(
7000 replyChainEnd)).task == task) {
7001 replyChainEnd++;
7002 }
7003 replyChainEnd--;
7004 } else if (replyChainEnd < 0) {
7005 replyChainEnd = targetI;
7006 }
7007 HistoryRecord p = null;
7008 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7009 p = (HistoryRecord)mHistory.get(srcPos);
7010 if (p.finishing) {
7011 continue;
7012 }
7013 if (finishActivityLocked(p, srcPos,
7014 Activity.RESULT_CANCELED, null, "reset")) {
7015 replyChainEnd--;
7016 srcPos--;
7017 }
7018 }
7019 if (taskTop == p) {
7020 taskTop = below;
7021 }
7022 if (taskTopI == replyChainEnd) {
7023 taskTopI = -1;
7024 }
7025 replyChainEnd = -1;
7026 } else {
7027 // If we were in the middle of a chain, well the
7028 // activity that started it all doesn't want anything
7029 // special, so leave it all as-is.
7030 replyChainEnd = -1;
7031 }
7032 } else {
7033 // Reached the bottom of the task -- any reply chain
7034 // should be left as-is.
7035 replyChainEnd = -1;
7036 }
7037
7038 } else if (target.resultTo != null) {
7039 // If this activity is sending a reply to a previous
7040 // activity, we can't do anything with it now until
7041 // we reach the start of the reply chain.
7042 // XXX note that we are assuming the result is always
7043 // to the previous activity, which is almost always
7044 // the case but we really shouldn't count on.
7045 if (replyChainEnd < 0) {
7046 replyChainEnd = targetI;
7047 }
7048
7049 } else if (taskTopI >= 0 && allowTaskReparenting
7050 && task.affinity != null
7051 && task.affinity.equals(target.taskAffinity)) {
7052 // We are inside of another task... if this activity has
7053 // an affinity for our task, then either remove it if we are
7054 // clearing or move it over to our task. Note that
7055 // we currently punt on the case where we are resetting a
7056 // task that is not at the top but who has activities above
7057 // with an affinity to it... this is really not a normal
7058 // case, and we will need to later pull that task to the front
7059 // and usually at that point we will do the reset and pick
7060 // up those remaining activities. (This only happens if
7061 // someone starts an activity in a new task from an activity
7062 // in a task that is not currently on top.)
7063 if (forceReset || finishOnTaskLaunch) {
7064 if (replyChainEnd < 0) {
7065 replyChainEnd = targetI;
7066 }
7067 HistoryRecord p = null;
7068 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7069 p = (HistoryRecord)mHistory.get(srcPos);
7070 if (p.finishing) {
7071 continue;
7072 }
7073 if (finishActivityLocked(p, srcPos,
7074 Activity.RESULT_CANCELED, null, "reset")) {
7075 taskTopI--;
7076 lastReparentPos--;
7077 replyChainEnd--;
7078 srcPos--;
7079 }
7080 }
7081 replyChainEnd = -1;
7082 } else {
7083 if (replyChainEnd < 0) {
7084 replyChainEnd = targetI;
7085 }
7086 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7087 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7088 if (p.finishing) {
7089 continue;
7090 }
7091 if (lastReparentPos < 0) {
7092 lastReparentPos = taskTopI;
7093 taskTop = p;
7094 } else {
7095 lastReparentPos--;
7096 }
7097 mHistory.remove(srcPos);
7098 p.task.numActivities--;
7099 p.task = task;
7100 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007101 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007102 + " in to resetting task " + task);
7103 task.numActivities++;
7104 mWindowManager.moveAppToken(lastReparentPos, p);
7105 mWindowManager.setAppGroupId(p, p.task.taskId);
7106 if (VALIDATE_TOKENS) {
7107 mWindowManager.validateAppTokens(mHistory);
7108 }
7109 }
7110 replyChainEnd = -1;
7111
7112 // Now we've moved it in to place... but what if this is
7113 // a singleTop activity and we have put it on top of another
7114 // instance of the same activity? Then we drop the instance
7115 // below so it remains singleTop.
7116 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7117 for (int j=lastReparentPos-1; j>=0; j--) {
7118 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7119 if (p.finishing) {
7120 continue;
7121 }
7122 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7123 if (finishActivityLocked(p, j,
7124 Activity.RESULT_CANCELED, null, "replace")) {
7125 taskTopI--;
7126 lastReparentPos--;
7127 }
7128 }
7129 }
7130 }
7131 }
7132 }
7133
7134 target = below;
7135 targetI = i;
7136 }
7137
7138 return taskTop;
7139 }
7140
7141 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007142 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007143 */
7144 public void moveTaskToFront(int task) {
7145 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7146 "moveTaskToFront()");
7147
7148 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007149 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7150 Binder.getCallingUid(), "Task to front")) {
7151 return;
7152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007153 final long origId = Binder.clearCallingIdentity();
7154 try {
7155 int N = mRecentTasks.size();
7156 for (int i=0; i<N; i++) {
7157 TaskRecord tr = mRecentTasks.get(i);
7158 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007159 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007160 return;
7161 }
7162 }
7163 for (int i=mHistory.size()-1; i>=0; i--) {
7164 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7165 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007166 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007167 return;
7168 }
7169 }
7170 } finally {
7171 Binder.restoreCallingIdentity(origId);
7172 }
7173 }
7174 }
7175
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007176 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007177 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007178
7179 final int task = tr.taskId;
7180 int top = mHistory.size()-1;
7181
7182 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7183 // nothing to do!
7184 return;
7185 }
7186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007187 ArrayList moved = new ArrayList();
7188
7189 // Applying the affinities may have removed entries from the history,
7190 // so get the size again.
7191 top = mHistory.size()-1;
7192 int pos = top;
7193
7194 // Shift all activities with this task up to the top
7195 // of the stack, keeping them in the same internal order.
7196 while (pos >= 0) {
7197 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007198 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007199 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7200 boolean first = true;
7201 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007202 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007203 mHistory.remove(pos);
7204 mHistory.add(top, r);
7205 moved.add(0, r);
7206 top--;
7207 if (first) {
7208 addRecentTask(r.task);
7209 first = false;
7210 }
7211 }
7212 pos--;
7213 }
7214
Joe Onorato8a9b2202010-02-26 18:56:32 -08007215 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007216 "Prepare to front transition: task=" + tr);
7217 if (reason != null &&
7218 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7219 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7220 HistoryRecord r = topRunningActivityLocked(null);
7221 if (r != null) {
7222 mNoAnimActivities.add(r);
7223 }
7224 } else {
7225 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7226 }
7227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 mWindowManager.moveAppTokensToTop(moved);
7229 if (VALIDATE_TOKENS) {
7230 mWindowManager.validateAppTokens(mHistory);
7231 }
7232
7233 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007234 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007235 }
7236
7237 private final void finishTaskMove(int task) {
7238 resumeTopActivityLocked(null);
7239 }
7240
7241 public void moveTaskToBack(int task) {
7242 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7243 "moveTaskToBack()");
7244
7245 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007246 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7247 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7248 Binder.getCallingUid(), "Task to back")) {
7249 return;
7250 }
7251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007253 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007254 Binder.restoreCallingIdentity(origId);
7255 }
7256 }
7257
7258 /**
7259 * Moves an activity, and all of the other activities within the same task, to the bottom
7260 * of the history stack. The activity's order within the task is unchanged.
7261 *
7262 * @param token A reference to the activity we wish to move
7263 * @param nonRoot If false then this only works if the activity is the root
7264 * of a task; if true it will work for any activity in a task.
7265 * @return Returns true if the move completed, false if not.
7266 */
7267 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7268 synchronized(this) {
7269 final long origId = Binder.clearCallingIdentity();
7270 int taskId = getTaskForActivityLocked(token, !nonRoot);
7271 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007272 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273 }
7274 Binder.restoreCallingIdentity(origId);
7275 }
7276 return false;
7277 }
7278
7279 /**
7280 * Worker method for rearranging history stack. Implements the function of moving all
7281 * activities for a specific task (gathering them if disjoint) into a single group at the
7282 * bottom of the stack.
7283 *
7284 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7285 * to premeptively cancel the move.
7286 *
7287 * @param task The taskId to collect and move to the bottom.
7288 * @return Returns true if the move completed, false if not.
7289 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007290 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007291 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007292
7293 // If we have a watcher, preflight the move before committing to it. First check
7294 // for *other* available tasks, but if none are available, then try again allowing the
7295 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007296 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007297 HistoryRecord next = topRunningActivityLocked(null, task);
7298 if (next == null) {
7299 next = topRunningActivityLocked(null, 0);
7300 }
7301 if (next != null) {
7302 // ask watcher if this is allowed
7303 boolean moveOK = true;
7304 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007305 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007307 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 }
7309 if (!moveOK) {
7310 return false;
7311 }
7312 }
7313 }
7314
7315 ArrayList moved = new ArrayList();
7316
Joe Onorato8a9b2202010-02-26 18:56:32 -08007317 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007318 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007319
7320 final int N = mHistory.size();
7321 int bottom = 0;
7322 int pos = 0;
7323
7324 // Shift all activities with this task down to the bottom
7325 // of the stack, keeping them in the same internal order.
7326 while (pos < N) {
7327 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007328 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7330 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007331 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007332 mHistory.remove(pos);
7333 mHistory.add(bottom, r);
7334 moved.add(r);
7335 bottom++;
7336 }
7337 pos++;
7338 }
7339
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007340 if (reason != null &&
7341 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7342 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7343 HistoryRecord r = topRunningActivityLocked(null);
7344 if (r != null) {
7345 mNoAnimActivities.add(r);
7346 }
7347 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007348 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 mWindowManager.moveAppTokensToBottom(moved);
7351 if (VALIDATE_TOKENS) {
7352 mWindowManager.validateAppTokens(mHistory);
7353 }
7354
7355 finishTaskMove(task);
7356 return true;
7357 }
7358
7359 public void moveTaskBackwards(int task) {
7360 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7361 "moveTaskBackwards()");
7362
7363 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007364 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7365 Binder.getCallingUid(), "Task backwards")) {
7366 return;
7367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 final long origId = Binder.clearCallingIdentity();
7369 moveTaskBackwardsLocked(task);
7370 Binder.restoreCallingIdentity(origId);
7371 }
7372 }
7373
7374 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007375 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 }
7377
7378 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7379 synchronized(this) {
7380 return getTaskForActivityLocked(token, onlyRoot);
7381 }
7382 }
7383
7384 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7385 final int N = mHistory.size();
7386 TaskRecord lastTask = null;
7387 for (int i=0; i<N; i++) {
7388 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7389 if (r == token) {
7390 if (!onlyRoot || lastTask != r.task) {
7391 return r.task.taskId;
7392 }
7393 return -1;
7394 }
7395 lastTask = r.task;
7396 }
7397
7398 return -1;
7399 }
7400
7401 /**
7402 * Returns the top activity in any existing task matching the given
7403 * Intent. Returns null if no such task is found.
7404 */
7405 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7406 ComponentName cls = intent.getComponent();
7407 if (info.targetActivity != null) {
7408 cls = new ComponentName(info.packageName, info.targetActivity);
7409 }
7410
7411 TaskRecord cp = null;
7412
7413 final int N = mHistory.size();
7414 for (int i=(N-1); i>=0; i--) {
7415 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7416 if (!r.finishing && r.task != cp
7417 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7418 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007419 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007420 // + "/aff=" + r.task.affinity + " to new cls="
7421 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7422 if (r.task.affinity != null) {
7423 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007424 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007425 return r;
7426 }
7427 } else if (r.task.intent != null
7428 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007429 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007431 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432 return r;
7433 } else if (r.task.affinityIntent != null
7434 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007435 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007437 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 return r;
7439 }
7440 }
7441 }
7442
7443 return null;
7444 }
7445
7446 /**
7447 * Returns the first activity (starting from the top of the stack) that
7448 * is the same as the given activity. Returns null if no such activity
7449 * is found.
7450 */
7451 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7452 ComponentName cls = intent.getComponent();
7453 if (info.targetActivity != null) {
7454 cls = new ComponentName(info.packageName, info.targetActivity);
7455 }
7456
7457 final int N = mHistory.size();
7458 for (int i=(N-1); i>=0; i--) {
7459 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7460 if (!r.finishing) {
7461 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007462 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007463 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007464 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 return r;
7466 }
7467 }
7468 }
7469
7470 return null;
7471 }
7472
7473 public void finishOtherInstances(IBinder token, ComponentName className) {
7474 synchronized(this) {
7475 final long origId = Binder.clearCallingIdentity();
7476
7477 int N = mHistory.size();
7478 TaskRecord lastTask = null;
7479 for (int i=0; i<N; i++) {
7480 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7481 if (r.realActivity.equals(className)
7482 && r != token && lastTask != r.task) {
7483 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7484 null, "others")) {
7485 i--;
7486 N--;
7487 }
7488 }
7489 lastTask = r.task;
7490 }
7491
7492 Binder.restoreCallingIdentity(origId);
7493 }
7494 }
7495
7496 // =========================================================
7497 // THUMBNAILS
7498 // =========================================================
7499
7500 public void reportThumbnail(IBinder token,
7501 Bitmap thumbnail, CharSequence description) {
7502 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7503 final long origId = Binder.clearCallingIdentity();
7504 sendPendingThumbnail(null, token, thumbnail, description, true);
7505 Binder.restoreCallingIdentity(origId);
7506 }
7507
7508 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7509 Bitmap thumbnail, CharSequence description, boolean always) {
7510 TaskRecord task = null;
7511 ArrayList receivers = null;
7512
7513 //System.out.println("Send pending thumbnail: " + r);
7514
7515 synchronized(this) {
7516 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007517 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007518 if (index < 0) {
7519 return;
7520 }
7521 r = (HistoryRecord)mHistory.get(index);
7522 }
7523 if (thumbnail == null) {
7524 thumbnail = r.thumbnail;
7525 description = r.description;
7526 }
7527 if (thumbnail == null && !always) {
7528 // If there is no thumbnail, and this entry is not actually
7529 // going away, then abort for now and pick up the next
7530 // thumbnail we get.
7531 return;
7532 }
7533 task = r.task;
7534
7535 int N = mPendingThumbnails.size();
7536 int i=0;
7537 while (i<N) {
7538 PendingThumbnailsRecord pr =
7539 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7540 //System.out.println("Looking in " + pr.pendingRecords);
7541 if (pr.pendingRecords.remove(r)) {
7542 if (receivers == null) {
7543 receivers = new ArrayList();
7544 }
7545 receivers.add(pr);
7546 if (pr.pendingRecords.size() == 0) {
7547 pr.finished = true;
7548 mPendingThumbnails.remove(i);
7549 N--;
7550 continue;
7551 }
7552 }
7553 i++;
7554 }
7555 }
7556
7557 if (receivers != null) {
7558 final int N = receivers.size();
7559 for (int i=0; i<N; i++) {
7560 try {
7561 PendingThumbnailsRecord pr =
7562 (PendingThumbnailsRecord)receivers.get(i);
7563 pr.receiver.newThumbnail(
7564 task != null ? task.taskId : -1, thumbnail, description);
7565 if (pr.finished) {
7566 pr.receiver.finished();
7567 }
7568 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007569 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 }
7571 }
7572 }
7573 }
7574
7575 // =========================================================
7576 // CONTENT PROVIDERS
7577 // =========================================================
7578
7579 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7580 List providers = null;
7581 try {
7582 providers = ActivityThread.getPackageManager().
7583 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007584 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007585 } catch (RemoteException ex) {
7586 }
7587 if (providers != null) {
7588 final int N = providers.size();
7589 for (int i=0; i<N; i++) {
7590 ProviderInfo cpi =
7591 (ProviderInfo)providers.get(i);
7592 ContentProviderRecord cpr =
7593 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7594 if (cpr == null) {
7595 cpr = new ContentProviderRecord(cpi, app.info);
7596 mProvidersByClass.put(cpi.name, cpr);
7597 }
7598 app.pubProviders.put(cpi.name, cpr);
7599 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007600 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007601 }
7602 }
7603 return providers;
7604 }
7605
7606 private final String checkContentProviderPermissionLocked(
7607 ProviderInfo cpi, ProcessRecord r, int mode) {
7608 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7609 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7610 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7611 cpi.exported ? -1 : cpi.applicationInfo.uid)
7612 == PackageManager.PERMISSION_GRANTED
7613 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7614 return null;
7615 }
7616 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7617 cpi.exported ? -1 : cpi.applicationInfo.uid)
7618 == PackageManager.PERMISSION_GRANTED) {
7619 return null;
7620 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007621
7622 PathPermission[] pps = cpi.pathPermissions;
7623 if (pps != null) {
7624 int i = pps.length;
7625 while (i > 0) {
7626 i--;
7627 PathPermission pp = pps[i];
7628 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7629 cpi.exported ? -1 : cpi.applicationInfo.uid)
7630 == PackageManager.PERMISSION_GRANTED
7631 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7632 return null;
7633 }
7634 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7635 cpi.exported ? -1 : cpi.applicationInfo.uid)
7636 == PackageManager.PERMISSION_GRANTED) {
7637 return null;
7638 }
7639 }
7640 }
7641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007642 String msg = "Permission Denial: opening provider " + cpi.name
7643 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7644 + ", uid=" + callingUid + ") requires "
7645 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007646 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007647 return msg;
7648 }
7649
7650 private final ContentProviderHolder getContentProviderImpl(
7651 IApplicationThread caller, String name) {
7652 ContentProviderRecord cpr;
7653 ProviderInfo cpi = null;
7654
7655 synchronized(this) {
7656 ProcessRecord r = null;
7657 if (caller != null) {
7658 r = getRecordForAppLocked(caller);
7659 if (r == null) {
7660 throw new SecurityException(
7661 "Unable to find app for caller " + caller
7662 + " (pid=" + Binder.getCallingPid()
7663 + ") when getting content provider " + name);
7664 }
7665 }
7666
7667 // First check if this content provider has been published...
7668 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7669 if (cpr != null) {
7670 cpi = cpr.info;
7671 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7672 return new ContentProviderHolder(cpi,
7673 cpi.readPermission != null
7674 ? cpi.readPermission : cpi.writePermission);
7675 }
7676
7677 if (r != null && cpr.canRunHere(r)) {
7678 // This provider has been published or is in the process
7679 // of being published... but it is also allowed to run
7680 // in the caller's process, so don't make a connection
7681 // and just let the caller instantiate its own instance.
7682 if (cpr.provider != null) {
7683 // don't give caller the provider object, it needs
7684 // to make its own.
7685 cpr = new ContentProviderRecord(cpr);
7686 }
7687 return cpr;
7688 }
7689
7690 final long origId = Binder.clearCallingIdentity();
7691
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007692 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007693 // return it right away.
7694 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007695 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007696 "Adding provider requested by "
7697 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007698 + cpr.info.processName);
7699 Integer cnt = r.conProviders.get(cpr);
7700 if (cnt == null) {
7701 r.conProviders.put(cpr, new Integer(1));
7702 } else {
7703 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705 cpr.clients.add(r);
7706 } else {
7707 cpr.externals++;
7708 }
7709
7710 if (cpr.app != null) {
7711 updateOomAdjLocked(cpr.app);
7712 }
7713
7714 Binder.restoreCallingIdentity(origId);
7715
7716 } else {
7717 try {
7718 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007719 resolveContentProvider(name,
7720 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007721 } catch (RemoteException ex) {
7722 }
7723 if (cpi == null) {
7724 return null;
7725 }
7726
7727 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7728 return new ContentProviderHolder(cpi,
7729 cpi.readPermission != null
7730 ? cpi.readPermission : cpi.writePermission);
7731 }
7732
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007733 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7734 && !cpi.processName.equals("system")) {
7735 // If this content provider does not run in the system
7736 // process, and the system is not yet ready to run other
7737 // processes, then fail fast instead of hanging.
7738 throw new IllegalArgumentException(
7739 "Attempt to launch content provider before system ready");
7740 }
7741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7743 final boolean firstClass = cpr == null;
7744 if (firstClass) {
7745 try {
7746 ApplicationInfo ai =
7747 ActivityThread.getPackageManager().
7748 getApplicationInfo(
7749 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007750 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007752 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007753 + cpi.name);
7754 return null;
7755 }
7756 cpr = new ContentProviderRecord(cpi, ai);
7757 } catch (RemoteException ex) {
7758 // pm is in same process, this will never happen.
7759 }
7760 }
7761
7762 if (r != null && cpr.canRunHere(r)) {
7763 // If this is a multiprocess provider, then just return its
7764 // info and allow the caller to instantiate it. Only do
7765 // this if the provider is the same user as the caller's
7766 // process, or can run as root (so can be in any process).
7767 return cpr;
7768 }
7769
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007770 if (DEBUG_PROVIDER) {
7771 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007772 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007773 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774 }
7775
7776 // This is single process, and our app is now connecting to it.
7777 // See if we are already in the process of launching this
7778 // provider.
7779 final int N = mLaunchingProviders.size();
7780 int i;
7781 for (i=0; i<N; i++) {
7782 if (mLaunchingProviders.get(i) == cpr) {
7783 break;
7784 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 }
7786
7787 // If the provider is not already being launched, then get it
7788 // started.
7789 if (i >= N) {
7790 final long origId = Binder.clearCallingIdentity();
7791 ProcessRecord proc = startProcessLocked(cpi.processName,
7792 cpr.appInfo, false, 0, "content provider",
7793 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007794 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007795 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007796 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 + cpi.applicationInfo.packageName + "/"
7798 + cpi.applicationInfo.uid + " for provider "
7799 + name + ": process is bad");
7800 return null;
7801 }
7802 cpr.launchingApp = proc;
7803 mLaunchingProviders.add(cpr);
7804 Binder.restoreCallingIdentity(origId);
7805 }
7806
7807 // Make sure the provider is published (the same provider class
7808 // may be published under multiple names).
7809 if (firstClass) {
7810 mProvidersByClass.put(cpi.name, cpr);
7811 }
7812 mProvidersByName.put(name, cpr);
7813
7814 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007815 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007816 "Adding provider requested by "
7817 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007818 + cpr.info.processName);
7819 Integer cnt = r.conProviders.get(cpr);
7820 if (cnt == null) {
7821 r.conProviders.put(cpr, new Integer(1));
7822 } else {
7823 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 cpr.clients.add(r);
7826 } else {
7827 cpr.externals++;
7828 }
7829 }
7830 }
7831
7832 // Wait for the provider to be published...
7833 synchronized (cpr) {
7834 while (cpr.provider == null) {
7835 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007836 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007837 + cpi.applicationInfo.packageName + "/"
7838 + cpi.applicationInfo.uid + " for provider "
7839 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007840 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 cpi.applicationInfo.packageName,
7842 cpi.applicationInfo.uid, name);
7843 return null;
7844 }
7845 try {
7846 cpr.wait();
7847 } catch (InterruptedException ex) {
7848 }
7849 }
7850 }
7851 return cpr;
7852 }
7853
7854 public final ContentProviderHolder getContentProvider(
7855 IApplicationThread caller, String name) {
7856 if (caller == null) {
7857 String msg = "null IApplicationThread when getting content provider "
7858 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007859 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007860 throw new SecurityException(msg);
7861 }
7862
7863 return getContentProviderImpl(caller, name);
7864 }
7865
7866 private ContentProviderHolder getContentProviderExternal(String name) {
7867 return getContentProviderImpl(null, name);
7868 }
7869
7870 /**
7871 * Drop a content provider from a ProcessRecord's bookkeeping
7872 * @param cpr
7873 */
7874 public void removeContentProvider(IApplicationThread caller, String name) {
7875 synchronized (this) {
7876 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7877 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007878 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007879 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007880 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 return;
7882 }
7883 final ProcessRecord r = getRecordForAppLocked(caller);
7884 if (r == null) {
7885 throw new SecurityException(
7886 "Unable to find app for caller " + caller +
7887 " when removing content provider " + name);
7888 }
7889 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007890 ContentProviderRecord localCpr = (ContentProviderRecord)
7891 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007892 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007893 + r.info.processName + " from process "
7894 + localCpr.appInfo.processName);
7895 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007896 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007897 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007898 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007899 return;
7900 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007901 Integer cnt = r.conProviders.get(localCpr);
7902 if (cnt == null || cnt.intValue() <= 1) {
7903 localCpr.clients.remove(r);
7904 r.conProviders.remove(localCpr);
7905 } else {
7906 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 }
7909 updateOomAdjLocked();
7910 }
7911 }
7912
7913 private void removeContentProviderExternal(String name) {
7914 synchronized (this) {
7915 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7916 if(cpr == null) {
7917 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007918 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007919 return;
7920 }
7921
7922 //update content provider record entry info
7923 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7924 localCpr.externals--;
7925 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007926 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927 }
7928 updateOomAdjLocked();
7929 }
7930 }
7931
7932 public final void publishContentProviders(IApplicationThread caller,
7933 List<ContentProviderHolder> providers) {
7934 if (providers == null) {
7935 return;
7936 }
7937
7938 synchronized(this) {
7939 final ProcessRecord r = getRecordForAppLocked(caller);
7940 if (r == null) {
7941 throw new SecurityException(
7942 "Unable to find app for caller " + caller
7943 + " (pid=" + Binder.getCallingPid()
7944 + ") when publishing content providers");
7945 }
7946
7947 final long origId = Binder.clearCallingIdentity();
7948
7949 final int N = providers.size();
7950 for (int i=0; i<N; i++) {
7951 ContentProviderHolder src = providers.get(i);
7952 if (src == null || src.info == null || src.provider == null) {
7953 continue;
7954 }
7955 ContentProviderRecord dst =
7956 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7957 if (dst != null) {
7958 mProvidersByClass.put(dst.info.name, dst);
7959 String names[] = dst.info.authority.split(";");
7960 for (int j = 0; j < names.length; j++) {
7961 mProvidersByName.put(names[j], dst);
7962 }
7963
7964 int NL = mLaunchingProviders.size();
7965 int j;
7966 for (j=0; j<NL; j++) {
7967 if (mLaunchingProviders.get(j) == dst) {
7968 mLaunchingProviders.remove(j);
7969 j--;
7970 NL--;
7971 }
7972 }
7973 synchronized (dst) {
7974 dst.provider = src.provider;
7975 dst.app = r;
7976 dst.notifyAll();
7977 }
7978 updateOomAdjLocked(r);
7979 }
7980 }
7981
7982 Binder.restoreCallingIdentity(origId);
7983 }
7984 }
7985
7986 public static final void installSystemProviders() {
7987 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7988 List providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007989 if (providers != null) {
7990 for (int i=providers.size()-1; i>=0; i--) {
7991 ProviderInfo pi = (ProviderInfo)providers.get(i);
7992 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007993 Slog.w(TAG, "Not installing system proc provider " + pi.name
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007994 + ": not system .apk");
7995 providers.remove(i);
7996 }
7997 }
7998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007999 mSystemThread.installSystemProviders(providers);
8000 }
8001
8002 // =========================================================
8003 // GLOBAL MANAGEMENT
8004 // =========================================================
8005
8006 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8007 ApplicationInfo info, String customProcess) {
8008 String proc = customProcess != null ? customProcess : info.processName;
8009 BatteryStatsImpl.Uid.Proc ps = null;
8010 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8011 synchronized (stats) {
8012 ps = stats.getProcessStatsLocked(info.uid, proc);
8013 }
8014 return new ProcessRecord(ps, thread, info, proc);
8015 }
8016
8017 final ProcessRecord addAppLocked(ApplicationInfo info) {
8018 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8019
8020 if (app == null) {
8021 app = newProcessRecordLocked(null, info, null);
8022 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008023 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 }
8025
8026 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8027 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8028 app.persistent = true;
8029 app.maxAdj = CORE_SERVER_ADJ;
8030 }
8031 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8032 mPersistentStartingProcesses.add(app);
8033 startProcessLocked(app, "added application", app.processName);
8034 }
8035
8036 return app;
8037 }
8038
8039 public void unhandledBack() {
8040 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8041 "unhandledBack()");
8042
8043 synchronized(this) {
8044 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008045 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008046 TAG, "Performing unhandledBack(): stack size = " + count);
8047 if (count > 1) {
8048 final long origId = Binder.clearCallingIdentity();
8049 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8050 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8051 Binder.restoreCallingIdentity(origId);
8052 }
8053 }
8054 }
8055
8056 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8057 String name = uri.getAuthority();
8058 ContentProviderHolder cph = getContentProviderExternal(name);
8059 ParcelFileDescriptor pfd = null;
8060 if (cph != null) {
8061 // We record the binder invoker's uid in thread-local storage before
8062 // going to the content provider to open the file. Later, in the code
8063 // that handles all permissions checks, we look for this uid and use
8064 // that rather than the Activity Manager's own uid. The effect is that
8065 // we do the check against the caller's permissions even though it looks
8066 // to the content provider like the Activity Manager itself is making
8067 // the request.
8068 sCallerIdentity.set(new Identity(
8069 Binder.getCallingPid(), Binder.getCallingUid()));
8070 try {
8071 pfd = cph.provider.openFile(uri, "r");
8072 } catch (FileNotFoundException e) {
8073 // do nothing; pfd will be returned null
8074 } finally {
8075 // Ensure that whatever happens, we clean up the identity state
8076 sCallerIdentity.remove();
8077 }
8078
8079 // We've got the fd now, so we're done with the provider.
8080 removeContentProviderExternal(name);
8081 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008082 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008083 }
8084 return pfd;
8085 }
8086
8087 public void goingToSleep() {
8088 synchronized(this) {
8089 mSleeping = true;
8090 mWindowManager.setEventDispatching(false);
8091
8092 if (mResumedActivity != null) {
8093 pauseIfSleepingLocked();
8094 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008095 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008096 }
8097 }
8098 }
8099
Dianne Hackborn55280a92009-05-07 15:53:46 -07008100 public boolean shutdown(int timeout) {
8101 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8102 != PackageManager.PERMISSION_GRANTED) {
8103 throw new SecurityException("Requires permission "
8104 + android.Manifest.permission.SHUTDOWN);
8105 }
8106
8107 boolean timedout = false;
8108
8109 synchronized(this) {
8110 mShuttingDown = true;
8111 mWindowManager.setEventDispatching(false);
8112
8113 if (mResumedActivity != null) {
8114 pauseIfSleepingLocked();
8115 final long endTime = System.currentTimeMillis() + timeout;
8116 while (mResumedActivity != null || mPausingActivity != null) {
8117 long delay = endTime - System.currentTimeMillis();
8118 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008119 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008120 timedout = true;
8121 break;
8122 }
8123 try {
8124 this.wait();
8125 } catch (InterruptedException e) {
8126 }
8127 }
8128 }
8129 }
8130
8131 mUsageStatsService.shutdown();
8132 mBatteryStatsService.shutdown();
8133
8134 return timedout;
8135 }
8136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008138 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 if (!mGoingToSleep.isHeld()) {
8140 mGoingToSleep.acquire();
8141 if (mLaunchingActivity.isHeld()) {
8142 mLaunchingActivity.release();
8143 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8144 }
8145 }
8146
8147 // If we are not currently pausing an activity, get the current
8148 // one to pause. If we are pausing one, we will just let that stuff
8149 // run and release the wake lock when all done.
8150 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008151 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8152 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008153 startPausingLocked(false, true);
8154 }
8155 }
8156 }
8157
8158 public void wakingUp() {
8159 synchronized(this) {
8160 if (mGoingToSleep.isHeld()) {
8161 mGoingToSleep.release();
8162 }
8163 mWindowManager.setEventDispatching(true);
8164 mSleeping = false;
8165 resumeTopActivityLocked(null);
8166 }
8167 }
8168
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008169 public void stopAppSwitches() {
8170 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8171 != PackageManager.PERMISSION_GRANTED) {
8172 throw new SecurityException("Requires permission "
8173 + android.Manifest.permission.STOP_APP_SWITCHES);
8174 }
8175
8176 synchronized(this) {
8177 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8178 + APP_SWITCH_DELAY_TIME;
8179 mDidAppSwitch = false;
8180 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8181 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8182 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8183 }
8184 }
8185
8186 public void resumeAppSwitches() {
8187 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8188 != PackageManager.PERMISSION_GRANTED) {
8189 throw new SecurityException("Requires permission "
8190 + android.Manifest.permission.STOP_APP_SWITCHES);
8191 }
8192
8193 synchronized(this) {
8194 // Note that we don't execute any pending app switches... we will
8195 // let those wait until either the timeout, or the next start
8196 // activity request.
8197 mAppSwitchesAllowedTime = 0;
8198 }
8199 }
8200
8201 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8202 String name) {
8203 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8204 return true;
8205 }
8206
8207 final int perm = checkComponentPermission(
8208 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8209 callingUid, -1);
8210 if (perm == PackageManager.PERMISSION_GRANTED) {
8211 return true;
8212 }
8213
Joe Onorato8a9b2202010-02-26 18:56:32 -08008214 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008215 return false;
8216 }
8217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008218 public void setDebugApp(String packageName, boolean waitForDebugger,
8219 boolean persistent) {
8220 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8221 "setDebugApp()");
8222
8223 // Note that this is not really thread safe if there are multiple
8224 // callers into it at the same time, but that's not a situation we
8225 // care about.
8226 if (persistent) {
8227 final ContentResolver resolver = mContext.getContentResolver();
8228 Settings.System.putString(
8229 resolver, Settings.System.DEBUG_APP,
8230 packageName);
8231 Settings.System.putInt(
8232 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8233 waitForDebugger ? 1 : 0);
8234 }
8235
8236 synchronized (this) {
8237 if (!persistent) {
8238 mOrigDebugApp = mDebugApp;
8239 mOrigWaitForDebugger = mWaitForDebugger;
8240 }
8241 mDebugApp = packageName;
8242 mWaitForDebugger = waitForDebugger;
8243 mDebugTransient = !persistent;
8244 if (packageName != null) {
8245 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008246 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 Binder.restoreCallingIdentity(origId);
8248 }
8249 }
8250 }
8251
8252 public void setAlwaysFinish(boolean enabled) {
8253 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8254 "setAlwaysFinish()");
8255
8256 Settings.System.putInt(
8257 mContext.getContentResolver(),
8258 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8259
8260 synchronized (this) {
8261 mAlwaysFinishActivities = enabled;
8262 }
8263 }
8264
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008265 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008267 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008269 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270 }
8271 }
8272
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008273 public boolean isUserAMonkey() {
8274 // For now the fact that there is a controller implies
8275 // we have a monkey.
8276 synchronized (this) {
8277 return mController != null;
8278 }
8279 }
8280
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008281 public void registerActivityWatcher(IActivityWatcher watcher) {
8282 mWatchers.register(watcher);
8283 }
8284
8285 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8286 mWatchers.unregister(watcher);
8287 }
8288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008289 public final void enterSafeMode() {
8290 synchronized(this) {
8291 // It only makes sense to do this before the system is ready
8292 // and started launching other packages.
8293 if (!mSystemReady) {
8294 try {
8295 ActivityThread.getPackageManager().enterSafeMode();
8296 } catch (RemoteException e) {
8297 }
8298
8299 View v = LayoutInflater.from(mContext).inflate(
8300 com.android.internal.R.layout.safe_mode, null);
8301 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8302 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8303 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8304 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8305 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8306 lp.format = v.getBackground().getOpacity();
8307 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8308 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8309 ((WindowManager)mContext.getSystemService(
8310 Context.WINDOW_SERVICE)).addView(v, lp);
8311 }
8312 }
8313 }
8314
8315 public void noteWakeupAlarm(IIntentSender sender) {
8316 if (!(sender instanceof PendingIntentRecord)) {
8317 return;
8318 }
8319 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8320 synchronized (stats) {
8321 if (mBatteryStatsService.isOnBattery()) {
8322 mBatteryStatsService.enforceCallingPermission();
8323 PendingIntentRecord rec = (PendingIntentRecord)sender;
8324 int MY_UID = Binder.getCallingUid();
8325 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8326 BatteryStatsImpl.Uid.Pkg pkg =
8327 stats.getPackageStatsLocked(uid, rec.key.packageName);
8328 pkg.incWakeupsLocked();
8329 }
8330 }
8331 }
8332
8333 public boolean killPidsForMemory(int[] pids) {
8334 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8335 throw new SecurityException("killPidsForMemory only available to the system");
8336 }
8337
8338 // XXX Note: don't acquire main activity lock here, because the window
8339 // manager calls in with its locks held.
8340
8341 boolean killed = false;
8342 synchronized (mPidsSelfLocked) {
8343 int[] types = new int[pids.length];
8344 int worstType = 0;
8345 for (int i=0; i<pids.length; i++) {
8346 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8347 if (proc != null) {
8348 int type = proc.setAdj;
8349 types[i] = type;
8350 if (type > worstType) {
8351 worstType = type;
8352 }
8353 }
8354 }
8355
8356 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8357 // then constrain it so we will kill all hidden procs.
8358 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8359 worstType = HIDDEN_APP_MIN_ADJ;
8360 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008361 Slog.w(TAG, "Killing processes for memory at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008362 for (int i=0; i<pids.length; i++) {
8363 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8364 if (proc == null) {
8365 continue;
8366 }
8367 int adj = proc.setAdj;
8368 if (adj >= worstType) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008369 Slog.w(TAG, "Killing for memory: " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008370 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008371 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008372 proc.processName, adj);
8373 killed = true;
8374 Process.killProcess(pids[i]);
8375 }
8376 }
8377 }
8378 return killed;
8379 }
8380
8381 public void reportPss(IApplicationThread caller, int pss) {
8382 Watchdog.PssRequestor req;
8383 String name;
8384 ProcessRecord callerApp;
8385 synchronized (this) {
8386 if (caller == null) {
8387 return;
8388 }
8389 callerApp = getRecordForAppLocked(caller);
8390 if (callerApp == null) {
8391 return;
8392 }
8393 callerApp.lastPss = pss;
8394 req = callerApp;
8395 name = callerApp.processName;
8396 }
8397 Watchdog.getInstance().reportPss(req, name, pss);
8398 if (!callerApp.persistent) {
8399 removeRequestedPss(callerApp);
8400 }
8401 }
8402
8403 public void requestPss(Runnable completeCallback) {
8404 ArrayList<ProcessRecord> procs;
8405 synchronized (this) {
8406 mRequestPssCallback = completeCallback;
8407 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008408 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8409 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008410 if (!proc.persistent) {
8411 mRequestPssList.add(proc);
8412 }
8413 }
8414 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8415 }
8416
8417 int oldPri = Process.getThreadPriority(Process.myTid());
8418 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8419 for (int i=procs.size()-1; i>=0; i--) {
8420 ProcessRecord proc = procs.get(i);
8421 proc.lastPss = 0;
8422 proc.requestPss();
8423 }
8424 Process.setThreadPriority(oldPri);
8425 }
8426
8427 void removeRequestedPss(ProcessRecord proc) {
8428 Runnable callback = null;
8429 synchronized (this) {
8430 if (mRequestPssList.remove(proc)) {
8431 if (mRequestPssList.size() == 0) {
8432 callback = mRequestPssCallback;
8433 mRequestPssCallback = null;
8434 }
8435 }
8436 }
8437
8438 if (callback != null) {
8439 callback.run();
8440 }
8441 }
8442
8443 public void collectPss(Watchdog.PssStats stats) {
8444 stats.mEmptyPss = 0;
8445 stats.mEmptyCount = 0;
8446 stats.mBackgroundPss = 0;
8447 stats.mBackgroundCount = 0;
8448 stats.mServicePss = 0;
8449 stats.mServiceCount = 0;
8450 stats.mVisiblePss = 0;
8451 stats.mVisibleCount = 0;
8452 stats.mForegroundPss = 0;
8453 stats.mForegroundCount = 0;
8454 stats.mNoPssCount = 0;
8455 synchronized (this) {
8456 int i;
8457 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8458 ? mProcDeaths.length : stats.mProcDeaths.length;
8459 int aggr = 0;
8460 for (i=0; i<NPD; i++) {
8461 aggr += mProcDeaths[i];
8462 stats.mProcDeaths[i] = aggr;
8463 }
8464 while (i<stats.mProcDeaths.length) {
8465 stats.mProcDeaths[i] = 0;
8466 i++;
8467 }
8468
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008469 for (i=mLruProcesses.size()-1; i>=0; i--) {
8470 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 if (proc.persistent) {
8472 continue;
8473 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008474 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475 if (proc.lastPss == 0) {
8476 stats.mNoPssCount++;
8477 continue;
8478 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008479 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8480 if (proc.empty) {
8481 stats.mEmptyPss += proc.lastPss;
8482 stats.mEmptyCount++;
8483 } else {
8484 stats.mBackgroundPss += proc.lastPss;
8485 stats.mBackgroundCount++;
8486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008487 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8488 stats.mVisiblePss += proc.lastPss;
8489 stats.mVisibleCount++;
8490 } else {
8491 stats.mForegroundPss += proc.lastPss;
8492 stats.mForegroundCount++;
8493 }
8494 }
8495 }
8496 }
8497
8498 public final void startRunning(String pkg, String cls, String action,
8499 String data) {
8500 synchronized(this) {
8501 if (mStartRunning) {
8502 return;
8503 }
8504 mStartRunning = true;
8505 mTopComponent = pkg != null && cls != null
8506 ? new ComponentName(pkg, cls) : null;
8507 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8508 mTopData = data;
8509 if (!mSystemReady) {
8510 return;
8511 }
8512 }
8513
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008514 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 }
8516
8517 private void retrieveSettings() {
8518 final ContentResolver resolver = mContext.getContentResolver();
8519 String debugApp = Settings.System.getString(
8520 resolver, Settings.System.DEBUG_APP);
8521 boolean waitForDebugger = Settings.System.getInt(
8522 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8523 boolean alwaysFinishActivities = Settings.System.getInt(
8524 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8525
8526 Configuration configuration = new Configuration();
8527 Settings.System.getConfiguration(resolver, configuration);
8528
8529 synchronized (this) {
8530 mDebugApp = mOrigDebugApp = debugApp;
8531 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8532 mAlwaysFinishActivities = alwaysFinishActivities;
8533 // This happens before any activities are started, so we can
8534 // change mConfiguration in-place.
8535 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008536 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008537 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008538 }
8539 }
8540
8541 public boolean testIsSystemReady() {
8542 // no need to synchronize(this) just to read & return the value
8543 return mSystemReady;
8544 }
8545
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008546 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008547 // In the simulator, startRunning will never have been called, which
8548 // normally sets a few crucial variables. Do it here instead.
8549 if (!Process.supportsProcesses()) {
8550 mStartRunning = true;
8551 mTopAction = Intent.ACTION_MAIN;
8552 }
8553
8554 synchronized(this) {
8555 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008556 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008557 return;
8558 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008559
8560 // Check to see if there are any update receivers to run.
8561 if (!mDidUpdate) {
8562 if (mWaitingUpdate) {
8563 return;
8564 }
8565 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8566 List<ResolveInfo> ris = null;
8567 try {
8568 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8569 intent, null, 0);
8570 } catch (RemoteException e) {
8571 }
8572 if (ris != null) {
8573 for (int i=ris.size()-1; i>=0; i--) {
8574 if ((ris.get(i).activityInfo.applicationInfo.flags
8575 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8576 ris.remove(i);
8577 }
8578 }
8579 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8580 for (int i=0; i<ris.size(); i++) {
8581 ActivityInfo ai = ris.get(i).activityInfo;
8582 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8583 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008584 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008585 finisher = new IIntentReceiver.Stub() {
8586 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008587 String data, Bundle extras, boolean ordered,
8588 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008589 throws RemoteException {
8590 synchronized (ActivityManagerService.this) {
8591 mDidUpdate = true;
8592 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008593 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008594 }
8595 };
8596 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008597 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008598 broadcastIntentLocked(null, null, intent, null, finisher,
8599 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008600 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008601 mWaitingUpdate = true;
8602 }
8603 }
8604 }
8605 if (mWaitingUpdate) {
8606 return;
8607 }
8608 mDidUpdate = true;
8609 }
8610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008611 mSystemReady = true;
8612 if (!mStartRunning) {
8613 return;
8614 }
8615 }
8616
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008617 ArrayList<ProcessRecord> procsToKill = null;
8618 synchronized(mPidsSelfLocked) {
8619 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8620 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8621 if (!isAllowedWhileBooting(proc.info)){
8622 if (procsToKill == null) {
8623 procsToKill = new ArrayList<ProcessRecord>();
8624 }
8625 procsToKill.add(proc);
8626 }
8627 }
8628 }
8629
8630 if (procsToKill != null) {
8631 synchronized(this) {
8632 for (int i=procsToKill.size()-1; i>=0; i--) {
8633 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008634 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008635 removeProcessLocked(proc, true);
8636 }
8637 }
8638 }
8639
Joe Onorato8a9b2202010-02-26 18:56:32 -08008640 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008641 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642 SystemClock.uptimeMillis());
8643
8644 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008645 // Make sure we have no pre-ready processes sitting around.
8646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008647 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8648 ResolveInfo ri = mContext.getPackageManager()
8649 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008650 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008651 CharSequence errorMsg = null;
8652 if (ri != null) {
8653 ActivityInfo ai = ri.activityInfo;
8654 ApplicationInfo app = ai.applicationInfo;
8655 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8656 mTopAction = Intent.ACTION_FACTORY_TEST;
8657 mTopData = null;
8658 mTopComponent = new ComponentName(app.packageName,
8659 ai.name);
8660 } else {
8661 errorMsg = mContext.getResources().getText(
8662 com.android.internal.R.string.factorytest_not_system);
8663 }
8664 } else {
8665 errorMsg = mContext.getResources().getText(
8666 com.android.internal.R.string.factorytest_no_action);
8667 }
8668 if (errorMsg != null) {
8669 mTopAction = null;
8670 mTopData = null;
8671 mTopComponent = null;
8672 Message msg = Message.obtain();
8673 msg.what = SHOW_FACTORY_ERROR_MSG;
8674 msg.getData().putCharSequence("msg", errorMsg);
8675 mHandler.sendMessage(msg);
8676 }
8677 }
8678 }
8679
8680 retrieveSettings();
8681
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008682 if (goingCallback != null) goingCallback.run();
8683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008684 synchronized (this) {
8685 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8686 try {
8687 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008688 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 if (apps != null) {
8690 int N = apps.size();
8691 int i;
8692 for (i=0; i<N; i++) {
8693 ApplicationInfo info
8694 = (ApplicationInfo)apps.get(i);
8695 if (info != null &&
8696 !info.packageName.equals("android")) {
8697 addAppLocked(info);
8698 }
8699 }
8700 }
8701 } catch (RemoteException ex) {
8702 // pm is in same process, this will never happen.
8703 }
8704 }
8705
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008706 // Start up initial activity.
8707 mBooting = true;
8708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008709 try {
8710 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8711 Message msg = Message.obtain();
8712 msg.what = SHOW_UID_ERROR_MSG;
8713 mHandler.sendMessage(msg);
8714 }
8715 } catch (RemoteException e) {
8716 }
8717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 resumeTopActivityLocked(null);
8719 }
8720 }
8721
Dan Egnorb7f03672009-12-09 16:22:32 -08008722 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008723 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008724 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008725 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008726 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008727 startAppProblemLocked(app);
8728 app.stopFreezingAllLocked();
8729 return handleAppCrashLocked(app);
8730 }
8731
Dan Egnorb7f03672009-12-09 16:22:32 -08008732 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008733 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008734 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008735 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008736 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8737 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 startAppProblemLocked(app);
8739 app.stopFreezingAllLocked();
8740 }
8741
8742 /**
8743 * Generate a process error record, suitable for attachment to a ProcessRecord.
8744 *
8745 * @param app The ProcessRecord in which the error occurred.
8746 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8747 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008748 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749 * @param shortMsg Short message describing the crash.
8750 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008751 * @param stackTrace Full crash stack trace, may be null.
8752 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008753 * @return Returns a fully-formed AppErrorStateInfo record.
8754 */
8755 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008756 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 report.condition = condition;
8760 report.processName = app.processName;
8761 report.pid = app.pid;
8762 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008763 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008764 report.shortMsg = shortMsg;
8765 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008766 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008767
8768 return report;
8769 }
8770
Dan Egnor42471dd2010-01-07 17:25:22 -08008771 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008772 synchronized (this) {
8773 app.crashing = false;
8774 app.crashingReport = null;
8775 app.notResponding = false;
8776 app.notRespondingReport = null;
8777 if (app.anrDialog == fromDialog) {
8778 app.anrDialog = null;
8779 }
8780 if (app.waitDialog == fromDialog) {
8781 app.waitDialog = null;
8782 }
8783 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008784 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008785 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008786 + app.processName
8787 + " (pid=" + app.pid + ") at user's request");
8788 Process.killProcess(app.pid);
8789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008790 }
8791 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008792
Dan Egnorb7f03672009-12-09 16:22:32 -08008793 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 long now = SystemClock.uptimeMillis();
8795
8796 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8797 app.info.uid);
8798 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8799 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008800 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008802 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008803 app.info.processName, app.info.uid);
8804 killServicesLocked(app, false);
8805 for (int i=mHistory.size()-1; i>=0; i--) {
8806 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8807 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008808 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008809 + r.intent.getComponent().flattenToShortString());
8810 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8811 }
8812 }
8813 if (!app.persistent) {
8814 // We don't want to start this process again until the user
8815 // explicitly does so... but for persistent process, we really
8816 // need to keep it running. If a persistent process is actually
8817 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008818 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 app.info.processName);
8820 mBadProcesses.put(app.info.processName, app.info.uid, now);
8821 app.bad = true;
8822 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8823 app.removed = true;
8824 removeProcessLocked(app, false);
8825 return false;
8826 }
8827 }
8828
8829 // Bump up the crash count of any services currently running in the proc.
8830 if (app.services.size() != 0) {
8831 // Any services running in the application need to be placed
8832 // back in the pending list.
8833 Iterator it = app.services.iterator();
8834 while (it.hasNext()) {
8835 ServiceRecord sr = (ServiceRecord)it.next();
8836 sr.crashCount++;
8837 }
8838 }
8839
8840 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8841 return true;
8842 }
8843
8844 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008845 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8846 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008847 skipCurrentReceiverLocked(app);
8848 }
8849
8850 void skipCurrentReceiverLocked(ProcessRecord app) {
8851 boolean reschedule = false;
8852 BroadcastRecord r = app.curReceiver;
8853 if (r != null) {
8854 // The current broadcast is waiting for this app's receiver
8855 // to be finished. Looks like that's not going to happen, so
8856 // let the broadcast continue.
8857 logBroadcastReceiverDiscard(r);
8858 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8859 r.resultExtras, r.resultAbort, true);
8860 reschedule = true;
8861 }
8862 r = mPendingBroadcast;
8863 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008864 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008865 "skip & discard pending app " + r);
8866 logBroadcastReceiverDiscard(r);
8867 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8868 r.resultExtras, r.resultAbort, true);
8869 reschedule = true;
8870 }
8871 if (reschedule) {
8872 scheduleBroadcastsLocked();
8873 }
8874 }
8875
Dan Egnor60d87622009-12-16 16:32:58 -08008876 /**
8877 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8878 * The application process will exit immediately after this call returns.
8879 * @param app object of the crashing app, null for the system server
8880 * @param crashInfo describing the exception
8881 */
8882 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8883 ProcessRecord r = findAppProcess(app);
8884
8885 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8886 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008887 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008888 crashInfo.exceptionClassName,
8889 crashInfo.exceptionMessage,
8890 crashInfo.throwFileName,
8891 crashInfo.throwLineNumber);
8892
Dan Egnor42471dd2010-01-07 17:25:22 -08008893 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008894
8895 crashApplication(r, crashInfo);
8896 }
8897
8898 /**
8899 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8900 * @param app object of the crashing app, null for the system server
8901 * @param tag reported by the caller
8902 * @param crashInfo describing the context of the error
8903 * @return true if the process should exit immediately (WTF is fatal)
8904 */
8905 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008906 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008907 ProcessRecord r = findAppProcess(app);
8908
8909 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8910 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008911 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008912 tag, crashInfo.exceptionMessage);
8913
Dan Egnor42471dd2010-01-07 17:25:22 -08008914 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008915
Doug Zongker43866e02010-01-07 12:09:54 -08008916 if (Settings.Secure.getInt(mContext.getContentResolver(),
8917 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008918 crashApplication(r, crashInfo);
8919 return true;
8920 } else {
8921 return false;
8922 }
8923 }
8924
8925 /**
8926 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8927 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8928 */
8929 private ProcessRecord findAppProcess(IBinder app) {
8930 if (app == null) {
8931 return null;
8932 }
8933
8934 synchronized (this) {
8935 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8936 final int NA = apps.size();
8937 for (int ia=0; ia<NA; ia++) {
8938 ProcessRecord p = apps.valueAt(ia);
8939 if (p.thread != null && p.thread.asBinder() == app) {
8940 return p;
8941 }
8942 }
8943 }
8944
Joe Onorato8a9b2202010-02-26 18:56:32 -08008945 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008946 return null;
8947 }
8948 }
8949
8950 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008951 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008952 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008953 * @param process which caused the error, null means the system server
8954 * @param activity which triggered the error, null if unknown
8955 * @param parent activity related to the error, null if unknown
8956 * @param subject line related to the error, null if absent
8957 * @param report in long form describing the error, null if absent
8958 * @param logFile to include in the report, null if none
8959 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008960 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08008961 public void addErrorToDropBox(String eventType,
Dan Egnor42471dd2010-01-07 17:25:22 -08008962 ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
8963 String subject, String report, File logFile,
Dan Egnor60d87622009-12-16 16:32:58 -08008964 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08008965 // NOTE -- this must never acquire the ActivityManagerService lock,
8966 // otherwise the watchdog may be prevented from resetting the system.
8967
Dan Egnor42471dd2010-01-07 17:25:22 -08008968 String dropboxTag;
8969 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008970 dropboxTag = "system_server_" + eventType;
Dan Egnor42471dd2010-01-07 17:25:22 -08008971 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008972 dropboxTag = "system_app_" + eventType;
8973 } else {
8974 dropboxTag = "data_app_" + eventType;
8975 }
8976
8977 DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
8978 if (dbox != null && dbox.isTagEnabled(dropboxTag)) {
8979 StringBuilder sb = new StringBuilder(1024);
Dan Egnor42471dd2010-01-07 17:25:22 -08008980 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008981 sb.append("Process: system_server\n");
8982 } else {
Dan Egnor42471dd2010-01-07 17:25:22 -08008983 sb.append("Process: ").append(process.processName).append("\n");
Dan Egnor66c40e72010-01-26 16:23:11 -08008984 }
8985 if (process != null) {
8986 int flags = process.info.flags;
8987 IPackageManager pm = ActivityThread.getPackageManager();
8988 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8989 for (String pkg : process.pkgList) {
8990 sb.append("Package: ").append(pkg);
8991 try {
8992 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8993 if (pi != null) {
8994 sb.append(" v").append(pi.versionCode);
8995 if (pi.versionName != null) {
8996 sb.append(" (").append(pi.versionName).append(")");
8997 }
8998 }
8999 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009000 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor66c40e72010-01-26 16:23:11 -08009001 }
9002 sb.append("\n");
9003 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009004 }
9005 if (activity != null) {
9006 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9007 }
9008 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9009 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9010 }
9011 if (parent != null && parent != activity) {
9012 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9013 }
9014 if (subject != null) {
9015 sb.append("Subject: ").append(subject).append("\n");
9016 }
9017 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9018 sb.append("\n");
9019 if (report != null) {
9020 sb.append(report);
9021 }
9022 if (logFile != null) {
9023 try {
9024 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9025 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009026 Slog.e(TAG, "Error reading " + logFile, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009027 }
9028 }
Dan Egnor60d87622009-12-16 16:32:58 -08009029 if (crashInfo != null && crashInfo.stackTrace != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009030 sb.append(crashInfo.stackTrace);
Dan Egnor60d87622009-12-16 16:32:58 -08009031 }
9032 dbox.addText(dropboxTag, sb.toString());
9033 }
9034 }
9035
9036 /**
9037 * Bring up the "unexpected error" dialog box for a crashing app.
9038 * Deal with edge cases (intercepts from instrumented applications,
9039 * ActivityController, error intent receivers, that sort of thing).
9040 * @param r the application crashing
9041 * @param crashInfo describing the failure
9042 */
9043 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009044 long timeMillis = System.currentTimeMillis();
9045 String shortMsg = crashInfo.exceptionClassName;
9046 String longMsg = crashInfo.exceptionMessage;
9047 String stackTrace = crashInfo.stackTrace;
9048 if (shortMsg != null && longMsg != null) {
9049 longMsg = shortMsg + ": " + longMsg;
9050 } else if (shortMsg != null) {
9051 longMsg = shortMsg;
9052 }
9053
Dan Egnor60d87622009-12-16 16:32:58 -08009054 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009056 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009057 try {
9058 String name = r != null ? r.processName : null;
9059 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009060 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009061 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009062 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009063 + " at watcher's request");
9064 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009065 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009066 }
9067 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009068 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009069 }
9070 }
9071
9072 final long origId = Binder.clearCallingIdentity();
9073
9074 // If this process is running instrumentation, finish it.
9075 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009076 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009078 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9079 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009080 Bundle info = new Bundle();
9081 info.putString("shortMsg", shortMsg);
9082 info.putString("longMsg", longMsg);
9083 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9084 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009085 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 }
9087
Dan Egnor60d87622009-12-16 16:32:58 -08009088 // If we can't identify the process or it's already exceeded its crash quota,
9089 // quit right away without showing a crash dialog.
9090 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009091 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009092 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009093 }
9094
9095 Message msg = Message.obtain();
9096 msg.what = SHOW_ERROR_MSG;
9097 HashMap data = new HashMap();
9098 data.put("result", result);
9099 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009100 msg.obj = data;
9101 mHandler.sendMessage(msg);
9102
9103 Binder.restoreCallingIdentity(origId);
9104 }
9105
9106 int res = result.get();
9107
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009108 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009109 synchronized (this) {
9110 if (r != null) {
9111 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9112 SystemClock.uptimeMillis());
9113 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009114 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009115 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009116 }
9117 }
9118
9119 if (appErrorIntent != null) {
9120 try {
9121 mContext.startActivity(appErrorIntent);
9122 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009123 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009126 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009127
9128 Intent createAppErrorIntentLocked(ProcessRecord r,
9129 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9130 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009131 if (report == null) {
9132 return null;
9133 }
9134 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9135 result.setComponent(r.errorReportReceiver);
9136 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9137 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9138 return result;
9139 }
9140
Dan Egnorb7f03672009-12-09 16:22:32 -08009141 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9142 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009143 if (r.errorReportReceiver == null) {
9144 return null;
9145 }
9146
9147 if (!r.crashing && !r.notResponding) {
9148 return null;
9149 }
9150
Dan Egnorb7f03672009-12-09 16:22:32 -08009151 ApplicationErrorReport report = new ApplicationErrorReport();
9152 report.packageName = r.info.packageName;
9153 report.installerPackageName = r.errorReportReceiver.getPackageName();
9154 report.processName = r.processName;
9155 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009156 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009157
Dan Egnorb7f03672009-12-09 16:22:32 -08009158 if (r.crashing) {
9159 report.type = ApplicationErrorReport.TYPE_CRASH;
9160 report.crashInfo = crashInfo;
9161 } else if (r.notResponding) {
9162 report.type = ApplicationErrorReport.TYPE_ANR;
9163 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009164
Dan Egnorb7f03672009-12-09 16:22:32 -08009165 report.anrInfo.activity = r.notRespondingReport.tag;
9166 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9167 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009168 }
9169
Dan Egnorb7f03672009-12-09 16:22:32 -08009170 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009171 }
9172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9174 // assume our apps are happy - lazy create the list
9175 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9176
9177 synchronized (this) {
9178
9179 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009180 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9181 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9183 // This one's in trouble, so we'll generate a report for it
9184 // crashes are higher priority (in case there's a crash *and* an anr)
9185 ActivityManager.ProcessErrorStateInfo report = null;
9186 if (app.crashing) {
9187 report = app.crashingReport;
9188 } else if (app.notResponding) {
9189 report = app.notRespondingReport;
9190 }
9191
9192 if (report != null) {
9193 if (errList == null) {
9194 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9195 }
9196 errList.add(report);
9197 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009198 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009199 " crashing = " + app.crashing +
9200 " notResponding = " + app.notResponding);
9201 }
9202 }
9203 }
9204 }
9205
9206 return errList;
9207 }
9208
9209 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9210 // Lazy instantiation of list
9211 List<ActivityManager.RunningAppProcessInfo> runList = null;
9212 synchronized (this) {
9213 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009214 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9215 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009216 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9217 // Generate process state info for running application
9218 ActivityManager.RunningAppProcessInfo currApp =
9219 new ActivityManager.RunningAppProcessInfo(app.processName,
9220 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009221 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009223 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009224 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9225 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9226 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009227 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9228 } else if (adj >= HOME_APP_ADJ) {
9229 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9230 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 } else if (adj >= SECONDARY_SERVER_ADJ) {
9232 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9233 } else if (adj >= VISIBLE_APP_ADJ) {
9234 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9235 } else {
9236 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9237 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009238 currApp.importanceReasonCode = app.adjTypeCode;
9239 if (app.adjSource instanceof ProcessRecord) {
9240 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9241 } else if (app.adjSource instanceof HistoryRecord) {
9242 HistoryRecord r = (HistoryRecord)app.adjSource;
9243 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9244 }
9245 if (app.adjTarget instanceof ComponentName) {
9246 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9247 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009248 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009249 // + " lru=" + currApp.lru);
9250 if (runList == null) {
9251 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9252 }
9253 runList.add(currApp);
9254 }
9255 }
9256 }
9257 return runList;
9258 }
9259
9260 @Override
9261 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009262 if (checkCallingPermission(android.Manifest.permission.DUMP)
9263 != PackageManager.PERMISSION_GRANTED) {
9264 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9265 + Binder.getCallingPid()
9266 + ", uid=" + Binder.getCallingUid()
9267 + " without permission "
9268 + android.Manifest.permission.DUMP);
9269 return;
9270 }
9271
9272 boolean dumpAll = false;
9273
9274 int opti = 0;
9275 while (opti < args.length) {
9276 String opt = args[opti];
9277 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9278 break;
9279 }
9280 opti++;
9281 if ("-a".equals(opt)) {
9282 dumpAll = true;
9283 } else if ("-h".equals(opt)) {
9284 pw.println("Activity manager dump options:");
9285 pw.println(" [-a] [h- [cmd] ...");
9286 pw.println(" cmd may be one of:");
9287 pw.println(" activities: activity stack state");
9288 pw.println(" broadcasts: broadcast state");
9289 pw.println(" intents: pending intent state");
9290 pw.println(" processes: process state");
9291 pw.println(" providers: content provider state");
9292 pw.println(" services: service state");
9293 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009294 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009295 } else {
9296 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009297 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009298 }
9299
9300 // Is the caller requesting to dump a particular piece of data?
9301 if (opti < args.length) {
9302 String cmd = args[opti];
9303 opti++;
9304 if ("activities".equals(cmd) || "a".equals(cmd)) {
9305 synchronized (this) {
9306 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009307 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009308 return;
9309 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9310 synchronized (this) {
9311 dumpBroadcastsLocked(fd, pw, args, opti, true);
9312 }
9313 return;
9314 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9315 synchronized (this) {
9316 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9317 }
9318 return;
9319 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9320 synchronized (this) {
9321 dumpProcessesLocked(fd, pw, args, opti, true);
9322 }
9323 return;
9324 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9325 synchronized (this) {
9326 dumpProvidersLocked(fd, pw, args, opti, true);
9327 }
9328 return;
9329 } else if ("service".equals(cmd)) {
9330 dumpService(fd, pw, args, opti, true);
9331 return;
9332 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9333 synchronized (this) {
9334 dumpServicesLocked(fd, pw, args, opti, true);
9335 }
9336 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009337 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009338 }
9339
9340 // No piece of data specified, dump everything.
9341 synchronized (this) {
9342 boolean needSep;
9343 if (dumpAll) {
9344 pw.println("Providers in Current Activity Manager State:");
9345 }
9346 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9347 if (needSep) {
9348 pw.println(" ");
9349 }
9350 if (dumpAll) {
9351 pw.println("-------------------------------------------------------------------------------");
9352 pw.println("Broadcasts in Current Activity Manager State:");
9353 }
9354 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9355 if (needSep) {
9356 pw.println(" ");
9357 }
9358 if (dumpAll) {
9359 pw.println("-------------------------------------------------------------------------------");
9360 pw.println("Services in Current Activity Manager State:");
9361 }
9362 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9363 if (needSep) {
9364 pw.println(" ");
9365 }
9366 if (dumpAll) {
9367 pw.println("-------------------------------------------------------------------------------");
9368 pw.println("PendingIntents in Current Activity Manager State:");
9369 }
9370 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9371 if (needSep) {
9372 pw.println(" ");
9373 }
9374 if (dumpAll) {
9375 pw.println("-------------------------------------------------------------------------------");
9376 pw.println("Activities in Current Activity Manager State:");
9377 }
9378 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9379 if (needSep) {
9380 pw.println(" ");
9381 }
9382 if (dumpAll) {
9383 pw.println("-------------------------------------------------------------------------------");
9384 pw.println("Processes in Current Activity Manager State:");
9385 }
9386 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9387 }
9388 }
9389
9390 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9391 int opti, boolean dumpAll, boolean needHeader) {
9392 if (needHeader) {
9393 pw.println(" Activity stack:");
9394 }
9395 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9396 pw.println(" ");
9397 pw.println(" Running activities (most recent first):");
9398 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9399 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009400 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009401 pw.println(" Activities waiting for another to become visible:");
9402 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9403 }
9404 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009405 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009406 pw.println(" Activities waiting to stop:");
9407 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9408 }
9409 if (mFinishingActivities.size() > 0) {
9410 pw.println(" ");
9411 pw.println(" Activities waiting to finish:");
9412 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009414
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009415 pw.println(" ");
9416 pw.println(" mPausingActivity: " + mPausingActivity);
9417 pw.println(" mResumedActivity: " + mResumedActivity);
9418 pw.println(" mFocusedActivity: " + mFocusedActivity);
9419 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009421 if (dumpAll && mRecentTasks.size() > 0) {
9422 pw.println(" ");
9423 pw.println("Recent tasks in Current Activity Manager State:");
9424
9425 final int N = mRecentTasks.size();
9426 for (int i=0; i<N; i++) {
9427 TaskRecord tr = mRecentTasks.get(i);
9428 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9429 pw.println(tr);
9430 mRecentTasks.get(i).dump(pw, " ");
9431 }
9432 }
9433
9434 pw.println(" ");
9435 pw.println(" mCurTask: " + mCurTask);
9436
9437 return true;
9438 }
9439
9440 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9441 int opti, boolean dumpAll) {
9442 boolean needSep = false;
9443 int numPers = 0;
9444
9445 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9447 final int NA = procs.size();
9448 for (int ia=0; ia<NA; ia++) {
9449 if (!needSep) {
9450 pw.println(" All known processes:");
9451 needSep = true;
9452 }
9453 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009454 pw.print(r.persistent ? " *PERS*" : " *APP*");
9455 pw.print(" UID "); pw.print(procs.keyAt(ia));
9456 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009457 r.dump(pw, " ");
9458 if (r.persistent) {
9459 numPers++;
9460 }
9461 }
9462 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009463 }
9464
9465 if (mLruProcesses.size() > 0) {
9466 if (needSep) pw.println(" ");
9467 needSep = true;
9468 pw.println(" Running processes (most recent first):");
9469 dumpProcessList(pw, this, mLruProcesses, " ",
9470 "App ", "PERS", true);
9471 needSep = true;
9472 }
9473
9474 synchronized (mPidsSelfLocked) {
9475 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009476 if (needSep) pw.println(" ");
9477 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009478 pw.println(" PID mappings:");
9479 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9480 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9481 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009482 }
9483 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009484 }
9485
9486 if (mForegroundProcesses.size() > 0) {
9487 if (needSep) pw.println(" ");
9488 needSep = true;
9489 pw.println(" Foreground Processes:");
9490 for (int i=0; i<mForegroundProcesses.size(); i++) {
9491 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9492 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009493 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009494 }
9495
9496 if (mPersistentStartingProcesses.size() > 0) {
9497 if (needSep) pw.println(" ");
9498 needSep = true;
9499 pw.println(" Persisent processes that are starting:");
9500 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9501 "Starting Norm", "Restarting PERS", false);
9502 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009503
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009504 if (mStartingProcesses.size() > 0) {
9505 if (needSep) pw.println(" ");
9506 needSep = true;
9507 pw.println(" Processes that are starting:");
9508 dumpProcessList(pw, this, mStartingProcesses, " ",
9509 "Starting Norm", "Starting PERS", false);
9510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009511
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009512 if (mRemovedProcesses.size() > 0) {
9513 if (needSep) pw.println(" ");
9514 needSep = true;
9515 pw.println(" Processes that are being removed:");
9516 dumpProcessList(pw, this, mRemovedProcesses, " ",
9517 "Removed Norm", "Removed PERS", false);
9518 }
9519
9520 if (mProcessesOnHold.size() > 0) {
9521 if (needSep) pw.println(" ");
9522 needSep = true;
9523 pw.println(" Processes that are on old until the system is ready:");
9524 dumpProcessList(pw, this, mProcessesOnHold, " ",
9525 "OnHold Norm", "OnHold PERS", false);
9526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009527
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009528 if (mProcessesToGc.size() > 0) {
9529 if (needSep) pw.println(" ");
9530 needSep = true;
9531 pw.println(" Processes that are waiting to GC:");
9532 long now = SystemClock.uptimeMillis();
9533 for (int i=0; i<mProcessesToGc.size(); i++) {
9534 ProcessRecord proc = mProcessesToGc.get(i);
9535 pw.print(" Process "); pw.println(proc);
9536 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9537 pw.print(", last gced=");
9538 pw.print(now-proc.lastRequestedGc);
9539 pw.print(" ms ago, last lowMem=");
9540 pw.print(now-proc.lastLowMemory);
9541 pw.println(" ms ago");
9542
9543 }
9544 }
9545
9546 if (mProcessCrashTimes.getMap().size() > 0) {
9547 if (needSep) pw.println(" ");
9548 needSep = true;
9549 pw.println(" Time since processes crashed:");
9550 long now = SystemClock.uptimeMillis();
9551 for (Map.Entry<String, SparseArray<Long>> procs
9552 : mProcessCrashTimes.getMap().entrySet()) {
9553 SparseArray<Long> uids = procs.getValue();
9554 final int N = uids.size();
9555 for (int i=0; i<N; i++) {
9556 pw.print(" Process "); pw.print(procs.getKey());
9557 pw.print(" uid "); pw.print(uids.keyAt(i));
9558 pw.print(": last crashed ");
9559 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009560 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009561 }
9562 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009564
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009565 if (mBadProcesses.getMap().size() > 0) {
9566 if (needSep) pw.println(" ");
9567 needSep = true;
9568 pw.println(" Bad processes:");
9569 for (Map.Entry<String, SparseArray<Long>> procs
9570 : mBadProcesses.getMap().entrySet()) {
9571 SparseArray<Long> uids = procs.getValue();
9572 final int N = uids.size();
9573 for (int i=0; i<N; i++) {
9574 pw.print(" Bad process "); pw.print(procs.getKey());
9575 pw.print(" uid "); pw.print(uids.keyAt(i));
9576 pw.print(": crashed at time ");
9577 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578 }
9579 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009581
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009582 pw.println(" ");
9583 pw.println(" mHomeProcess: " + mHomeProcess);
9584 pw.println(" mConfiguration: " + mConfiguration);
9585 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9586 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9587 || mOrigWaitForDebugger) {
9588 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9589 + " mDebugTransient=" + mDebugTransient
9590 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9591 }
9592 if (mAlwaysFinishActivities || mController != null) {
9593 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9594 + " mController=" + mController);
9595 }
9596 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009597 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598 pw.println(" mStartRunning=" + mStartRunning
9599 + " mSystemReady=" + mSystemReady
9600 + " mBooting=" + mBooting
9601 + " mBooted=" + mBooted
9602 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009603 pw.println(" mGoingToSleep=" + mGoingToSleep);
9604 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009605 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009606
9607 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009608 }
9609
9610 /**
9611 * There are three ways to call this:
9612 * - no service specified: dump all the services
9613 * - a flattened component name that matched an existing service was specified as the
9614 * first arg: dump that one service
9615 * - the first arg isn't the flattened component name of an existing service:
9616 * dump all services whose component contains the first arg as a substring
9617 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009618 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9619 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009620 String[] newArgs;
9621 String componentNameString;
9622 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009623 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009624 componentNameString = null;
9625 newArgs = EMPTY_STRING_ARRAY;
9626 r = null;
9627 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009628 componentNameString = args[opti];
9629 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009630 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9631 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009632 newArgs = new String[args.length - opti];
9633 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009634 }
9635
9636 if (r != null) {
9637 dumpService(fd, pw, r, newArgs);
9638 } else {
9639 for (ServiceRecord r1 : mServices.values()) {
9640 if (componentNameString == null
9641 || r1.name.flattenToString().contains(componentNameString)) {
9642 dumpService(fd, pw, r1, newArgs);
9643 }
9644 }
9645 }
9646 }
9647
9648 /**
9649 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9650 * there is a thread associated with the service.
9651 */
9652 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9653 pw.println(" Service " + r.name.flattenToString());
9654 if (r.app != null && r.app.thread != null) {
9655 try {
9656 // flush anything that is already in the PrintWriter since the thread is going
9657 // to write to the file descriptor directly
9658 pw.flush();
9659 r.app.thread.dumpService(fd, r, args);
9660 pw.print("\n");
9661 } catch (RemoteException e) {
9662 pw.println("got a RemoteException while dumping the service");
9663 }
9664 }
9665 }
9666
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009667 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9668 int opti, boolean dumpAll) {
9669 boolean needSep = false;
9670
9671 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009672 if (mRegisteredReceivers.size() > 0) {
9673 pw.println(" ");
9674 pw.println(" Registered Receivers:");
9675 Iterator it = mRegisteredReceivers.values().iterator();
9676 while (it.hasNext()) {
9677 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009678 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009679 r.dump(pw, " ");
9680 }
9681 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 pw.println(" ");
9684 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009685 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009686 needSep = true;
9687 }
9688
9689 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9690 || mPendingBroadcast != null) {
9691 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009693 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009694 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009695 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9696 pw.println(" Broadcast #" + i + ":");
9697 mParallelBroadcasts.get(i).dump(pw, " ");
9698 }
9699 if (mOrderedBroadcasts.size() > 0) {
9700 pw.println(" ");
9701 pw.println(" Active serialized broadcasts:");
9702 }
9703 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9704 pw.println(" Serialized Broadcast #" + i + ":");
9705 mOrderedBroadcasts.get(i).dump(pw, " ");
9706 }
9707 pw.println(" ");
9708 pw.println(" Pending broadcast:");
9709 if (mPendingBroadcast != null) {
9710 mPendingBroadcast.dump(pw, " ");
9711 } else {
9712 pw.println(" (null)");
9713 }
9714 needSep = true;
9715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009716
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009717 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009718 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009719 pw.println(" Historical broadcasts:");
9720 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9721 BroadcastRecord r = mBroadcastHistory[i];
9722 if (r == null) {
9723 break;
9724 }
9725 pw.println(" Historical Broadcast #" + i + ":");
9726 r.dump(pw, " ");
9727 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009728 needSep = true;
9729 }
9730
9731 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009732 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009733 pw.println(" Sticky broadcasts:");
9734 StringBuilder sb = new StringBuilder(128);
9735 for (Map.Entry<String, ArrayList<Intent>> ent
9736 : mStickyBroadcasts.entrySet()) {
9737 pw.print(" * Sticky action "); pw.print(ent.getKey());
9738 pw.println(":");
9739 ArrayList<Intent> intents = ent.getValue();
9740 final int N = intents.size();
9741 for (int i=0; i<N; i++) {
9742 sb.setLength(0);
9743 sb.append(" Intent: ");
9744 intents.get(i).toShortString(sb, true, false);
9745 pw.println(sb.toString());
9746 Bundle bundle = intents.get(i).getExtras();
9747 if (bundle != null) {
9748 pw.print(" ");
9749 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009750 }
9751 }
9752 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009753 needSep = true;
9754 }
9755
9756 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009758 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759 pw.println(" mHandler:");
9760 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009761 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009763
9764 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765 }
9766
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009767 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9768 int opti, boolean dumpAll) {
9769 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009770
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009771 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009772 if (mServices.size() > 0) {
9773 pw.println(" Active services:");
9774 Iterator<ServiceRecord> it = mServices.values().iterator();
9775 while (it.hasNext()) {
9776 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009777 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009778 r.dump(pw, " ");
9779 }
9780 needSep = true;
9781 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009782 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009783
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009784 if (mPendingServices.size() > 0) {
9785 if (needSep) pw.println(" ");
9786 pw.println(" Pending services:");
9787 for (int i=0; i<mPendingServices.size(); i++) {
9788 ServiceRecord r = mPendingServices.get(i);
9789 pw.print(" * Pending "); pw.println(r);
9790 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009792 needSep = true;
9793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009795 if (mRestartingServices.size() > 0) {
9796 if (needSep) pw.println(" ");
9797 pw.println(" Restarting services:");
9798 for (int i=0; i<mRestartingServices.size(); i++) {
9799 ServiceRecord r = mRestartingServices.get(i);
9800 pw.print(" * Restarting "); pw.println(r);
9801 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009802 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009803 needSep = true;
9804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009805
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009806 if (mStoppingServices.size() > 0) {
9807 if (needSep) pw.println(" ");
9808 pw.println(" Stopping services:");
9809 for (int i=0; i<mStoppingServices.size(); i++) {
9810 ServiceRecord r = mStoppingServices.get(i);
9811 pw.print(" * Stopping "); pw.println(r);
9812 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009814 needSep = true;
9815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009816
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009817 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009818 if (mServiceConnections.size() > 0) {
9819 if (needSep) pw.println(" ");
9820 pw.println(" Connection bindings to services:");
9821 Iterator<ConnectionRecord> it
9822 = mServiceConnections.values().iterator();
9823 while (it.hasNext()) {
9824 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009825 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009826 r.dump(pw, " ");
9827 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009828 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009829 }
9830 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009831
9832 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833 }
9834
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009835 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9836 int opti, boolean dumpAll) {
9837 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009838
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009839 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009840 if (mProvidersByClass.size() > 0) {
9841 if (needSep) pw.println(" ");
9842 pw.println(" Published content providers (by class):");
9843 Iterator it = mProvidersByClass.entrySet().iterator();
9844 while (it.hasNext()) {
9845 Map.Entry e = (Map.Entry)it.next();
9846 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009847 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009848 r.dump(pw, " ");
9849 }
9850 needSep = true;
9851 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009852
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009853 if (mProvidersByName.size() > 0) {
9854 pw.println(" ");
9855 pw.println(" Authority to provider mappings:");
9856 Iterator it = mProvidersByName.entrySet().iterator();
9857 while (it.hasNext()) {
9858 Map.Entry e = (Map.Entry)it.next();
9859 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9860 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9861 pw.println(r);
9862 }
9863 needSep = true;
9864 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009866
9867 if (mLaunchingProviders.size() > 0) {
9868 if (needSep) pw.println(" ");
9869 pw.println(" Launching content providers:");
9870 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9871 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9872 pw.println(mLaunchingProviders.get(i));
9873 }
9874 needSep = true;
9875 }
9876
9877 if (mGrantedUriPermissions.size() > 0) {
9878 pw.println();
9879 pw.println("Granted Uri Permissions:");
9880 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9881 int uid = mGrantedUriPermissions.keyAt(i);
9882 HashMap<Uri, UriPermission> perms
9883 = mGrantedUriPermissions.valueAt(i);
9884 pw.print(" * UID "); pw.print(uid);
9885 pw.println(" holds:");
9886 for (UriPermission perm : perms.values()) {
9887 pw.print(" "); pw.println(perm);
9888 perm.dump(pw, " ");
9889 }
9890 }
9891 needSep = true;
9892 }
9893
9894 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009895 }
9896
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009897 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9898 int opti, boolean dumpAll) {
9899 boolean needSep = false;
9900
9901 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009902 if (this.mIntentSenderRecords.size() > 0) {
9903 Iterator<WeakReference<PendingIntentRecord>> it
9904 = mIntentSenderRecords.values().iterator();
9905 while (it.hasNext()) {
9906 WeakReference<PendingIntentRecord> ref = it.next();
9907 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009908 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009909 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009910 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009911 rec.dump(pw, " ");
9912 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009913 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009914 }
9915 }
9916 }
9917 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009918
9919 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009920 }
9921
9922 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009923 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009924 TaskRecord lastTask = null;
9925 for (int i=list.size()-1; i>=0; i--) {
9926 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009927 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009928 if (lastTask != r.task) {
9929 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009930 pw.print(prefix);
9931 pw.print(full ? "* " : " ");
9932 pw.println(lastTask);
9933 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009934 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009936 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009937 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9938 pw.print(" #"); pw.print(i); pw.print(": ");
9939 pw.println(r);
9940 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009941 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 }
9944 }
9945
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009946 private static String buildOomTag(String prefix, String space, int val, int base) {
9947 if (val == base) {
9948 if (space == null) return prefix;
9949 return prefix + " ";
9950 }
9951 return prefix + "+" + Integer.toString(val-base);
9952 }
9953
9954 private static final int dumpProcessList(PrintWriter pw,
9955 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009956 String prefix, String normalLabel, String persistentLabel,
9957 boolean inclOomAdj) {
9958 int numPers = 0;
9959 for (int i=list.size()-1; i>=0; i--) {
9960 ProcessRecord r = (ProcessRecord)list.get(i);
9961 if (false) {
9962 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
9963 + " #" + i + ":");
9964 r.dump(pw, prefix + " ");
9965 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009966 String oomAdj;
9967 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009968 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009969 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009970 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
9971 } else if (r.setAdj >= HOME_APP_ADJ) {
9972 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
9973 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
9974 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
9975 } else if (r.setAdj >= BACKUP_APP_ADJ) {
9976 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
9977 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
9978 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
9979 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
9980 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009981 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009982 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009983 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009984 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009985 } else {
9986 oomAdj = Integer.toString(r.setAdj);
9987 }
9988 String schedGroup;
9989 switch (r.setSchedGroup) {
9990 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9991 schedGroup = "B";
9992 break;
9993 case Process.THREAD_GROUP_DEFAULT:
9994 schedGroup = "F";
9995 break;
9996 default:
9997 schedGroup = Integer.toString(r.setSchedGroup);
9998 break;
9999 }
10000 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010002 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010003 if (r.adjSource != null || r.adjTarget != null) {
10004 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010005 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010007 } else {
10008 pw.println(String.format("%s%s #%2d: %s",
10009 prefix, (r.persistent ? persistentLabel : normalLabel),
10010 i, r.toString()));
10011 }
10012 if (r.persistent) {
10013 numPers++;
10014 }
10015 }
10016 return numPers;
10017 }
10018
10019 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
10020 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010021 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010022 long uptime = SystemClock.uptimeMillis();
10023 long realtime = SystemClock.elapsedRealtime();
10024
10025 if (isCheckinRequest) {
10026 // short checkin version
10027 pw.println(uptime + "," + realtime);
10028 pw.flush();
10029 } else {
10030 pw.println("Applications Memory Usage (kB):");
10031 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10032 }
10033 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10034 ProcessRecord r = (ProcessRecord)list.get(i);
10035 if (r.thread != null) {
10036 if (!isCheckinRequest) {
10037 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10038 pw.flush();
10039 }
10040 try {
10041 r.thread.asBinder().dump(fd, args);
10042 } catch (RemoteException e) {
10043 if (!isCheckinRequest) {
10044 pw.println("Got RemoteException!");
10045 pw.flush();
10046 }
10047 }
10048 }
10049 }
10050 }
10051
10052 /**
10053 * Searches array of arguments for the specified string
10054 * @param args array of argument strings
10055 * @param value value to search for
10056 * @return true if the value is contained in the array
10057 */
10058 private static boolean scanArgs(String[] args, String value) {
10059 if (args != null) {
10060 for (String arg : args) {
10061 if (value.equals(arg)) {
10062 return true;
10063 }
10064 }
10065 }
10066 return false;
10067 }
10068
Dianne Hackborn75b03852009-06-12 15:43:26 -070010069 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010070 int count = mHistory.size();
10071
10072 // convert the token to an entry in the history.
10073 HistoryRecord r = null;
10074 int index = -1;
10075 for (int i=count-1; i>=0; i--) {
10076 Object o = mHistory.get(i);
10077 if (o == token) {
10078 r = (HistoryRecord)o;
10079 index = i;
10080 break;
10081 }
10082 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010083
10084 return index;
10085 }
10086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010087 private final void killServicesLocked(ProcessRecord app,
10088 boolean allowRestart) {
10089 // Report disconnected services.
10090 if (false) {
10091 // XXX we are letting the client link to the service for
10092 // death notifications.
10093 if (app.services.size() > 0) {
10094 Iterator it = app.services.iterator();
10095 while (it.hasNext()) {
10096 ServiceRecord r = (ServiceRecord)it.next();
10097 if (r.connections.size() > 0) {
10098 Iterator<ConnectionRecord> jt
10099 = r.connections.values().iterator();
10100 while (jt.hasNext()) {
10101 ConnectionRecord c = jt.next();
10102 if (c.binding.client != app) {
10103 try {
10104 //c.conn.connected(r.className, null);
10105 } catch (Exception e) {
10106 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010107 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010108 + r.shortName
10109 + " from app " + app.processName, e);
10110 }
10111 }
10112 }
10113 }
10114 }
10115 }
10116 }
10117
10118 // Clean up any connections this application has to other services.
10119 if (app.connections.size() > 0) {
10120 Iterator<ConnectionRecord> it = app.connections.iterator();
10121 while (it.hasNext()) {
10122 ConnectionRecord r = it.next();
10123 removeConnectionLocked(r, app, null);
10124 }
10125 }
10126 app.connections.clear();
10127
10128 if (app.services.size() != 0) {
10129 // Any services running in the application need to be placed
10130 // back in the pending list.
10131 Iterator it = app.services.iterator();
10132 while (it.hasNext()) {
10133 ServiceRecord sr = (ServiceRecord)it.next();
10134 synchronized (sr.stats.getBatteryStats()) {
10135 sr.stats.stopLaunchedLocked();
10136 }
10137 sr.app = null;
10138 sr.executeNesting = 0;
10139 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010140
10141 boolean hasClients = sr.bindings.size() > 0;
10142 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010143 Iterator<IntentBindRecord> bindings
10144 = sr.bindings.values().iterator();
10145 while (bindings.hasNext()) {
10146 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010147 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 + ": shouldUnbind=" + b.hasBound);
10149 b.binder = null;
10150 b.requested = b.received = b.hasBound = false;
10151 }
10152 }
10153
10154 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010155 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010156 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010157 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010158 sr.crashCount, sr.shortName, app.pid);
10159 bringDownServiceLocked(sr, true);
10160 } else if (!allowRestart) {
10161 bringDownServiceLocked(sr, true);
10162 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010163 boolean canceled = scheduleServiceRestartLocked(sr, true);
10164
10165 // Should the service remain running? Note that in the
10166 // extreme case of so many attempts to deliver a command
10167 // that it failed, that we also will stop it here.
10168 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10169 if (sr.pendingStarts.size() == 0) {
10170 sr.startRequested = false;
10171 if (!hasClients) {
10172 // Whoops, no reason to restart!
10173 bringDownServiceLocked(sr, true);
10174 }
10175 }
10176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010177 }
10178 }
10179
10180 if (!allowRestart) {
10181 app.services.clear();
10182 }
10183 }
10184
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010185 // Make sure we have no more records on the stopping list.
10186 int i = mStoppingServices.size();
10187 while (i > 0) {
10188 i--;
10189 ServiceRecord sr = mStoppingServices.get(i);
10190 if (sr.app == app) {
10191 mStoppingServices.remove(i);
10192 }
10193 }
10194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010195 app.executingServices.clear();
10196 }
10197
10198 private final void removeDyingProviderLocked(ProcessRecord proc,
10199 ContentProviderRecord cpr) {
10200 synchronized (cpr) {
10201 cpr.launchingApp = null;
10202 cpr.notifyAll();
10203 }
10204
10205 mProvidersByClass.remove(cpr.info.name);
10206 String names[] = cpr.info.authority.split(";");
10207 for (int j = 0; j < names.length; j++) {
10208 mProvidersByName.remove(names[j]);
10209 }
10210
10211 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10212 while (cit.hasNext()) {
10213 ProcessRecord capp = cit.next();
10214 if (!capp.persistent && capp.thread != null
10215 && capp.pid != 0
10216 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010217 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010218 + " (pid " + capp.pid
10219 + ") because provider " + cpr.info.name
10220 + " is in dying process " + proc.processName);
10221 Process.killProcess(capp.pid);
10222 }
10223 }
10224
10225 mLaunchingProviders.remove(cpr);
10226 }
10227
10228 /**
10229 * Main code for cleaning up a process when it has gone away. This is
10230 * called both as a result of the process dying, or directly when stopping
10231 * a process when running in single process mode.
10232 */
10233 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10234 boolean restarting, int index) {
10235 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010236 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010237 }
10238
Dianne Hackborn36124872009-10-08 16:22:03 -070010239 mProcessesToGc.remove(app);
10240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010241 // Dismiss any open dialogs.
10242 if (app.crashDialog != null) {
10243 app.crashDialog.dismiss();
10244 app.crashDialog = null;
10245 }
10246 if (app.anrDialog != null) {
10247 app.anrDialog.dismiss();
10248 app.anrDialog = null;
10249 }
10250 if (app.waitDialog != null) {
10251 app.waitDialog.dismiss();
10252 app.waitDialog = null;
10253 }
10254
10255 app.crashing = false;
10256 app.notResponding = false;
10257
10258 app.resetPackageList();
10259 app.thread = null;
10260 app.forcingToForeground = null;
10261 app.foregroundServices = false;
10262
10263 killServicesLocked(app, true);
10264
10265 boolean restart = false;
10266
10267 int NL = mLaunchingProviders.size();
10268
10269 // Remove published content providers.
10270 if (!app.pubProviders.isEmpty()) {
10271 Iterator it = app.pubProviders.values().iterator();
10272 while (it.hasNext()) {
10273 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10274 cpr.provider = null;
10275 cpr.app = null;
10276
10277 // See if someone is waiting for this provider... in which
10278 // case we don't remove it, but just let it restart.
10279 int i = 0;
10280 if (!app.bad) {
10281 for (; i<NL; i++) {
10282 if (mLaunchingProviders.get(i) == cpr) {
10283 restart = true;
10284 break;
10285 }
10286 }
10287 } else {
10288 i = NL;
10289 }
10290
10291 if (i >= NL) {
10292 removeDyingProviderLocked(app, cpr);
10293 NL = mLaunchingProviders.size();
10294 }
10295 }
10296 app.pubProviders.clear();
10297 }
10298
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010299 // Take care of any launching providers waiting for this process.
10300 if (checkAppInLaunchingProvidersLocked(app, false)) {
10301 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010302 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010304 // Unregister from connected content providers.
10305 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010306 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010307 while (it.hasNext()) {
10308 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10309 cpr.clients.remove(app);
10310 }
10311 app.conProviders.clear();
10312 }
10313
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010314 // At this point there may be remaining entries in mLaunchingProviders
10315 // where we were the only one waiting, so they are no longer of use.
10316 // Look for these and clean up if found.
10317 // XXX Commented out for now. Trying to figure out a way to reproduce
10318 // the actual situation to identify what is actually going on.
10319 if (false) {
10320 for (int i=0; i<NL; i++) {
10321 ContentProviderRecord cpr = (ContentProviderRecord)
10322 mLaunchingProviders.get(i);
10323 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10324 synchronized (cpr) {
10325 cpr.launchingApp = null;
10326 cpr.notifyAll();
10327 }
10328 }
10329 }
10330 }
10331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332 skipCurrentReceiverLocked(app);
10333
10334 // Unregister any receivers.
10335 if (app.receivers.size() > 0) {
10336 Iterator<ReceiverList> it = app.receivers.iterator();
10337 while (it.hasNext()) {
10338 removeReceiverLocked(it.next());
10339 }
10340 app.receivers.clear();
10341 }
10342
Christopher Tate181fafa2009-05-14 11:12:14 -070010343 // If the app is undergoing backup, tell the backup manager about it
10344 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010345 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010346 try {
10347 IBackupManager bm = IBackupManager.Stub.asInterface(
10348 ServiceManager.getService(Context.BACKUP_SERVICE));
10349 bm.agentDisconnected(app.info.packageName);
10350 } catch (RemoteException e) {
10351 // can't happen; backup manager is local
10352 }
10353 }
10354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010355 // If the caller is restarting this app, then leave it in its
10356 // current lists and let the caller take care of it.
10357 if (restarting) {
10358 return;
10359 }
10360
10361 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010362 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010363 "Removing non-persistent process during cleanup: " + app);
10364 mProcessNames.remove(app.processName, app.info.uid);
10365 } else if (!app.removed) {
10366 // This app is persistent, so we need to keep its record around.
10367 // If it is not already on the pending app list, add it there
10368 // and start a new process for it.
10369 app.thread = null;
10370 app.forcingToForeground = null;
10371 app.foregroundServices = false;
10372 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10373 mPersistentStartingProcesses.add(app);
10374 restart = true;
10375 }
10376 }
10377 mProcessesOnHold.remove(app);
10378
The Android Open Source Project4df24232009-03-05 14:34:35 -080010379 if (app == mHomeProcess) {
10380 mHomeProcess = null;
10381 }
10382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 if (restart) {
10384 // We have components that still need to be running in the
10385 // process, so re-launch it.
10386 mProcessNames.put(app.processName, app.info.uid, app);
10387 startProcessLocked(app, "restart", app.processName);
10388 } else if (app.pid > 0 && app.pid != MY_PID) {
10389 // Goodbye!
10390 synchronized (mPidsSelfLocked) {
10391 mPidsSelfLocked.remove(app.pid);
10392 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10393 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010394 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010395 }
10396 }
10397
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010398 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10399 // Look through the content providers we are waiting to have launched,
10400 // and if any run in this process then either schedule a restart of
10401 // the process or kill the client waiting for it if this process has
10402 // gone bad.
10403 int NL = mLaunchingProviders.size();
10404 boolean restart = false;
10405 for (int i=0; i<NL; i++) {
10406 ContentProviderRecord cpr = (ContentProviderRecord)
10407 mLaunchingProviders.get(i);
10408 if (cpr.launchingApp == app) {
10409 if (!alwaysBad && !app.bad) {
10410 restart = true;
10411 } else {
10412 removeDyingProviderLocked(app, cpr);
10413 NL = mLaunchingProviders.size();
10414 }
10415 }
10416 }
10417 return restart;
10418 }
10419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010420 // =========================================================
10421 // SERVICES
10422 // =========================================================
10423
10424 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10425 ActivityManager.RunningServiceInfo info =
10426 new ActivityManager.RunningServiceInfo();
10427 info.service = r.name;
10428 if (r.app != null) {
10429 info.pid = r.app.pid;
10430 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010431 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010432 info.process = r.processName;
10433 info.foreground = r.isForeground;
10434 info.activeSince = r.createTime;
10435 info.started = r.startRequested;
10436 info.clientCount = r.connections.size();
10437 info.crashCount = r.crashCount;
10438 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010439 if (r.isForeground) {
10440 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10441 }
10442 if (r.startRequested) {
10443 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10444 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010445 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010446 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10447 }
10448 if (r.app != null && r.app.persistent) {
10449 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10450 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010451 for (ConnectionRecord conn : r.connections.values()) {
10452 if (conn.clientLabel != 0) {
10453 info.clientPackage = conn.binding.client.info.packageName;
10454 info.clientLabel = conn.clientLabel;
10455 break;
10456 }
10457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010458 return info;
10459 }
10460
10461 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10462 int flags) {
10463 synchronized (this) {
10464 ArrayList<ActivityManager.RunningServiceInfo> res
10465 = new ArrayList<ActivityManager.RunningServiceInfo>();
10466
10467 if (mServices.size() > 0) {
10468 Iterator<ServiceRecord> it = mServices.values().iterator();
10469 while (it.hasNext() && res.size() < maxNum) {
10470 res.add(makeRunningServiceInfoLocked(it.next()));
10471 }
10472 }
10473
10474 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10475 ServiceRecord r = mRestartingServices.get(i);
10476 ActivityManager.RunningServiceInfo info =
10477 makeRunningServiceInfoLocked(r);
10478 info.restarting = r.nextRestartTime;
10479 res.add(info);
10480 }
10481
10482 return res;
10483 }
10484 }
10485
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010486 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10487 synchronized (this) {
10488 ServiceRecord r = mServices.get(name);
10489 if (r != null) {
10490 for (ConnectionRecord conn : r.connections.values()) {
10491 if (conn.clientIntent != null) {
10492 return conn.clientIntent;
10493 }
10494 }
10495 }
10496 }
10497 return null;
10498 }
10499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 private final ServiceRecord findServiceLocked(ComponentName name,
10501 IBinder token) {
10502 ServiceRecord r = mServices.get(name);
10503 return r == token ? r : null;
10504 }
10505
10506 private final class ServiceLookupResult {
10507 final ServiceRecord record;
10508 final String permission;
10509
10510 ServiceLookupResult(ServiceRecord _record, String _permission) {
10511 record = _record;
10512 permission = _permission;
10513 }
10514 };
10515
10516 private ServiceLookupResult findServiceLocked(Intent service,
10517 String resolvedType) {
10518 ServiceRecord r = null;
10519 if (service.getComponent() != null) {
10520 r = mServices.get(service.getComponent());
10521 }
10522 if (r == null) {
10523 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10524 r = mServicesByIntent.get(filter);
10525 }
10526
10527 if (r == null) {
10528 try {
10529 ResolveInfo rInfo =
10530 ActivityThread.getPackageManager().resolveService(
10531 service, resolvedType, 0);
10532 ServiceInfo sInfo =
10533 rInfo != null ? rInfo.serviceInfo : null;
10534 if (sInfo == null) {
10535 return null;
10536 }
10537
10538 ComponentName name = new ComponentName(
10539 sInfo.applicationInfo.packageName, sInfo.name);
10540 r = mServices.get(name);
10541 } catch (RemoteException ex) {
10542 // pm is in same process, this will never happen.
10543 }
10544 }
10545 if (r != null) {
10546 int callingPid = Binder.getCallingPid();
10547 int callingUid = Binder.getCallingUid();
10548 if (checkComponentPermission(r.permission,
10549 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10550 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010551 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010552 + " from pid=" + callingPid
10553 + ", uid=" + callingUid
10554 + " requires " + r.permission);
10555 return new ServiceLookupResult(null, r.permission);
10556 }
10557 return new ServiceLookupResult(r, null);
10558 }
10559 return null;
10560 }
10561
10562 private class ServiceRestarter implements Runnable {
10563 private ServiceRecord mService;
10564
10565 void setService(ServiceRecord service) {
10566 mService = service;
10567 }
10568
10569 public void run() {
10570 synchronized(ActivityManagerService.this) {
10571 performServiceRestartLocked(mService);
10572 }
10573 }
10574 }
10575
10576 private ServiceLookupResult retrieveServiceLocked(Intent service,
10577 String resolvedType, int callingPid, int callingUid) {
10578 ServiceRecord r = null;
10579 if (service.getComponent() != null) {
10580 r = mServices.get(service.getComponent());
10581 }
10582 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10583 r = mServicesByIntent.get(filter);
10584 if (r == null) {
10585 try {
10586 ResolveInfo rInfo =
10587 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010588 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010589 ServiceInfo sInfo =
10590 rInfo != null ? rInfo.serviceInfo : null;
10591 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010592 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010593 ": not found");
10594 return null;
10595 }
10596
10597 ComponentName name = new ComponentName(
10598 sInfo.applicationInfo.packageName, sInfo.name);
10599 r = mServices.get(name);
10600 if (r == null) {
10601 filter = new Intent.FilterComparison(service.cloneFilter());
10602 ServiceRestarter res = new ServiceRestarter();
10603 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10604 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10605 synchronized (stats) {
10606 ss = stats.getServiceStatsLocked(
10607 sInfo.applicationInfo.uid, sInfo.packageName,
10608 sInfo.name);
10609 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010610 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 res.setService(r);
10612 mServices.put(name, r);
10613 mServicesByIntent.put(filter, r);
10614
10615 // Make sure this component isn't in the pending list.
10616 int N = mPendingServices.size();
10617 for (int i=0; i<N; i++) {
10618 ServiceRecord pr = mPendingServices.get(i);
10619 if (pr.name.equals(name)) {
10620 mPendingServices.remove(i);
10621 i--;
10622 N--;
10623 }
10624 }
10625 }
10626 } catch (RemoteException ex) {
10627 // pm is in same process, this will never happen.
10628 }
10629 }
10630 if (r != null) {
10631 if (checkComponentPermission(r.permission,
10632 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10633 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010634 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010635 + " from pid=" + Binder.getCallingPid()
10636 + ", uid=" + Binder.getCallingUid()
10637 + " requires " + r.permission);
10638 return new ServiceLookupResult(null, r.permission);
10639 }
10640 return new ServiceLookupResult(r, null);
10641 }
10642 return null;
10643 }
10644
10645 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10646 long now = SystemClock.uptimeMillis();
10647 if (r.executeNesting == 0 && r.app != null) {
10648 if (r.app.executingServices.size() == 0) {
10649 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10650 msg.obj = r.app;
10651 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10652 }
10653 r.app.executingServices.add(r);
10654 }
10655 r.executeNesting++;
10656 r.executingStart = now;
10657 }
10658
10659 private final void sendServiceArgsLocked(ServiceRecord r,
10660 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010661 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010662 if (N == 0) {
10663 return;
10664 }
10665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010666 int i = 0;
10667 while (i < N) {
10668 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010669 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010670 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010671 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010672 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010673 // If somehow we got a dummy start at the front, then
10674 // just drop it here.
10675 i++;
10676 continue;
10677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010678 bumpServiceExecutingLocked(r);
10679 if (!oomAdjusted) {
10680 oomAdjusted = true;
10681 updateOomAdjLocked(r.app);
10682 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010683 int flags = 0;
10684 if (si.deliveryCount > 0) {
10685 flags |= Service.START_FLAG_RETRY;
10686 }
10687 if (si.doneExecutingCount > 0) {
10688 flags |= Service.START_FLAG_REDELIVERY;
10689 }
10690 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10691 si.deliveredTime = SystemClock.uptimeMillis();
10692 r.deliveredStarts.add(si);
10693 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010694 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010695 } catch (RemoteException e) {
10696 // Remote process gone... we'll let the normal cleanup take
10697 // care of this.
10698 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010699 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010700 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010701 break;
10702 }
10703 }
10704 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010705 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010706 } else {
10707 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010708 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010709 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010710 }
10711 }
10712 }
10713
10714 private final boolean requestServiceBindingLocked(ServiceRecord r,
10715 IntentBindRecord i, boolean rebind) {
10716 if (r.app == null || r.app.thread == null) {
10717 // If service is not currently running, can't yet bind.
10718 return false;
10719 }
10720 if ((!i.requested || rebind) && i.apps.size() > 0) {
10721 try {
10722 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010723 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010724 + ": shouldUnbind=" + i.hasBound);
10725 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10726 if (!rebind) {
10727 i.requested = true;
10728 }
10729 i.hasBound = true;
10730 i.doRebind = false;
10731 } catch (RemoteException e) {
10732 return false;
10733 }
10734 }
10735 return true;
10736 }
10737
10738 private final void requestServiceBindingsLocked(ServiceRecord r) {
10739 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10740 while (bindings.hasNext()) {
10741 IntentBindRecord i = bindings.next();
10742 if (!requestServiceBindingLocked(r, i, false)) {
10743 break;
10744 }
10745 }
10746 }
10747
10748 private final void realStartServiceLocked(ServiceRecord r,
10749 ProcessRecord app) throws RemoteException {
10750 if (app.thread == null) {
10751 throw new RemoteException();
10752 }
10753
10754 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010755 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010756
10757 app.services.add(r);
10758 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010759 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010760
10761 boolean created = false;
10762 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010763 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010765 mStringBuilder.setLength(0);
10766 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010767 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010768 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010769 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010770 synchronized (r.stats.getBatteryStats()) {
10771 r.stats.startLaunchedLocked();
10772 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010773 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010774 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010775 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010776 created = true;
10777 } finally {
10778 if (!created) {
10779 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010780 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010781 }
10782 }
10783
10784 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010785
10786 // If the service is in the started state, and there are no
10787 // pending arguments, then fake up one so its onStartCommand() will
10788 // be called.
10789 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10790 r.lastStartId++;
10791 if (r.lastStartId < 1) {
10792 r.lastStartId = 1;
10793 }
10794 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10795 }
10796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 sendServiceArgsLocked(r, true);
10798 }
10799
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010800 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10801 boolean allowCancel) {
10802 boolean canceled = false;
10803
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010804 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010805 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010806 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010807
10808 // Any delivered but not yet finished starts should be put back
10809 // on the pending list.
10810 final int N = r.deliveredStarts.size();
10811 if (N > 0) {
10812 for (int i=N-1; i>=0; i--) {
10813 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10814 if (si.intent == null) {
10815 // We'll generate this again if needed.
10816 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10817 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10818 r.pendingStarts.add(0, si);
10819 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10820 dur *= 2;
10821 if (minDuration < dur) minDuration = dur;
10822 if (resetTime < dur) resetTime = dur;
10823 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010824 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010825 + r.name);
10826 canceled = true;
10827 }
10828 }
10829 r.deliveredStarts.clear();
10830 }
10831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010832 r.totalRestartCount++;
10833 if (r.restartDelay == 0) {
10834 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010835 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 } else {
10837 // If it has been a "reasonably long time" since the service
10838 // was started, then reset our restart duration back to
10839 // the beginning, so we don't infinitely increase the duration
10840 // on a service that just occasionally gets killed (which is
10841 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010842 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010843 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010844 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010845 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010846 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010847 if (r.restartDelay < minDuration) {
10848 r.restartDelay = minDuration;
10849 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010850 }
10851 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010852
10853 r.nextRestartTime = now + r.restartDelay;
10854
10855 // Make sure that we don't end up restarting a bunch of services
10856 // all at the same time.
10857 boolean repeat;
10858 do {
10859 repeat = false;
10860 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10861 ServiceRecord r2 = mRestartingServices.get(i);
10862 if (r2 != r && r.nextRestartTime
10863 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10864 && r.nextRestartTime
10865 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10866 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10867 r.restartDelay = r.nextRestartTime - now;
10868 repeat = true;
10869 break;
10870 }
10871 }
10872 } while (repeat);
10873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010874 if (!mRestartingServices.contains(r)) {
10875 mRestartingServices.add(r);
10876 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010877
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010878 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010880 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010881 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010883 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010884 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010885 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010886 r.shortName, r.restartDelay);
10887
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010888 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010889 }
10890
10891 final void performServiceRestartLocked(ServiceRecord r) {
10892 if (!mRestartingServices.contains(r)) {
10893 return;
10894 }
10895 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10896 }
10897
10898 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10899 if (r.restartDelay == 0) {
10900 return false;
10901 }
10902 r.resetRestartCounter();
10903 mRestartingServices.remove(r);
10904 mHandler.removeCallbacks(r.restarter);
10905 return true;
10906 }
10907
10908 private final boolean bringUpServiceLocked(ServiceRecord r,
10909 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010910 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010911 //r.dump(" ");
10912
Dianne Hackborn36124872009-10-08 16:22:03 -070010913 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010914 sendServiceArgsLocked(r, false);
10915 return true;
10916 }
10917
10918 if (!whileRestarting && r.restartDelay > 0) {
10919 // If waiting for a restart, then do nothing.
10920 return true;
10921 }
10922
Joe Onorato8a9b2202010-02-26 18:56:32 -080010923 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010924 + " " + r.intent);
10925
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010926 // We are now bringing the service up, so no longer in the
10927 // restarting state.
10928 mRestartingServices.remove(r);
10929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010930 final String appName = r.processName;
10931 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10932 if (app != null && app.thread != null) {
10933 try {
10934 realStartServiceLocked(r, app);
10935 return true;
10936 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010937 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 }
10939
10940 // If a dead object exception was thrown -- fall through to
10941 // restart the application.
10942 }
10943
Dianne Hackborn36124872009-10-08 16:22:03 -070010944 // Not running -- get it started, and enqueue this service record
10945 // to be executed when the app comes up.
10946 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10947 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010948 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070010949 + r.appInfo.packageName + "/"
10950 + r.appInfo.uid + " for service "
10951 + r.intent.getIntent() + ": process is bad");
10952 bringDownServiceLocked(r, true);
10953 return false;
10954 }
10955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010956 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 mPendingServices.add(r);
10958 }
Dianne Hackborn36124872009-10-08 16:22:03 -070010959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 return true;
10961 }
10962
10963 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010964 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010965 //r.dump(" ");
10966
10967 // Does it still need to run?
10968 if (!force && r.startRequested) {
10969 return;
10970 }
10971 if (r.connections.size() > 0) {
10972 if (!force) {
10973 // XXX should probably keep a count of the number of auto-create
10974 // connections directly in the service.
10975 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10976 while (it.hasNext()) {
10977 ConnectionRecord cr = it.next();
10978 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10979 return;
10980 }
10981 }
10982 }
10983
10984 // Report to all of the connections that the service is no longer
10985 // available.
10986 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10987 while (it.hasNext()) {
10988 ConnectionRecord c = it.next();
10989 try {
10990 // todo: shouldn't be a synchronous call!
10991 c.conn.connected(r.name, null);
10992 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010993 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010994 " to connection " + c.conn.asBinder() +
10995 " (in " + c.binding.client.processName + ")", e);
10996 }
10997 }
10998 }
10999
11000 // Tell the service that it has been unbound.
11001 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11002 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11003 while (it.hasNext()) {
11004 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011005 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011006 + ": hasBound=" + ibr.hasBound);
11007 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11008 try {
11009 bumpServiceExecutingLocked(r);
11010 updateOomAdjLocked(r.app);
11011 ibr.hasBound = false;
11012 r.app.thread.scheduleUnbindService(r,
11013 ibr.intent.getIntent());
11014 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011015 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 + r.shortName, e);
11017 serviceDoneExecutingLocked(r, true);
11018 }
11019 }
11020 }
11021 }
11022
Joe Onorato8a9b2202010-02-26 18:56:32 -080011023 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011024 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011025 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026 System.identityHashCode(r), r.shortName,
11027 (r.app != null) ? r.app.pid : -1);
11028
11029 mServices.remove(r.name);
11030 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011031 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011032 r.totalRestartCount = 0;
11033 unscheduleServiceRestartLocked(r);
11034
11035 // Also make sure it is not on the pending list.
11036 int N = mPendingServices.size();
11037 for (int i=0; i<N; i++) {
11038 if (mPendingServices.get(i) == r) {
11039 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011040 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 TAG, "Removed pending service: " + r.shortName);
11042 i--;
11043 N--;
11044 }
11045 }
11046
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011047 r.cancelNotification();
11048 r.isForeground = false;
11049 r.foregroundId = 0;
11050 r.foregroundNoti = null;
11051
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011052 // Clear start entries.
11053 r.deliveredStarts.clear();
11054 r.pendingStarts.clear();
11055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 if (r.app != null) {
11057 synchronized (r.stats.getBatteryStats()) {
11058 r.stats.stopLaunchedLocked();
11059 }
11060 r.app.services.remove(r);
11061 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011063 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011064 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 bumpServiceExecutingLocked(r);
11066 mStoppingServices.add(r);
11067 updateOomAdjLocked(r.app);
11068 r.app.thread.scheduleStopService(r);
11069 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011070 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011071 + r.shortName, e);
11072 serviceDoneExecutingLocked(r, true);
11073 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011074 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011075 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011076 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077 TAG, "Removed service that has no process: " + r.shortName);
11078 }
11079 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011080 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011081 TAG, "Removed service that is not running: " + r.shortName);
11082 }
11083 }
11084
11085 ComponentName startServiceLocked(IApplicationThread caller,
11086 Intent service, String resolvedType,
11087 int callingPid, int callingUid) {
11088 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011089 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011090 + " type=" + resolvedType + " args=" + service.getExtras());
11091
11092 if (caller != null) {
11093 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11094 if (callerApp == null) {
11095 throw new SecurityException(
11096 "Unable to find app for caller " + caller
11097 + " (pid=" + Binder.getCallingPid()
11098 + ") when starting service " + service);
11099 }
11100 }
11101
11102 ServiceLookupResult res =
11103 retrieveServiceLocked(service, resolvedType,
11104 callingPid, callingUid);
11105 if (res == null) {
11106 return null;
11107 }
11108 if (res.record == null) {
11109 return new ComponentName("!", res.permission != null
11110 ? res.permission : "private to package");
11111 }
11112 ServiceRecord r = res.record;
11113 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011114 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011115 + r.shortName);
11116 }
11117 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011118 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011119 r.lastStartId++;
11120 if (r.lastStartId < 1) {
11121 r.lastStartId = 1;
11122 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011123 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011124 r.lastActivity = SystemClock.uptimeMillis();
11125 synchronized (r.stats.getBatteryStats()) {
11126 r.stats.startRunningLocked();
11127 }
11128 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11129 return new ComponentName("!", "Service process is bad");
11130 }
11131 return r.name;
11132 }
11133 }
11134
11135 public ComponentName startService(IApplicationThread caller, Intent service,
11136 String resolvedType) {
11137 // Refuse possible leaked file descriptors
11138 if (service != null && service.hasFileDescriptors() == true) {
11139 throw new IllegalArgumentException("File descriptors passed in Intent");
11140 }
11141
11142 synchronized(this) {
11143 final int callingPid = Binder.getCallingPid();
11144 final int callingUid = Binder.getCallingUid();
11145 final long origId = Binder.clearCallingIdentity();
11146 ComponentName res = startServiceLocked(caller, service,
11147 resolvedType, callingPid, callingUid);
11148 Binder.restoreCallingIdentity(origId);
11149 return res;
11150 }
11151 }
11152
11153 ComponentName startServiceInPackage(int uid,
11154 Intent service, String resolvedType) {
11155 synchronized(this) {
11156 final long origId = Binder.clearCallingIdentity();
11157 ComponentName res = startServiceLocked(null, service,
11158 resolvedType, -1, uid);
11159 Binder.restoreCallingIdentity(origId);
11160 return res;
11161 }
11162 }
11163
11164 public int stopService(IApplicationThread caller, Intent service,
11165 String resolvedType) {
11166 // Refuse possible leaked file descriptors
11167 if (service != null && service.hasFileDescriptors() == true) {
11168 throw new IllegalArgumentException("File descriptors passed in Intent");
11169 }
11170
11171 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011172 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011173 + " type=" + resolvedType);
11174
11175 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11176 if (caller != null && callerApp == null) {
11177 throw new SecurityException(
11178 "Unable to find app for caller " + caller
11179 + " (pid=" + Binder.getCallingPid()
11180 + ") when stopping service " + service);
11181 }
11182
11183 // If this service is active, make sure it is stopped.
11184 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11185 if (r != null) {
11186 if (r.record != null) {
11187 synchronized (r.record.stats.getBatteryStats()) {
11188 r.record.stats.stopRunningLocked();
11189 }
11190 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011191 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 final long origId = Binder.clearCallingIdentity();
11193 bringDownServiceLocked(r.record, false);
11194 Binder.restoreCallingIdentity(origId);
11195 return 1;
11196 }
11197 return -1;
11198 }
11199 }
11200
11201 return 0;
11202 }
11203
11204 public IBinder peekService(Intent service, String resolvedType) {
11205 // Refuse possible leaked file descriptors
11206 if (service != null && service.hasFileDescriptors() == true) {
11207 throw new IllegalArgumentException("File descriptors passed in Intent");
11208 }
11209
11210 IBinder ret = null;
11211
11212 synchronized(this) {
11213 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11214
11215 if (r != null) {
11216 // r.record is null if findServiceLocked() failed the caller permission check
11217 if (r.record == null) {
11218 throw new SecurityException(
11219 "Permission Denial: Accessing service " + r.record.name
11220 + " from pid=" + Binder.getCallingPid()
11221 + ", uid=" + Binder.getCallingUid()
11222 + " requires " + r.permission);
11223 }
11224 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11225 if (ib != null) {
11226 ret = ib.binder;
11227 }
11228 }
11229 }
11230
11231 return ret;
11232 }
11233
11234 public boolean stopServiceToken(ComponentName className, IBinder token,
11235 int startId) {
11236 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011237 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011238 + " " + token + " startId=" + startId);
11239 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011240 if (r != null) {
11241 if (startId >= 0) {
11242 // Asked to only stop if done with all work. Note that
11243 // to avoid leaks, we will take this as dropping all
11244 // start items up to and including this one.
11245 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11246 if (si != null) {
11247 while (r.deliveredStarts.size() > 0) {
11248 if (r.deliveredStarts.remove(0) == si) {
11249 break;
11250 }
11251 }
11252 }
11253
11254 if (r.lastStartId != startId) {
11255 return false;
11256 }
11257
11258 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011259 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011260 + " is last, but have " + r.deliveredStarts.size()
11261 + " remaining args");
11262 }
11263 }
11264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011265 synchronized (r.stats.getBatteryStats()) {
11266 r.stats.stopRunningLocked();
11267 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011268 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 }
11270 final long origId = Binder.clearCallingIdentity();
11271 bringDownServiceLocked(r, false);
11272 Binder.restoreCallingIdentity(origId);
11273 return true;
11274 }
11275 }
11276 return false;
11277 }
11278
11279 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011280 int id, Notification notification, boolean removeNotification) {
11281 final long origId = Binder.clearCallingIdentity();
11282 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011283 synchronized(this) {
11284 ServiceRecord r = findServiceLocked(className, token);
11285 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011286 if (id != 0) {
11287 if (notification == null) {
11288 throw new IllegalArgumentException("null notification");
11289 }
11290 if (r.foregroundId != id) {
11291 r.cancelNotification();
11292 r.foregroundId = id;
11293 }
11294 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11295 r.foregroundNoti = notification;
11296 r.isForeground = true;
11297 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011298 if (r.app != null) {
11299 updateServiceForegroundLocked(r.app, true);
11300 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011301 } else {
11302 if (r.isForeground) {
11303 r.isForeground = false;
11304 if (r.app != null) {
11305 updateServiceForegroundLocked(r.app, true);
11306 }
11307 }
11308 if (removeNotification) {
11309 r.cancelNotification();
11310 r.foregroundId = 0;
11311 r.foregroundNoti = null;
11312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 }
11314 }
11315 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011316 } finally {
11317 Binder.restoreCallingIdentity(origId);
11318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011319 }
11320
11321 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11322 boolean anyForeground = false;
11323 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11324 if (sr.isForeground) {
11325 anyForeground = true;
11326 break;
11327 }
11328 }
11329 if (anyForeground != proc.foregroundServices) {
11330 proc.foregroundServices = anyForeground;
11331 if (oomAdj) {
11332 updateOomAdjLocked();
11333 }
11334 }
11335 }
11336
11337 public int bindService(IApplicationThread caller, IBinder token,
11338 Intent service, String resolvedType,
11339 IServiceConnection connection, int flags) {
11340 // Refuse possible leaked file descriptors
11341 if (service != null && service.hasFileDescriptors() == true) {
11342 throw new IllegalArgumentException("File descriptors passed in Intent");
11343 }
11344
11345 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011346 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 + " type=" + resolvedType + " conn=" + connection.asBinder()
11348 + " flags=0x" + Integer.toHexString(flags));
11349 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11350 if (callerApp == null) {
11351 throw new SecurityException(
11352 "Unable to find app for caller " + caller
11353 + " (pid=" + Binder.getCallingPid()
11354 + ") when binding service " + service);
11355 }
11356
11357 HistoryRecord activity = null;
11358 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011359 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011361 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 return 0;
11363 }
11364 activity = (HistoryRecord)mHistory.get(aindex);
11365 }
11366
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011367 int clientLabel = 0;
11368 PendingIntent clientIntent = null;
11369
11370 if (callerApp.info.uid == Process.SYSTEM_UID) {
11371 // Hacky kind of thing -- allow system stuff to tell us
11372 // what they are, so we can report this elsewhere for
11373 // others to know why certain services are running.
11374 try {
11375 clientIntent = (PendingIntent)service.getParcelableExtra(
11376 Intent.EXTRA_CLIENT_INTENT);
11377 } catch (RuntimeException e) {
11378 }
11379 if (clientIntent != null) {
11380 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11381 if (clientLabel != 0) {
11382 // There are no useful extras in the intent, trash them.
11383 // System code calling with this stuff just needs to know
11384 // this will happen.
11385 service = service.cloneFilter();
11386 }
11387 }
11388 }
11389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011390 ServiceLookupResult res =
11391 retrieveServiceLocked(service, resolvedType,
11392 Binder.getCallingPid(), Binder.getCallingUid());
11393 if (res == null) {
11394 return 0;
11395 }
11396 if (res.record == null) {
11397 return -1;
11398 }
11399 ServiceRecord s = res.record;
11400
11401 final long origId = Binder.clearCallingIdentity();
11402
11403 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011404 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405 + s.shortName);
11406 }
11407
11408 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11409 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011410 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011411
11412 IBinder binder = connection.asBinder();
11413 s.connections.put(binder, c);
11414 b.connections.add(c);
11415 if (activity != null) {
11416 if (activity.connections == null) {
11417 activity.connections = new HashSet<ConnectionRecord>();
11418 }
11419 activity.connections.add(c);
11420 }
11421 b.client.connections.add(c);
11422 mServiceConnections.put(binder, c);
11423
11424 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11425 s.lastActivity = SystemClock.uptimeMillis();
11426 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11427 return 0;
11428 }
11429 }
11430
11431 if (s.app != null) {
11432 // This could have made the service more important.
11433 updateOomAdjLocked(s.app);
11434 }
11435
Joe Onorato8a9b2202010-02-26 18:56:32 -080011436 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011437 + ": received=" + b.intent.received
11438 + " apps=" + b.intent.apps.size()
11439 + " doRebind=" + b.intent.doRebind);
11440
11441 if (s.app != null && b.intent.received) {
11442 // Service is already running, so we can immediately
11443 // publish the connection.
11444 try {
11445 c.conn.connected(s.name, b.intent.binder);
11446 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011447 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011448 + " to connection " + c.conn.asBinder()
11449 + " (in " + c.binding.client.processName + ")", e);
11450 }
11451
11452 // If this is the first app connected back to this binding,
11453 // and the service had previously asked to be told when
11454 // rebound, then do so.
11455 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11456 requestServiceBindingLocked(s, b.intent, true);
11457 }
11458 } else if (!b.intent.requested) {
11459 requestServiceBindingLocked(s, b.intent, false);
11460 }
11461
11462 Binder.restoreCallingIdentity(origId);
11463 }
11464
11465 return 1;
11466 }
11467
11468 private void removeConnectionLocked(
11469 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11470 IBinder binder = c.conn.asBinder();
11471 AppBindRecord b = c.binding;
11472 ServiceRecord s = b.service;
11473 s.connections.remove(binder);
11474 b.connections.remove(c);
11475 if (c.activity != null && c.activity != skipAct) {
11476 if (c.activity.connections != null) {
11477 c.activity.connections.remove(c);
11478 }
11479 }
11480 if (b.client != skipApp) {
11481 b.client.connections.remove(c);
11482 }
11483 mServiceConnections.remove(binder);
11484
11485 if (b.connections.size() == 0) {
11486 b.intent.apps.remove(b.client);
11487 }
11488
Joe Onorato8a9b2202010-02-26 18:56:32 -080011489 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011490 + ": shouldUnbind=" + b.intent.hasBound);
11491 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11492 && b.intent.hasBound) {
11493 try {
11494 bumpServiceExecutingLocked(s);
11495 updateOomAdjLocked(s.app);
11496 b.intent.hasBound = false;
11497 // Assume the client doesn't want to know about a rebind;
11498 // we will deal with that later if it asks for one.
11499 b.intent.doRebind = false;
11500 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11501 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011502 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 serviceDoneExecutingLocked(s, true);
11504 }
11505 }
11506
11507 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11508 bringDownServiceLocked(s, false);
11509 }
11510 }
11511
11512 public boolean unbindService(IServiceConnection connection) {
11513 synchronized (this) {
11514 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011515 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011516 ConnectionRecord r = mServiceConnections.get(binder);
11517 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011518 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011519 + connection.asBinder());
11520 return false;
11521 }
11522
11523 final long origId = Binder.clearCallingIdentity();
11524
11525 removeConnectionLocked(r, null, null);
11526
11527 if (r.binding.service.app != null) {
11528 // This could have made the service less important.
11529 updateOomAdjLocked(r.binding.service.app);
11530 }
11531
11532 Binder.restoreCallingIdentity(origId);
11533 }
11534
11535 return true;
11536 }
11537
11538 public void publishService(IBinder token, Intent intent, IBinder service) {
11539 // Refuse possible leaked file descriptors
11540 if (intent != null && intent.hasFileDescriptors() == true) {
11541 throw new IllegalArgumentException("File descriptors passed in Intent");
11542 }
11543
11544 synchronized(this) {
11545 if (!(token instanceof ServiceRecord)) {
11546 throw new IllegalArgumentException("Invalid service token");
11547 }
11548 ServiceRecord r = (ServiceRecord)token;
11549
11550 final long origId = Binder.clearCallingIdentity();
11551
Joe Onorato8a9b2202010-02-26 18:56:32 -080011552 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011553 + " " + intent + ": " + service);
11554 if (r != null) {
11555 Intent.FilterComparison filter
11556 = new Intent.FilterComparison(intent);
11557 IntentBindRecord b = r.bindings.get(filter);
11558 if (b != null && !b.received) {
11559 b.binder = service;
11560 b.requested = true;
11561 b.received = true;
11562 if (r.connections.size() > 0) {
11563 Iterator<ConnectionRecord> it
11564 = r.connections.values().iterator();
11565 while (it.hasNext()) {
11566 ConnectionRecord c = it.next();
11567 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011568 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011569 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011570 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011572 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011573 TAG, "Published intent: " + intent);
11574 continue;
11575 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011576 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011577 try {
11578 c.conn.connected(r.name, service);
11579 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011580 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011581 " to connection " + c.conn.asBinder() +
11582 " (in " + c.binding.client.processName + ")", e);
11583 }
11584 }
11585 }
11586 }
11587
11588 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11589
11590 Binder.restoreCallingIdentity(origId);
11591 }
11592 }
11593 }
11594
11595 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11596 // Refuse possible leaked file descriptors
11597 if (intent != null && intent.hasFileDescriptors() == true) {
11598 throw new IllegalArgumentException("File descriptors passed in Intent");
11599 }
11600
11601 synchronized(this) {
11602 if (!(token instanceof ServiceRecord)) {
11603 throw new IllegalArgumentException("Invalid service token");
11604 }
11605 ServiceRecord r = (ServiceRecord)token;
11606
11607 final long origId = Binder.clearCallingIdentity();
11608
11609 if (r != null) {
11610 Intent.FilterComparison filter
11611 = new Intent.FilterComparison(intent);
11612 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011613 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 + " at " + b + ": apps="
11615 + (b != null ? b.apps.size() : 0));
11616 if (b != null) {
11617 if (b.apps.size() > 0) {
11618 // Applications have already bound since the last
11619 // unbind, so just rebind right here.
11620 requestServiceBindingLocked(r, b, true);
11621 } else {
11622 // Note to tell the service the next time there is
11623 // a new client.
11624 b.doRebind = true;
11625 }
11626 }
11627
11628 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11629
11630 Binder.restoreCallingIdentity(origId);
11631 }
11632 }
11633 }
11634
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011635 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 synchronized(this) {
11637 if (!(token instanceof ServiceRecord)) {
11638 throw new IllegalArgumentException("Invalid service token");
11639 }
11640 ServiceRecord r = (ServiceRecord)token;
11641 boolean inStopping = mStoppingServices.contains(token);
11642 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011643 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 + ": nesting=" + r.executeNesting
11645 + ", inStopping=" + inStopping);
11646 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011647 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011648 + " with incorrect token: given " + token
11649 + ", expected " + r);
11650 return;
11651 }
11652
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011653 if (type == 1) {
11654 // This is a call from a service start... take care of
11655 // book-keeping.
11656 r.callStart = true;
11657 switch (res) {
11658 case Service.START_STICKY_COMPATIBILITY:
11659 case Service.START_STICKY: {
11660 // We are done with the associated start arguments.
11661 r.findDeliveredStart(startId, true);
11662 // Don't stop if killed.
11663 r.stopIfKilled = false;
11664 break;
11665 }
11666 case Service.START_NOT_STICKY: {
11667 // We are done with the associated start arguments.
11668 r.findDeliveredStart(startId, true);
11669 if (r.lastStartId == startId) {
11670 // There is no more work, and this service
11671 // doesn't want to hang around if killed.
11672 r.stopIfKilled = true;
11673 }
11674 break;
11675 }
11676 case Service.START_REDELIVER_INTENT: {
11677 // We'll keep this item until they explicitly
11678 // call stop for it, but keep track of the fact
11679 // that it was delivered.
11680 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11681 if (si != null) {
11682 si.deliveryCount = 0;
11683 si.doneExecutingCount++;
11684 // Don't stop if killed.
11685 r.stopIfKilled = true;
11686 }
11687 break;
11688 }
11689 default:
11690 throw new IllegalArgumentException(
11691 "Unknown service start result: " + res);
11692 }
11693 if (res == Service.START_STICKY_COMPATIBILITY) {
11694 r.callStart = false;
11695 }
11696 }
11697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011698 final long origId = Binder.clearCallingIdentity();
11699 serviceDoneExecutingLocked(r, inStopping);
11700 Binder.restoreCallingIdentity(origId);
11701 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011702 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011703 + " with token " + token);
11704 }
11705 }
11706 }
11707
11708 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11709 r.executeNesting--;
11710 if (r.executeNesting <= 0 && r.app != null) {
11711 r.app.executingServices.remove(r);
11712 if (r.app.executingServices.size() == 0) {
11713 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11714 }
11715 if (inStopping) {
11716 mStoppingServices.remove(r);
11717 }
11718 updateOomAdjLocked(r.app);
11719 }
11720 }
11721
11722 void serviceTimeout(ProcessRecord proc) {
11723 synchronized(this) {
11724 if (proc.executingServices.size() == 0 || proc.thread == null) {
11725 return;
11726 }
11727 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11728 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11729 ServiceRecord timeout = null;
11730 long nextTime = 0;
11731 while (it.hasNext()) {
11732 ServiceRecord sr = it.next();
11733 if (sr.executingStart < maxTime) {
11734 timeout = sr;
11735 break;
11736 }
11737 if (sr.executingStart > nextTime) {
11738 nextTime = sr.executingStart;
11739 }
11740 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011741 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011742 Slog.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011743 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011744 } else {
11745 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11746 msg.obj = proc;
11747 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11748 }
11749 }
11750 }
11751
11752 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011753 // BACKUP AND RESTORE
11754 // =========================================================
11755
11756 // Cause the target app to be launched if necessary and its backup agent
11757 // instantiated. The backup agent will invoke backupAgentCreated() on the
11758 // activity manager to announce its creation.
11759 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011760 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011761 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11762
11763 synchronized(this) {
11764 // !!! TODO: currently no check here that we're already bound
11765 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11766 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11767 synchronized (stats) {
11768 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11769 }
11770
11771 BackupRecord r = new BackupRecord(ss, app, backupMode);
11772 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11773 // startProcessLocked() returns existing proc's record if it's already running
11774 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011775 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011776 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011777 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011778 return false;
11779 }
11780
11781 r.app = proc;
11782 mBackupTarget = r;
11783 mBackupAppName = app.packageName;
11784
Christopher Tate6fa95972009-06-05 18:43:55 -070011785 // Try not to kill the process during backup
11786 updateOomAdjLocked(proc);
11787
Christopher Tate181fafa2009-05-14 11:12:14 -070011788 // If the process is already attached, schedule the creation of the backup agent now.
11789 // If it is not yet live, this will be done when it attaches to the framework.
11790 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011791 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011792 try {
11793 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11794 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011795 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011796 }
11797 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011798 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011799 }
11800 // Invariants: at this point, the target app process exists and the application
11801 // is either already running or in the process of coming up. mBackupTarget and
11802 // mBackupAppName describe the app, so that when it binds back to the AM we
11803 // know that it's scheduled for a backup-agent operation.
11804 }
11805
11806 return true;
11807 }
11808
11809 // A backup agent has just come up
11810 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011811 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011812 + " = " + agent);
11813
11814 synchronized(this) {
11815 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011816 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011817 return;
11818 }
11819
Christopher Tate043dadc2009-06-02 16:11:00 -070011820 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011821 try {
11822 IBackupManager bm = IBackupManager.Stub.asInterface(
11823 ServiceManager.getService(Context.BACKUP_SERVICE));
11824 bm.agentConnected(agentPackageName, agent);
11825 } catch (RemoteException e) {
11826 // can't happen; the backup manager service is local
11827 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011828 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070011829 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011830 } finally {
11831 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011832 }
11833 }
11834 }
11835
11836 // done with this agent
11837 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011838 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011839 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011840 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011841 return;
11842 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011843
11844 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011845 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011846 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011847 return;
11848 }
11849
Christopher Tate181fafa2009-05-14 11:12:14 -070011850 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011851 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011852 return;
11853 }
11854
Christopher Tate6fa95972009-06-05 18:43:55 -070011855 ProcessRecord proc = mBackupTarget.app;
11856 mBackupTarget = null;
11857 mBackupAppName = null;
11858
11859 // Not backing this app up any more; reset its OOM adjustment
11860 updateOomAdjLocked(proc);
11861
Christopher Tatec7b31e32009-06-10 15:49:30 -070011862 // If the app crashed during backup, 'thread' will be null here
11863 if (proc.thread != null) {
11864 try {
11865 proc.thread.scheduleDestroyBackupAgent(appInfo);
11866 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011867 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070011868 e.printStackTrace();
11869 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011870 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011871 }
11872 }
11873 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011874 // BROADCASTS
11875 // =========================================================
11876
11877 private final List getStickies(String action, IntentFilter filter,
11878 List cur) {
11879 final ContentResolver resolver = mContext.getContentResolver();
11880 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11881 if (list == null) {
11882 return cur;
11883 }
11884 int N = list.size();
11885 for (int i=0; i<N; i++) {
11886 Intent intent = list.get(i);
11887 if (filter.match(resolver, intent, true, TAG) >= 0) {
11888 if (cur == null) {
11889 cur = new ArrayList<Intent>();
11890 }
11891 cur.add(intent);
11892 }
11893 }
11894 return cur;
11895 }
11896
11897 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011898 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011899 + mBroadcastsScheduled);
11900
11901 if (mBroadcastsScheduled) {
11902 return;
11903 }
11904 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11905 mBroadcastsScheduled = true;
11906 }
11907
11908 public Intent registerReceiver(IApplicationThread caller,
11909 IIntentReceiver receiver, IntentFilter filter, String permission) {
11910 synchronized(this) {
11911 ProcessRecord callerApp = null;
11912 if (caller != null) {
11913 callerApp = getRecordForAppLocked(caller);
11914 if (callerApp == null) {
11915 throw new SecurityException(
11916 "Unable to find app for caller " + caller
11917 + " (pid=" + Binder.getCallingPid()
11918 + ") when registering receiver " + receiver);
11919 }
11920 }
11921
11922 List allSticky = null;
11923
11924 // Look for any matching sticky broadcasts...
11925 Iterator actions = filter.actionsIterator();
11926 if (actions != null) {
11927 while (actions.hasNext()) {
11928 String action = (String)actions.next();
11929 allSticky = getStickies(action, filter, allSticky);
11930 }
11931 } else {
11932 allSticky = getStickies(null, filter, allSticky);
11933 }
11934
11935 // The first sticky in the list is returned directly back to
11936 // the client.
11937 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11938
Joe Onorato8a9b2202010-02-26 18:56:32 -080011939 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011940 + ": " + sticky);
11941
11942 if (receiver == null) {
11943 return sticky;
11944 }
11945
11946 ReceiverList rl
11947 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11948 if (rl == null) {
11949 rl = new ReceiverList(this, callerApp,
11950 Binder.getCallingPid(),
11951 Binder.getCallingUid(), receiver);
11952 if (rl.app != null) {
11953 rl.app.receivers.add(rl);
11954 } else {
11955 try {
11956 receiver.asBinder().linkToDeath(rl, 0);
11957 } catch (RemoteException e) {
11958 return sticky;
11959 }
11960 rl.linkedToDeath = true;
11961 }
11962 mRegisteredReceivers.put(receiver.asBinder(), rl);
11963 }
11964 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
11965 rl.add(bf);
11966 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011967 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011968 }
11969 mReceiverResolver.addFilter(bf);
11970
11971 // Enqueue broadcasts for all existing stickies that match
11972 // this filter.
11973 if (allSticky != null) {
11974 ArrayList receivers = new ArrayList();
11975 receivers.add(bf);
11976
11977 int N = allSticky.size();
11978 for (int i=0; i<N; i++) {
11979 Intent intent = (Intent)allSticky.get(i);
11980 BroadcastRecord r = new BroadcastRecord(intent, null,
11981 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011982 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011983 if (mParallelBroadcasts.size() == 0) {
11984 scheduleBroadcastsLocked();
11985 }
11986 mParallelBroadcasts.add(r);
11987 }
11988 }
11989
11990 return sticky;
11991 }
11992 }
11993
11994 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011995 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011996
11997 boolean doNext = false;
11998
11999 synchronized(this) {
12000 ReceiverList rl
12001 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12002 if (rl != null) {
12003 if (rl.curBroadcast != null) {
12004 BroadcastRecord r = rl.curBroadcast;
12005 doNext = finishReceiverLocked(
12006 receiver.asBinder(), r.resultCode, r.resultData,
12007 r.resultExtras, r.resultAbort, true);
12008 }
12009
12010 if (rl.app != null) {
12011 rl.app.receivers.remove(rl);
12012 }
12013 removeReceiverLocked(rl);
12014 if (rl.linkedToDeath) {
12015 rl.linkedToDeath = false;
12016 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12017 }
12018 }
12019 }
12020
12021 if (!doNext) {
12022 return;
12023 }
12024
12025 final long origId = Binder.clearCallingIdentity();
12026 processNextBroadcast(false);
12027 trimApplications();
12028 Binder.restoreCallingIdentity(origId);
12029 }
12030
12031 void removeReceiverLocked(ReceiverList rl) {
12032 mRegisteredReceivers.remove(rl.receiver.asBinder());
12033 int N = rl.size();
12034 for (int i=0; i<N; i++) {
12035 mReceiverResolver.removeFilter(rl.get(i));
12036 }
12037 }
12038
12039 private final int broadcastIntentLocked(ProcessRecord callerApp,
12040 String callerPackage, Intent intent, String resolvedType,
12041 IIntentReceiver resultTo, int resultCode, String resultData,
12042 Bundle map, String requiredPermission,
12043 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12044 intent = new Intent(intent);
12045
Joe Onorato8a9b2202010-02-26 18:56:32 -080012046 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012047 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12048 + " ordered=" + ordered);
12049 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012050 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012051 }
12052
12053 // Handle special intents: if this broadcast is from the package
12054 // manager about a package being removed, we need to remove all of
12055 // its activities from the history stack.
12056 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12057 intent.getAction());
12058 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12059 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012060 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012061 || uidRemoved) {
12062 if (checkComponentPermission(
12063 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12064 callingPid, callingUid, -1)
12065 == PackageManager.PERMISSION_GRANTED) {
12066 if (uidRemoved) {
12067 final Bundle intentExtras = intent.getExtras();
12068 final int uid = intentExtras != null
12069 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12070 if (uid >= 0) {
12071 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12072 synchronized (bs) {
12073 bs.removeUidStatsLocked(uid);
12074 }
12075 }
12076 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012077 // If resources are unvailble just force stop all
12078 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012079 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012080 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12081 if (list != null && (list.length > 0)) {
12082 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012083 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012084 }
12085 }
12086 } else {
12087 Uri data = intent.getData();
12088 String ssp;
12089 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12090 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12091 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012092 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012093 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 }
12095 }
12096 }
12097 } else {
12098 String msg = "Permission Denial: " + intent.getAction()
12099 + " broadcast from " + callerPackage + " (pid=" + callingPid
12100 + ", uid=" + callingUid + ")"
12101 + " requires "
12102 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012103 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012104 throw new SecurityException(msg);
12105 }
12106 }
12107
12108 /*
12109 * If this is the time zone changed action, queue up a message that will reset the timezone
12110 * of all currently running processes. This message will get queued up before the broadcast
12111 * happens.
12112 */
12113 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12114 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12115 }
12116
Dianne Hackborn854060af2009-07-09 18:14:31 -070012117 /*
12118 * Prevent non-system code (defined here to be non-persistent
12119 * processes) from sending protected broadcasts.
12120 */
12121 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12122 || callingUid == Process.SHELL_UID || callingUid == 0) {
12123 // Always okay.
12124 } else if (callerApp == null || !callerApp.persistent) {
12125 try {
12126 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12127 intent.getAction())) {
12128 String msg = "Permission Denial: not allowed to send broadcast "
12129 + intent.getAction() + " from pid="
12130 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012131 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012132 throw new SecurityException(msg);
12133 }
12134 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012135 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012136 return BROADCAST_SUCCESS;
12137 }
12138 }
12139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012140 // Add to the sticky list if requested.
12141 if (sticky) {
12142 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12143 callingPid, callingUid)
12144 != PackageManager.PERMISSION_GRANTED) {
12145 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12146 + callingPid + ", uid=" + callingUid
12147 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012148 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012149 throw new SecurityException(msg);
12150 }
12151 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012152 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012153 + " and enforce permission " + requiredPermission);
12154 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12155 }
12156 if (intent.getComponent() != null) {
12157 throw new SecurityException(
12158 "Sticky broadcasts can't target a specific component");
12159 }
12160 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12161 if (list == null) {
12162 list = new ArrayList<Intent>();
12163 mStickyBroadcasts.put(intent.getAction(), list);
12164 }
12165 int N = list.size();
12166 int i;
12167 for (i=0; i<N; i++) {
12168 if (intent.filterEquals(list.get(i))) {
12169 // This sticky already exists, replace it.
12170 list.set(i, new Intent(intent));
12171 break;
12172 }
12173 }
12174 if (i >= N) {
12175 list.add(new Intent(intent));
12176 }
12177 }
12178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012179 // Figure out who all will receive this broadcast.
12180 List receivers = null;
12181 List<BroadcastFilter> registeredReceivers = null;
12182 try {
12183 if (intent.getComponent() != null) {
12184 // Broadcast is going to one specific receiver class...
12185 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012186 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012187 if (ai != null) {
12188 receivers = new ArrayList();
12189 ResolveInfo ri = new ResolveInfo();
12190 ri.activityInfo = ai;
12191 receivers.add(ri);
12192 }
12193 } else {
12194 // Need to resolve the intent to interested receivers...
12195 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12196 == 0) {
12197 receivers =
12198 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012199 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012200 }
Mihai Preda074edef2009-05-18 17:13:31 +020012201 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012202 }
12203 } catch (RemoteException ex) {
12204 // pm is in same process, this will never happen.
12205 }
12206
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012207 final boolean replacePending =
12208 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12209
Joe Onorato8a9b2202010-02-26 18:56:32 -080012210 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012211 + " replacePending=" + replacePending);
12212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012213 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12214 if (!ordered && NR > 0) {
12215 // If we are not serializing this broadcast, then send the
12216 // registered receivers separately so they don't wait for the
12217 // components to be launched.
12218 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12219 callerPackage, callingPid, callingUid, requiredPermission,
12220 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012221 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012222 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012223 TAG, "Enqueueing parallel broadcast " + r
12224 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012225 boolean replaced = false;
12226 if (replacePending) {
12227 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12228 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012229 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012230 "***** DROPPING PARALLEL: " + intent);
12231 mParallelBroadcasts.set(i, r);
12232 replaced = true;
12233 break;
12234 }
12235 }
12236 }
12237 if (!replaced) {
12238 mParallelBroadcasts.add(r);
12239 scheduleBroadcastsLocked();
12240 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012241 registeredReceivers = null;
12242 NR = 0;
12243 }
12244
12245 // Merge into one list.
12246 int ir = 0;
12247 if (receivers != null) {
12248 // A special case for PACKAGE_ADDED: do not allow the package
12249 // being added to see this broadcast. This prevents them from
12250 // using this as a back door to get run as soon as they are
12251 // installed. Maybe in the future we want to have a special install
12252 // broadcast or such for apps, but we'd like to deliberately make
12253 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012254 String skipPackages[] = null;
12255 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12256 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12257 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12258 Uri data = intent.getData();
12259 if (data != null) {
12260 String pkgName = data.getSchemeSpecificPart();
12261 if (pkgName != null) {
12262 skipPackages = new String[] { pkgName };
12263 }
12264 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012265 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012266 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012267 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012268 if (skipPackages != null && (skipPackages.length > 0)) {
12269 for (String skipPackage : skipPackages) {
12270 if (skipPackage != null) {
12271 int NT = receivers.size();
12272 for (int it=0; it<NT; it++) {
12273 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12274 if (curt.activityInfo.packageName.equals(skipPackage)) {
12275 receivers.remove(it);
12276 it--;
12277 NT--;
12278 }
12279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 }
12281 }
12282 }
12283
12284 int NT = receivers != null ? receivers.size() : 0;
12285 int it = 0;
12286 ResolveInfo curt = null;
12287 BroadcastFilter curr = null;
12288 while (it < NT && ir < NR) {
12289 if (curt == null) {
12290 curt = (ResolveInfo)receivers.get(it);
12291 }
12292 if (curr == null) {
12293 curr = registeredReceivers.get(ir);
12294 }
12295 if (curr.getPriority() >= curt.priority) {
12296 // Insert this broadcast record into the final list.
12297 receivers.add(it, curr);
12298 ir++;
12299 curr = null;
12300 it++;
12301 NT++;
12302 } else {
12303 // Skip to the next ResolveInfo in the final list.
12304 it++;
12305 curt = null;
12306 }
12307 }
12308 }
12309 while (ir < NR) {
12310 if (receivers == null) {
12311 receivers = new ArrayList();
12312 }
12313 receivers.add(registeredReceivers.get(ir));
12314 ir++;
12315 }
12316
12317 if ((receivers != null && receivers.size() > 0)
12318 || resultTo != null) {
12319 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12320 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012321 receivers, resultTo, resultCode, resultData, map, ordered,
12322 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012323 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012324 TAG, "Enqueueing ordered broadcast " + r
12325 + ": prev had " + mOrderedBroadcasts.size());
12326 if (DEBUG_BROADCAST) {
12327 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012328 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012329 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012330 boolean replaced = false;
12331 if (replacePending) {
12332 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12333 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012334 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012335 "***** DROPPING ORDERED: " + intent);
12336 mOrderedBroadcasts.set(i, r);
12337 replaced = true;
12338 break;
12339 }
12340 }
12341 }
12342 if (!replaced) {
12343 mOrderedBroadcasts.add(r);
12344 scheduleBroadcastsLocked();
12345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012346 }
12347
12348 return BROADCAST_SUCCESS;
12349 }
12350
12351 public final int broadcastIntent(IApplicationThread caller,
12352 Intent intent, String resolvedType, IIntentReceiver resultTo,
12353 int resultCode, String resultData, Bundle map,
12354 String requiredPermission, boolean serialized, boolean sticky) {
12355 // Refuse possible leaked file descriptors
12356 if (intent != null && intent.hasFileDescriptors() == true) {
12357 throw new IllegalArgumentException("File descriptors passed in Intent");
12358 }
12359
12360 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012361 int flags = intent.getFlags();
12362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012363 if (!mSystemReady) {
12364 // if the caller really truly claims to know what they're doing, go
12365 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012366 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12367 intent = new Intent(intent);
12368 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12369 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012370 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012371 + " before boot completion");
12372 throw new IllegalStateException("Cannot broadcast before boot completed");
12373 }
12374 }
12375
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012376 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12377 throw new IllegalArgumentException(
12378 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12379 }
12380
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012381 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12382 final int callingPid = Binder.getCallingPid();
12383 final int callingUid = Binder.getCallingUid();
12384 final long origId = Binder.clearCallingIdentity();
12385 int res = broadcastIntentLocked(callerApp,
12386 callerApp != null ? callerApp.info.packageName : null,
12387 intent, resolvedType, resultTo,
12388 resultCode, resultData, map, requiredPermission, serialized,
12389 sticky, callingPid, callingUid);
12390 Binder.restoreCallingIdentity(origId);
12391 return res;
12392 }
12393 }
12394
12395 int broadcastIntentInPackage(String packageName, int uid,
12396 Intent intent, String resolvedType, IIntentReceiver resultTo,
12397 int resultCode, String resultData, Bundle map,
12398 String requiredPermission, boolean serialized, boolean sticky) {
12399 synchronized(this) {
12400 final long origId = Binder.clearCallingIdentity();
12401 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12402 resultTo, resultCode, resultData, map, requiredPermission,
12403 serialized, sticky, -1, uid);
12404 Binder.restoreCallingIdentity(origId);
12405 return res;
12406 }
12407 }
12408
12409 public final void unbroadcastIntent(IApplicationThread caller,
12410 Intent intent) {
12411 // Refuse possible leaked file descriptors
12412 if (intent != null && intent.hasFileDescriptors() == true) {
12413 throw new IllegalArgumentException("File descriptors passed in Intent");
12414 }
12415
12416 synchronized(this) {
12417 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12418 != PackageManager.PERMISSION_GRANTED) {
12419 String msg = "Permission Denial: unbroadcastIntent() from pid="
12420 + Binder.getCallingPid()
12421 + ", uid=" + Binder.getCallingUid()
12422 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012423 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012424 throw new SecurityException(msg);
12425 }
12426 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12427 if (list != null) {
12428 int N = list.size();
12429 int i;
12430 for (i=0; i<N; i++) {
12431 if (intent.filterEquals(list.get(i))) {
12432 list.remove(i);
12433 break;
12434 }
12435 }
12436 }
12437 }
12438 }
12439
12440 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12441 String resultData, Bundle resultExtras, boolean resultAbort,
12442 boolean explicit) {
12443 if (mOrderedBroadcasts.size() == 0) {
12444 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012445 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012446 }
12447 return false;
12448 }
12449 BroadcastRecord r = mOrderedBroadcasts.get(0);
12450 if (r.receiver == null) {
12451 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012452 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012453 }
12454 return false;
12455 }
12456 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012457 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012458 return false;
12459 }
12460 int state = r.state;
12461 r.state = r.IDLE;
12462 if (state == r.IDLE) {
12463 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012464 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012465 }
12466 }
12467 r.receiver = null;
12468 r.intent.setComponent(null);
12469 if (r.curApp != null) {
12470 r.curApp.curReceiver = null;
12471 }
12472 if (r.curFilter != null) {
12473 r.curFilter.receiverList.curBroadcast = null;
12474 }
12475 r.curFilter = null;
12476 r.curApp = null;
12477 r.curComponent = null;
12478 r.curReceiver = null;
12479 mPendingBroadcast = null;
12480
12481 r.resultCode = resultCode;
12482 r.resultData = resultData;
12483 r.resultExtras = resultExtras;
12484 r.resultAbort = resultAbort;
12485
12486 // We will process the next receiver right now if this is finishing
12487 // an app receiver (which is always asynchronous) or after we have
12488 // come back from calling a receiver.
12489 return state == BroadcastRecord.APP_RECEIVE
12490 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12491 }
12492
12493 public void finishReceiver(IBinder who, int resultCode, String resultData,
12494 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012495 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012496
12497 // Refuse possible leaked file descriptors
12498 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12499 throw new IllegalArgumentException("File descriptors passed in Bundle");
12500 }
12501
12502 boolean doNext;
12503
12504 final long origId = Binder.clearCallingIdentity();
12505
12506 synchronized(this) {
12507 doNext = finishReceiverLocked(
12508 who, resultCode, resultData, resultExtras, resultAbort, true);
12509 }
12510
12511 if (doNext) {
12512 processNextBroadcast(false);
12513 }
12514 trimApplications();
12515
12516 Binder.restoreCallingIdentity(origId);
12517 }
12518
12519 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12520 if (r.nextReceiver > 0) {
12521 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12522 if (curReceiver instanceof BroadcastFilter) {
12523 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012524 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012525 System.identityHashCode(r),
12526 r.intent.getAction(),
12527 r.nextReceiver - 1,
12528 System.identityHashCode(bf));
12529 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012530 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012531 System.identityHashCode(r),
12532 r.intent.getAction(),
12533 r.nextReceiver - 1,
12534 ((ResolveInfo)curReceiver).toString());
12535 }
12536 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012537 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012538 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012539 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012540 System.identityHashCode(r),
12541 r.intent.getAction(),
12542 r.nextReceiver,
12543 "NONE");
12544 }
12545 }
12546
12547 private final void broadcastTimeout() {
12548 synchronized (this) {
12549 if (mOrderedBroadcasts.size() == 0) {
12550 return;
12551 }
12552 long now = SystemClock.uptimeMillis();
12553 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012554 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012555 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012556 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012557 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012558 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012559 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012560 return;
12561 }
12562
Joe Onorato8a9b2202010-02-26 18:56:32 -080012563 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012564 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012565 r.anrCount++;
12566
12567 // Current receiver has passed its expiration date.
12568 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012569 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012570 return;
12571 }
12572
12573 ProcessRecord app = null;
12574
12575 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012576 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012577 logBroadcastReceiverDiscard(r);
12578 if (curReceiver instanceof BroadcastFilter) {
12579 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12580 if (bf.receiverList.pid != 0
12581 && bf.receiverList.pid != MY_PID) {
12582 synchronized (this.mPidsSelfLocked) {
12583 app = this.mPidsSelfLocked.get(
12584 bf.receiverList.pid);
12585 }
12586 }
12587 } else {
12588 app = r.curApp;
12589 }
12590
12591 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012592 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012593 }
12594
12595 if (mPendingBroadcast == r) {
12596 mPendingBroadcast = null;
12597 }
12598
12599 // Move on to the next receiver.
12600 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12601 r.resultExtras, r.resultAbort, true);
12602 scheduleBroadcastsLocked();
12603 }
12604 }
12605
12606 private final void processCurBroadcastLocked(BroadcastRecord r,
12607 ProcessRecord app) throws RemoteException {
12608 if (app.thread == null) {
12609 throw new RemoteException();
12610 }
12611 r.receiver = app.thread.asBinder();
12612 r.curApp = app;
12613 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012614 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012615
12616 // Tell the application to launch this receiver.
12617 r.intent.setComponent(r.curComponent);
12618
12619 boolean started = false;
12620 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012621 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012622 "Delivering to component " + r.curComponent
12623 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012624 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012625 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12626 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12627 started = true;
12628 } finally {
12629 if (!started) {
12630 r.receiver = null;
12631 r.curApp = null;
12632 app.curReceiver = null;
12633 }
12634 }
12635
12636 }
12637
12638 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012639 Intent intent, int resultCode, String data, Bundle extras,
12640 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012641 if (app != null && app.thread != null) {
12642 // If we have an app thread, do the call through that so it is
12643 // correctly ordered with other one-way calls.
12644 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012645 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012646 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012647 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012648 }
12649 }
12650
12651 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12652 BroadcastFilter filter, boolean ordered) {
12653 boolean skip = false;
12654 if (filter.requiredPermission != null) {
12655 int perm = checkComponentPermission(filter.requiredPermission,
12656 r.callingPid, r.callingUid, -1);
12657 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012658 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012659 + r.intent.toString()
12660 + " from " + r.callerPackage + " (pid="
12661 + r.callingPid + ", uid=" + r.callingUid + ")"
12662 + " requires " + filter.requiredPermission
12663 + " due to registered receiver " + filter);
12664 skip = true;
12665 }
12666 }
12667 if (r.requiredPermission != null) {
12668 int perm = checkComponentPermission(r.requiredPermission,
12669 filter.receiverList.pid, filter.receiverList.uid, -1);
12670 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012671 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012672 + r.intent.toString()
12673 + " to " + filter.receiverList.app
12674 + " (pid=" + filter.receiverList.pid
12675 + ", uid=" + filter.receiverList.uid + ")"
12676 + " requires " + r.requiredPermission
12677 + " due to sender " + r.callerPackage
12678 + " (uid " + r.callingUid + ")");
12679 skip = true;
12680 }
12681 }
12682
12683 if (!skip) {
12684 // If this is not being sent as an ordered broadcast, then we
12685 // don't want to touch the fields that keep track of the current
12686 // state of ordered broadcasts.
12687 if (ordered) {
12688 r.receiver = filter.receiverList.receiver.asBinder();
12689 r.curFilter = filter;
12690 filter.receiverList.curBroadcast = r;
12691 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012692 if (filter.receiverList.app != null) {
12693 // Bump hosting application to no longer be in background
12694 // scheduling class. Note that we can't do that if there
12695 // isn't an app... but we can only be in that case for
12696 // things that directly call the IActivityManager API, which
12697 // are already core system stuff so don't matter for this.
12698 r.curApp = filter.receiverList.app;
12699 filter.receiverList.app.curReceiver = r;
12700 updateOomAdjLocked();
12701 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012702 }
12703 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012704 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012705 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012706 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012707 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012708 }
12709 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12710 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012711 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012712 if (ordered) {
12713 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12714 }
12715 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012716 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012717 if (ordered) {
12718 r.receiver = null;
12719 r.curFilter = null;
12720 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012721 if (filter.receiverList.app != null) {
12722 filter.receiverList.app.curReceiver = null;
12723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012724 }
12725 }
12726 }
12727 }
12728
Dianne Hackborn12527f92009-11-11 17:39:50 -080012729 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12730 if (r.callingUid < 0) {
12731 // This was from a registerReceiver() call; ignore it.
12732 return;
12733 }
12734 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12735 MAX_BROADCAST_HISTORY-1);
12736 r.finishTime = SystemClock.uptimeMillis();
12737 mBroadcastHistory[0] = r;
12738 }
12739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012740 private final void processNextBroadcast(boolean fromMsg) {
12741 synchronized(this) {
12742 BroadcastRecord r;
12743
Joe Onorato8a9b2202010-02-26 18:56:32 -080012744 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012745 + mParallelBroadcasts.size() + " broadcasts, "
12746 + mOrderedBroadcasts.size() + " serialized broadcasts");
12747
12748 updateCpuStats();
12749
12750 if (fromMsg) {
12751 mBroadcastsScheduled = false;
12752 }
12753
12754 // First, deliver any non-serialized broadcasts right away.
12755 while (mParallelBroadcasts.size() > 0) {
12756 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012757 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012758 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012759 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012760 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012761 for (int i=0; i<N; i++) {
12762 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012763 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012764 "Delivering non-serialized to registered "
12765 + target + ": " + r);
12766 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12767 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012768 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012769 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012770 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012771 }
12772
12773 // Now take care of the next serialized one...
12774
12775 // If we are waiting for a process to come up to handle the next
12776 // broadcast, then do nothing at this point. Just in case, we
12777 // check that the process we're waiting for still exists.
12778 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012779 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012780 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012781 + mPendingBroadcast.curApp);
12782 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012783
12784 boolean isDead;
12785 synchronized (mPidsSelfLocked) {
12786 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12787 }
12788 if (!isDead) {
12789 // It's still alive, so keep waiting
12790 return;
12791 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012792 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012793 + " died before responding to broadcast");
12794 mPendingBroadcast = null;
12795 }
12796 }
12797
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012798 boolean looped = false;
12799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012800 do {
12801 if (mOrderedBroadcasts.size() == 0) {
12802 // No more broadcasts pending, so all done!
12803 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012804 if (looped) {
12805 // If we had finished the last ordered broadcast, then
12806 // make sure all processes have correct oom and sched
12807 // adjustments.
12808 updateOomAdjLocked();
12809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012810 return;
12811 }
12812 r = mOrderedBroadcasts.get(0);
12813 boolean forceReceive = false;
12814
12815 // Ensure that even if something goes awry with the timeout
12816 // detection, we catch "hung" broadcasts here, discard them,
12817 // and continue to make progress.
12818 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12819 long now = SystemClock.uptimeMillis();
12820 if (r.dispatchTime > 0) {
12821 if ((numReceivers > 0) &&
12822 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012823 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012824 + " now=" + now
12825 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012826 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012827 + " intent=" + r.intent
12828 + " numReceivers=" + numReceivers
12829 + " nextReceiver=" + r.nextReceiver
12830 + " state=" + r.state);
12831 broadcastTimeout(); // forcibly finish this broadcast
12832 forceReceive = true;
12833 r.state = BroadcastRecord.IDLE;
12834 }
12835 }
12836
12837 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012838 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012839 "processNextBroadcast() called when not idle (state="
12840 + r.state + ")");
12841 return;
12842 }
12843
12844 if (r.receivers == null || r.nextReceiver >= numReceivers
12845 || r.resultAbort || forceReceive) {
12846 // No more receivers for this broadcast! Send the final
12847 // result if requested...
12848 if (r.resultTo != null) {
12849 try {
12850 if (DEBUG_BROADCAST) {
12851 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012852 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012853 + " seq=" + seq + " app=" + r.callerApp);
12854 }
12855 performReceive(r.callerApp, r.resultTo,
12856 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012857 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012858 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012859 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012860 }
12861 }
12862
Joe Onorato8a9b2202010-02-26 18:56:32 -080012863 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012864 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12865
Joe Onorato8a9b2202010-02-26 18:56:32 -080012866 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012867 + r);
12868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012869 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012870 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012871 mOrderedBroadcasts.remove(0);
12872 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012873 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012874 continue;
12875 }
12876 } while (r == null);
12877
12878 // Get the next receiver...
12879 int recIdx = r.nextReceiver++;
12880
12881 // Keep track of when this receiver started, and make sure there
12882 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012883 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012884 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012885 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012886
Joe Onorato8a9b2202010-02-26 18:56:32 -080012887 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012888 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012889 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012890 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012891 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012892 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012893 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012894 }
12895
12896 Object nextReceiver = r.receivers.get(recIdx);
12897 if (nextReceiver instanceof BroadcastFilter) {
12898 // Simple case: this is a registered receiver who gets
12899 // a direct call.
12900 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012901 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012902 "Delivering serialized to registered "
12903 + filter + ": " + r);
12904 deliverToRegisteredReceiver(r, filter, r.ordered);
12905 if (r.receiver == null || !r.ordered) {
12906 // The receiver has already finished, so schedule to
12907 // process the next one.
12908 r.state = BroadcastRecord.IDLE;
12909 scheduleBroadcastsLocked();
12910 }
12911 return;
12912 }
12913
12914 // Hard case: need to instantiate the receiver, possibly
12915 // starting its application process to host it.
12916
12917 ResolveInfo info =
12918 (ResolveInfo)nextReceiver;
12919
12920 boolean skip = false;
12921 int perm = checkComponentPermission(info.activityInfo.permission,
12922 r.callingPid, r.callingUid,
12923 info.activityInfo.exported
12924 ? -1 : info.activityInfo.applicationInfo.uid);
12925 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012926 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012927 + r.intent.toString()
12928 + " from " + r.callerPackage + " (pid=" + r.callingPid
12929 + ", uid=" + r.callingUid + ")"
12930 + " requires " + info.activityInfo.permission
12931 + " due to receiver " + info.activityInfo.packageName
12932 + "/" + info.activityInfo.name);
12933 skip = true;
12934 }
12935 if (r.callingUid != Process.SYSTEM_UID &&
12936 r.requiredPermission != null) {
12937 try {
12938 perm = ActivityThread.getPackageManager().
12939 checkPermission(r.requiredPermission,
12940 info.activityInfo.applicationInfo.packageName);
12941 } catch (RemoteException e) {
12942 perm = PackageManager.PERMISSION_DENIED;
12943 }
12944 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012945 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012946 + r.intent + " to "
12947 + info.activityInfo.applicationInfo.packageName
12948 + " requires " + r.requiredPermission
12949 + " due to sender " + r.callerPackage
12950 + " (uid " + r.callingUid + ")");
12951 skip = true;
12952 }
12953 }
12954 if (r.curApp != null && r.curApp.crashing) {
12955 // If the target process is crashing, just skip it.
12956 skip = true;
12957 }
12958
12959 if (skip) {
12960 r.receiver = null;
12961 r.curFilter = null;
12962 r.state = BroadcastRecord.IDLE;
12963 scheduleBroadcastsLocked();
12964 return;
12965 }
12966
12967 r.state = BroadcastRecord.APP_RECEIVE;
12968 String targetProcess = info.activityInfo.processName;
12969 r.curComponent = new ComponentName(
12970 info.activityInfo.applicationInfo.packageName,
12971 info.activityInfo.name);
12972 r.curReceiver = info.activityInfo;
12973
12974 // Is this receiver's application already running?
12975 ProcessRecord app = getProcessRecordLocked(targetProcess,
12976 info.activityInfo.applicationInfo.uid);
12977 if (app != null && app.thread != null) {
12978 try {
12979 processCurBroadcastLocked(r, app);
12980 return;
12981 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012982 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012983 + r.curComponent, e);
12984 }
12985
12986 // If a dead object exception was thrown -- fall through to
12987 // restart the application.
12988 }
12989
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012990 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012991 if ((r.curApp=startProcessLocked(targetProcess,
12992 info.activityInfo.applicationInfo, true,
12993 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012994 "broadcast", r.curComponent,
12995 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12996 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012997 // Ah, this recipient is unavailable. Finish it if necessary,
12998 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012999 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013000 + info.activityInfo.applicationInfo.packageName + "/"
13001 + info.activityInfo.applicationInfo.uid + " for broadcast "
13002 + r.intent + ": process is bad");
13003 logBroadcastReceiverDiscard(r);
13004 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13005 r.resultExtras, r.resultAbort, true);
13006 scheduleBroadcastsLocked();
13007 r.state = BroadcastRecord.IDLE;
13008 return;
13009 }
13010
13011 mPendingBroadcast = r;
13012 }
13013 }
13014
13015 // =========================================================
13016 // INSTRUMENTATION
13017 // =========================================================
13018
13019 public boolean startInstrumentation(ComponentName className,
13020 String profileFile, int flags, Bundle arguments,
13021 IInstrumentationWatcher watcher) {
13022 // Refuse possible leaked file descriptors
13023 if (arguments != null && arguments.hasFileDescriptors()) {
13024 throw new IllegalArgumentException("File descriptors passed in Bundle");
13025 }
13026
13027 synchronized(this) {
13028 InstrumentationInfo ii = null;
13029 ApplicationInfo ai = null;
13030 try {
13031 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013032 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013033 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013034 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013035 } catch (PackageManager.NameNotFoundException e) {
13036 }
13037 if (ii == null) {
13038 reportStartInstrumentationFailure(watcher, className,
13039 "Unable to find instrumentation info for: " + className);
13040 return false;
13041 }
13042 if (ai == null) {
13043 reportStartInstrumentationFailure(watcher, className,
13044 "Unable to find instrumentation target package: " + ii.targetPackage);
13045 return false;
13046 }
13047
13048 int match = mContext.getPackageManager().checkSignatures(
13049 ii.targetPackage, ii.packageName);
13050 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13051 String msg = "Permission Denial: starting instrumentation "
13052 + className + " from pid="
13053 + Binder.getCallingPid()
13054 + ", uid=" + Binder.getCallingPid()
13055 + " not allowed because package " + ii.packageName
13056 + " does not have a signature matching the target "
13057 + ii.targetPackage;
13058 reportStartInstrumentationFailure(watcher, className, msg);
13059 throw new SecurityException(msg);
13060 }
13061
13062 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013063 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013064 ProcessRecord app = addAppLocked(ai);
13065 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013066 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013067 app.instrumentationProfileFile = profileFile;
13068 app.instrumentationArguments = arguments;
13069 app.instrumentationWatcher = watcher;
13070 app.instrumentationResultClass = className;
13071 Binder.restoreCallingIdentity(origId);
13072 }
13073
13074 return true;
13075 }
13076
13077 /**
13078 * Report errors that occur while attempting to start Instrumentation. Always writes the
13079 * error to the logs, but if somebody is watching, send the report there too. This enables
13080 * the "am" command to report errors with more information.
13081 *
13082 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13083 * @param cn The component name of the instrumentation.
13084 * @param report The error report.
13085 */
13086 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13087 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013088 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013089 try {
13090 if (watcher != null) {
13091 Bundle results = new Bundle();
13092 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13093 results.putString("Error", report);
13094 watcher.instrumentationStatus(cn, -1, results);
13095 }
13096 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013097 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013098 }
13099 }
13100
13101 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13102 if (app.instrumentationWatcher != null) {
13103 try {
13104 // NOTE: IInstrumentationWatcher *must* be oneway here
13105 app.instrumentationWatcher.instrumentationFinished(
13106 app.instrumentationClass,
13107 resultCode,
13108 results);
13109 } catch (RemoteException e) {
13110 }
13111 }
13112 app.instrumentationWatcher = null;
13113 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013114 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013115 app.instrumentationProfileFile = null;
13116 app.instrumentationArguments = null;
13117
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013118 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013119 }
13120
13121 public void finishInstrumentation(IApplicationThread target,
13122 int resultCode, Bundle results) {
13123 // Refuse possible leaked file descriptors
13124 if (results != null && results.hasFileDescriptors()) {
13125 throw new IllegalArgumentException("File descriptors passed in Intent");
13126 }
13127
13128 synchronized(this) {
13129 ProcessRecord app = getRecordForAppLocked(target);
13130 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013131 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013132 return;
13133 }
13134 final long origId = Binder.clearCallingIdentity();
13135 finishInstrumentationLocked(app, resultCode, results);
13136 Binder.restoreCallingIdentity(origId);
13137 }
13138 }
13139
13140 // =========================================================
13141 // CONFIGURATION
13142 // =========================================================
13143
13144 public ConfigurationInfo getDeviceConfigurationInfo() {
13145 ConfigurationInfo config = new ConfigurationInfo();
13146 synchronized (this) {
13147 config.reqTouchScreen = mConfiguration.touchscreen;
13148 config.reqKeyboardType = mConfiguration.keyboard;
13149 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013150 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13151 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013152 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13153 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013154 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13155 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013156 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13157 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013158 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013159 }
13160 return config;
13161 }
13162
13163 public Configuration getConfiguration() {
13164 Configuration ci;
13165 synchronized(this) {
13166 ci = new Configuration(mConfiguration);
13167 }
13168 return ci;
13169 }
13170
13171 public void updateConfiguration(Configuration values) {
13172 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13173 "updateConfiguration()");
13174
13175 synchronized(this) {
13176 if (values == null && mWindowManager != null) {
13177 // sentinel: fetch the current configuration from the window manager
13178 values = mWindowManager.computeNewConfiguration();
13179 }
13180
13181 final long origId = Binder.clearCallingIdentity();
13182 updateConfigurationLocked(values, null);
13183 Binder.restoreCallingIdentity(origId);
13184 }
13185 }
13186
13187 /**
13188 * Do either or both things: (1) change the current configuration, and (2)
13189 * make sure the given activity is running with the (now) current
13190 * configuration. Returns true if the activity has been left running, or
13191 * false if <var>starting</var> is being destroyed to match the new
13192 * configuration.
13193 */
13194 public boolean updateConfigurationLocked(Configuration values,
13195 HistoryRecord starting) {
13196 int changes = 0;
13197
13198 boolean kept = true;
13199
13200 if (values != null) {
13201 Configuration newConfig = new Configuration(mConfiguration);
13202 changes = newConfig.updateFrom(values);
13203 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013204 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013205 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013206 }
13207
Doug Zongker2bec3d42009-12-04 12:52:44 -080013208 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013209
13210 if (values.locale != null) {
13211 saveLocaleLocked(values.locale,
13212 !values.locale.equals(mConfiguration.locale),
13213 values.userSetLocale);
13214 }
13215
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013216 mConfigurationSeq++;
13217 if (mConfigurationSeq <= 0) {
13218 mConfigurationSeq = 1;
13219 }
13220 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013221 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013222 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013223
13224 AttributeCache ac = AttributeCache.instance();
13225 if (ac != null) {
13226 ac.updateConfiguration(mConfiguration);
13227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013228
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013229 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13230 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13231 msg.obj = new Configuration(mConfiguration);
13232 mHandler.sendMessage(msg);
13233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013234
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013235 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13236 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013237 try {
13238 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013239 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013240 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013241 app.thread.scheduleConfigurationChanged(mConfiguration);
13242 }
13243 } catch (Exception e) {
13244 }
13245 }
13246 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013247 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13248 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013249 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13250 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013251 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13252 broadcastIntentLocked(null, null,
13253 new Intent(Intent.ACTION_LOCALE_CHANGED),
13254 null, null, 0, null, null,
13255 null, false, false, MY_PID, Process.SYSTEM_UID);
13256 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013257 }
13258 }
13259
13260 if (changes != 0 && starting == null) {
13261 // If the configuration changed, and the caller is not already
13262 // in the process of starting an activity, then find the top
13263 // activity to check if its configuration needs to change.
13264 starting = topRunningActivityLocked(null);
13265 }
13266
13267 if (starting != null) {
13268 kept = ensureActivityConfigurationLocked(starting, changes);
13269 if (kept) {
13270 // If this didn't result in the starting activity being
13271 // destroyed, then we need to make sure at this point that all
13272 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013273 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013274 + ", ensuring others are correct.");
13275 ensureActivitiesVisibleLocked(starting, changes);
13276 }
13277 }
13278
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013279 if (values != null && mWindowManager != null) {
13280 mWindowManager.setNewConfiguration(mConfiguration);
13281 }
13282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013283 return kept;
13284 }
13285
13286 private final boolean relaunchActivityLocked(HistoryRecord r,
13287 int changes, boolean andResume) {
13288 List<ResultInfo> results = null;
13289 List<Intent> newIntents = null;
13290 if (andResume) {
13291 results = r.results;
13292 newIntents = r.newIntents;
13293 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013294 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013295 + " with results=" + results + " newIntents=" + newIntents
13296 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013297 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13298 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013299 r.task.taskId, r.shortComponentName);
13300
13301 r.startFreezingScreenLocked(r.app, 0);
13302
13303 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013304 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013305 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013306 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013307 // Note: don't need to call pauseIfSleepingLocked() here, because
13308 // the caller will only pass in 'andResume' if this activity is
13309 // currently resumed, which implies we aren't sleeping.
13310 } catch (RemoteException e) {
13311 return false;
13312 }
13313
13314 if (andResume) {
13315 r.results = null;
13316 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013317 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013318 }
13319
13320 return true;
13321 }
13322
13323 /**
13324 * Make sure the given activity matches the current configuration. Returns
13325 * false if the activity had to be destroyed. Returns true if the
13326 * configuration is the same, or the activity will remain running as-is
13327 * for whatever reason. Ensures the HistoryRecord is updated with the
13328 * correct configuration and all other bookkeeping is handled.
13329 */
13330 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13331 int globalChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013332 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013333 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013334
13335 // Short circuit: if the two configurations are the exact same
13336 // object (the common case), then there is nothing to do.
13337 Configuration newConfig = mConfiguration;
13338 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013339 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013340 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013341 return true;
13342 }
13343
13344 // We don't worry about activities that are finishing.
13345 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013346 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013347 "Configuration doesn't matter in finishing " + r);
13348 r.stopFreezingScreenLocked(false);
13349 return true;
13350 }
13351
13352 // Okay we now are going to make this activity have the new config.
13353 // But then we need to figure out how it needs to deal with that.
13354 Configuration oldConfig = r.configuration;
13355 r.configuration = newConfig;
13356
13357 // If the activity isn't currently running, just leave the new
13358 // configuration and it will pick that up next time it starts.
13359 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013360 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013361 "Configuration doesn't matter not running " + r);
13362 r.stopFreezingScreenLocked(false);
13363 return true;
13364 }
13365
13366 // If the activity isn't persistent, there is a chance we will
13367 // need to restart it.
13368 if (!r.persistent) {
13369
13370 // Figure out what has changed between the two configurations.
13371 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013372 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013373 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013374 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013375 + Integer.toHexString(r.info.configChanges)
13376 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013377 }
13378 if ((changes&(~r.info.configChanges)) != 0) {
13379 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13380 r.configChangeFlags |= changes;
13381 r.startFreezingScreenLocked(r.app, globalChanges);
13382 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013383 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013384 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013385 destroyActivityLocked(r, true);
13386 } else if (r.state == ActivityState.PAUSING) {
13387 // A little annoying: we are waiting for this activity to
13388 // finish pausing. Let's not do anything now, but just
13389 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013390 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013391 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392 r.configDestroy = true;
13393 return true;
13394 } else if (r.state == ActivityState.RESUMED) {
13395 // Try to optimize this case: the configuration is changing
13396 // and we need to restart the top, resumed activity.
13397 // Instead of doing the normal handshaking, just say
13398 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013399 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013400 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013401 relaunchActivityLocked(r, r.configChangeFlags, true);
13402 r.configChangeFlags = 0;
13403 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013404 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013405 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013406 relaunchActivityLocked(r, r.configChangeFlags, false);
13407 r.configChangeFlags = 0;
13408 }
13409
13410 // All done... tell the caller we weren't able to keep this
13411 // activity around.
13412 return false;
13413 }
13414 }
13415
13416 // Default case: the activity can handle this new configuration, so
13417 // hand it over. Note that we don't need to give it the new
13418 // configuration, since we always send configuration changes to all
13419 // process when they happen so it can just use whatever configuration
13420 // it last got.
13421 if (r.app != null && r.app.thread != null) {
13422 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013423 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013424 r.app.thread.scheduleActivityConfigurationChanged(r);
13425 } catch (RemoteException e) {
13426 // If process died, whatever.
13427 }
13428 }
13429 r.stopFreezingScreenLocked(false);
13430
13431 return true;
13432 }
13433
13434 /**
13435 * Save the locale. You must be inside a synchronized (this) block.
13436 */
13437 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13438 if(isDiff) {
13439 SystemProperties.set("user.language", l.getLanguage());
13440 SystemProperties.set("user.region", l.getCountry());
13441 }
13442
13443 if(isPersist) {
13444 SystemProperties.set("persist.sys.language", l.getLanguage());
13445 SystemProperties.set("persist.sys.country", l.getCountry());
13446 SystemProperties.set("persist.sys.localevar", l.getVariant());
13447 }
13448 }
13449
13450 // =========================================================
13451 // LIFETIME MANAGEMENT
13452 // =========================================================
13453
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013454 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13455 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013456 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013457 // This adjustment has already been computed. If we are calling
13458 // from the top, we may have already computed our adjustment with
13459 // an earlier hidden adjustment that isn't really for us... if
13460 // so, use the new hidden adjustment.
13461 if (!recursed && app.hidden) {
13462 app.curAdj = hiddenAdj;
13463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013464 return app.curAdj;
13465 }
13466
13467 if (app.thread == null) {
13468 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013469 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013470 return (app.curAdj=EMPTY_APP_ADJ);
13471 }
13472
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013473 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13474 // The max adjustment doesn't allow this app to be anything
13475 // below foreground, so it is not worth doing work for it.
13476 app.adjType = "fixed";
13477 app.adjSeq = mAdjSeq;
13478 app.curRawAdj = app.maxAdj;
13479 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13480 return (app.curAdj=app.maxAdj);
13481 }
13482
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013483 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013484 app.adjSource = null;
13485 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013486 app.empty = false;
13487 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013488
The Android Open Source Project4df24232009-03-05 14:34:35 -080013489 // Determine the importance of the process, starting with most
13490 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013491 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013492 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013493 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013494 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013495 // The last app on the list is the foreground app.
13496 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013497 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013498 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013499 } else if (app.instrumentationClass != null) {
13500 // Don't want to kill running instrumentation.
13501 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013502 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013503 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013504 } else if (app.persistentActivities > 0) {
13505 // Special persistent activities... shouldn't be used these days.
13506 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013507 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013508 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013509 } else if (app.curReceiver != null ||
13510 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13511 // An app that is currently receiving a broadcast also
13512 // counts as being in the foreground.
13513 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013514 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013515 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013516 } else if (app.executingServices.size() > 0) {
13517 // An app that is currently executing a service callback also
13518 // counts as being in the foreground.
13519 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013520 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013521 app.adjType = "exec-service";
13522 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013523 // The user is aware of this app, so make it visible.
13524 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013525 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013526 app.adjType = "foreground-service";
13527 } else if (app.forcingToForeground != null) {
13528 // The user is aware of this app, so make it visible.
13529 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013530 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013531 app.adjType = "force-foreground";
13532 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013533 } else if (app == mHomeProcess) {
13534 // This process is hosting what we currently consider to be the
13535 // home app, so we don't want to let it go into the background.
13536 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013537 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013538 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013539 } else if ((N=app.activities.size()) != 0) {
13540 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013541 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013542 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013543 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013544 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013545 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013546 for (int j=0; j<N; j++) {
13547 if (((HistoryRecord)app.activities.get(j)).visible) {
13548 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013549 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013550 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013551 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013552 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013553 break;
13554 }
13555 }
13556 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013557 // A very not-needed process. If this is lower in the lru list,
13558 // we will push it in to the empty bucket.
13559 app.hidden = true;
13560 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013561 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013562 adj = hiddenAdj;
13563 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013564 }
13565
Joe Onorato8a9b2202010-02-26 18:56:32 -080013566 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013567
The Android Open Source Project4df24232009-03-05 14:34:35 -080013568 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013569 // there are applications dependent on our services or providers, but
13570 // this gives us a baseline and makes sure we don't get into an
13571 // infinite recursion.
13572 app.adjSeq = mAdjSeq;
13573 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013574
Christopher Tate6fa95972009-06-05 18:43:55 -070013575 if (mBackupTarget != null && app == mBackupTarget.app) {
13576 // If possible we want to avoid killing apps while they're being backed up
13577 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013578 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013579 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013580 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013581 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013582 }
13583 }
13584
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013585 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13586 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013587 final long now = SystemClock.uptimeMillis();
13588 // This process is more important if the top activity is
13589 // bound to the service.
13590 Iterator jt = app.services.iterator();
13591 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13592 ServiceRecord s = (ServiceRecord)jt.next();
13593 if (s.startRequested) {
13594 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13595 // This service has seen some activity within
13596 // recent memory, so we will keep its process ahead
13597 // of the background processes.
13598 if (adj > SECONDARY_SERVER_ADJ) {
13599 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013600 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013601 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013602 }
13603 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013604 // If we have let the service slide into the background
13605 // state, still have some text describing what it is doing
13606 // even though the service no longer has an impact.
13607 if (adj > SECONDARY_SERVER_ADJ) {
13608 app.adjType = "started-bg-services";
13609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013610 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013611 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13612 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013613 Iterator<ConnectionRecord> kt
13614 = s.connections.values().iterator();
13615 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13616 // XXX should compute this based on the max of
13617 // all connected clients.
13618 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013619 if (cr.binding.client == app) {
13620 // Binding to ourself is not interesting.
13621 continue;
13622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013623 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13624 ProcessRecord client = cr.binding.client;
13625 int myHiddenAdj = hiddenAdj;
13626 if (myHiddenAdj > client.hiddenAdj) {
13627 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13628 myHiddenAdj = client.hiddenAdj;
13629 } else {
13630 myHiddenAdj = VISIBLE_APP_ADJ;
13631 }
13632 }
13633 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013634 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013635 if (adj > clientAdj) {
13636 adj = clientAdj > VISIBLE_APP_ADJ
13637 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013638 if (!client.hidden) {
13639 app.hidden = false;
13640 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013641 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013642 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13643 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013644 app.adjSource = cr.binding.client;
13645 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013646 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013647 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13648 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13649 schedGroup = Process.THREAD_GROUP_DEFAULT;
13650 }
13651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013652 }
13653 HistoryRecord a = cr.activity;
13654 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013655 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013656 //}
13657 if (a != null && adj > FOREGROUND_APP_ADJ &&
13658 (a.state == ActivityState.RESUMED
13659 || a.state == ActivityState.PAUSING)) {
13660 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013661 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013662 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013663 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013664 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13665 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013666 app.adjSource = a;
13667 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013668 }
13669 }
13670 }
13671 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013672
13673 // Finally, f this process has active services running in it, we
13674 // would like to avoid killing it unless it would prevent the current
13675 // application from running. By default we put the process in
13676 // with the rest of the background processes; as we scan through
13677 // its services we may bump it up from there.
13678 if (adj > hiddenAdj) {
13679 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013680 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013681 app.adjType = "bg-services";
13682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013683 }
13684
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013685 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13686 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013687 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013688 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13689 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013690 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13691 if (cpr.clients.size() != 0) {
13692 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13693 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13694 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013695 if (client == app) {
13696 // Being our own client is not interesting.
13697 continue;
13698 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013699 int myHiddenAdj = hiddenAdj;
13700 if (myHiddenAdj > client.hiddenAdj) {
13701 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13702 myHiddenAdj = client.hiddenAdj;
13703 } else {
13704 myHiddenAdj = FOREGROUND_APP_ADJ;
13705 }
13706 }
13707 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013708 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013709 if (adj > clientAdj) {
13710 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013711 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013712 if (!client.hidden) {
13713 app.hidden = false;
13714 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013715 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013716 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13717 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013718 app.adjSource = client;
13719 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013720 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013721 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13722 schedGroup = Process.THREAD_GROUP_DEFAULT;
13723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013724 }
13725 }
13726 // If the provider has external (non-framework) process
13727 // dependencies, ensure that its adjustment is at least
13728 // FOREGROUND_APP_ADJ.
13729 if (cpr.externals != 0) {
13730 if (adj > FOREGROUND_APP_ADJ) {
13731 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013732 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013733 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013734 app.adjType = "provider";
13735 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013736 }
13737 }
13738 }
13739 }
13740
13741 app.curRawAdj = adj;
13742
Joe Onorato8a9b2202010-02-26 18:56:32 -080013743 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013744 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13745 if (adj > app.maxAdj) {
13746 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013747 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13748 schedGroup = Process.THREAD_GROUP_DEFAULT;
13749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013750 }
13751
13752 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013753 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013755 return adj;
13756 }
13757
13758 /**
13759 * Ask a given process to GC right now.
13760 */
13761 final void performAppGcLocked(ProcessRecord app) {
13762 try {
13763 app.lastRequestedGc = SystemClock.uptimeMillis();
13764 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013765 if (app.reportLowMemory) {
13766 app.reportLowMemory = false;
13767 app.thread.scheduleLowMemory();
13768 } else {
13769 app.thread.processInBackground();
13770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013771 }
13772 } catch (Exception e) {
13773 // whatever.
13774 }
13775 }
13776
13777 /**
13778 * Returns true if things are idle enough to perform GCs.
13779 */
13780 private final boolean canGcNow() {
13781 return mParallelBroadcasts.size() == 0
13782 && mOrderedBroadcasts.size() == 0
13783 && (mSleeping || (mResumedActivity != null &&
13784 mResumedActivity.idle));
13785 }
13786
13787 /**
13788 * Perform GCs on all processes that are waiting for it, but only
13789 * if things are idle.
13790 */
13791 final void performAppGcsLocked() {
13792 final int N = mProcessesToGc.size();
13793 if (N <= 0) {
13794 return;
13795 }
13796 if (canGcNow()) {
13797 while (mProcessesToGc.size() > 0) {
13798 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013799 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13800 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13801 <= SystemClock.uptimeMillis()) {
13802 // To avoid spamming the system, we will GC processes one
13803 // at a time, waiting a few seconds between each.
13804 performAppGcLocked(proc);
13805 scheduleAppGcsLocked();
13806 return;
13807 } else {
13808 // It hasn't been long enough since we last GCed this
13809 // process... put it in the list to wait for its time.
13810 addProcessToGcListLocked(proc);
13811 break;
13812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013813 }
13814 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013815
13816 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013817 }
13818 }
13819
13820 /**
13821 * If all looks good, perform GCs on all processes waiting for them.
13822 */
13823 final void performAppGcsIfAppropriateLocked() {
13824 if (canGcNow()) {
13825 performAppGcsLocked();
13826 return;
13827 }
13828 // Still not idle, wait some more.
13829 scheduleAppGcsLocked();
13830 }
13831
13832 /**
13833 * Schedule the execution of all pending app GCs.
13834 */
13835 final void scheduleAppGcsLocked() {
13836 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013837
13838 if (mProcessesToGc.size() > 0) {
13839 // Schedule a GC for the time to the next process.
13840 ProcessRecord proc = mProcessesToGc.get(0);
13841 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13842
13843 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13844 long now = SystemClock.uptimeMillis();
13845 if (when < (now+GC_TIMEOUT)) {
13846 when = now + GC_TIMEOUT;
13847 }
13848 mHandler.sendMessageAtTime(msg, when);
13849 }
13850 }
13851
13852 /**
13853 * Add a process to the array of processes waiting to be GCed. Keeps the
13854 * list in sorted order by the last GC time. The process can't already be
13855 * on the list.
13856 */
13857 final void addProcessToGcListLocked(ProcessRecord proc) {
13858 boolean added = false;
13859 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13860 if (mProcessesToGc.get(i).lastRequestedGc <
13861 proc.lastRequestedGc) {
13862 added = true;
13863 mProcessesToGc.add(i+1, proc);
13864 break;
13865 }
13866 }
13867 if (!added) {
13868 mProcessesToGc.add(0, proc);
13869 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013870 }
13871
13872 /**
13873 * Set up to ask a process to GC itself. This will either do it
13874 * immediately, or put it on the list of processes to gc the next
13875 * time things are idle.
13876 */
13877 final void scheduleAppGcLocked(ProcessRecord app) {
13878 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013879 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013880 return;
13881 }
13882 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013883 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013884 scheduleAppGcsLocked();
13885 }
13886 }
13887
13888 private final boolean updateOomAdjLocked(
13889 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13890 app.hiddenAdj = hiddenAdj;
13891
13892 if (app.thread == null) {
13893 return true;
13894 }
13895
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013896 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013897
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013898 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013899 if (app.curRawAdj != app.setRawAdj) {
13900 if (app.curRawAdj > FOREGROUND_APP_ADJ
13901 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13902 // If this app is transitioning from foreground to
13903 // non-foreground, have it do a gc.
13904 scheduleAppGcLocked(app);
13905 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13906 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13907 // Likewise do a gc when an app is moving in to the
13908 // background (such as a service stopping).
13909 scheduleAppGcLocked(app);
13910 }
13911 app.setRawAdj = app.curRawAdj;
13912 }
13913 if (adj != app.setAdj) {
13914 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013915 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013916 TAG, "Set app " + app.processName +
13917 " oom adj to " + adj);
13918 app.setAdj = adj;
13919 } else {
13920 return false;
13921 }
13922 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013923 if (app.setSchedGroup != app.curSchedGroup) {
13924 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013925 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013926 "Setting process group of " + app.processName
13927 + " to " + app.curSchedGroup);
13928 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013929 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013930 try {
13931 Process.setProcessGroup(app.pid, app.curSchedGroup);
13932 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013933 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013934 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013935 e.printStackTrace();
13936 } finally {
13937 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013938 }
13939 }
13940 if (false) {
13941 if (app.thread != null) {
13942 try {
13943 app.thread.setSchedulingGroup(app.curSchedGroup);
13944 } catch (RemoteException e) {
13945 }
13946 }
13947 }
13948 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013949 }
13950
13951 return true;
13952 }
13953
13954 private final HistoryRecord resumedAppLocked() {
13955 HistoryRecord resumedActivity = mResumedActivity;
13956 if (resumedActivity == null || resumedActivity.app == null) {
13957 resumedActivity = mPausingActivity;
13958 if (resumedActivity == null || resumedActivity.app == null) {
13959 resumedActivity = topRunningActivityLocked(null);
13960 }
13961 }
13962 return resumedActivity;
13963 }
13964
13965 private final boolean updateOomAdjLocked(ProcessRecord app) {
13966 final HistoryRecord TOP_ACT = resumedAppLocked();
13967 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13968 int curAdj = app.curAdj;
13969 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13970 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13971
13972 mAdjSeq++;
13973
13974 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13975 if (res) {
13976 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13977 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13978 if (nowHidden != wasHidden) {
13979 // Changed to/from hidden state, so apps after it in the LRU
13980 // list may also be changed.
13981 updateOomAdjLocked();
13982 }
13983 }
13984 return res;
13985 }
13986
13987 private final boolean updateOomAdjLocked() {
13988 boolean didOomAdj = true;
13989 final HistoryRecord TOP_ACT = resumedAppLocked();
13990 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13991
13992 if (false) {
13993 RuntimeException e = new RuntimeException();
13994 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013995 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013996 }
13997
13998 mAdjSeq++;
13999
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014000 // Let's determine how many processes we have running vs.
14001 // how many slots we have for background processes; we may want
14002 // to put multiple processes in a slot of there are enough of
14003 // them.
14004 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14005 int factor = (mLruProcesses.size()-4)/numSlots;
14006 if (factor < 1) factor = 1;
14007 int step = 0;
14008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014009 // First try updating the OOM adjustment for each of the
14010 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014011 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014012 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14013 while (i > 0) {
14014 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014015 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014016 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014017 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014018 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014019 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014020 step++;
14021 if (step >= factor) {
14022 step = 0;
14023 curHiddenAdj++;
14024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014025 }
14026 } else {
14027 didOomAdj = false;
14028 }
14029 }
14030
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014031 // If we return false, we will fall back on killing processes to
14032 // have a fixed limit. Do this if a limit has been requested; else
14033 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014034 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14035 }
14036
14037 private final void trimApplications() {
14038 synchronized (this) {
14039 int i;
14040
14041 // First remove any unused application processes whose package
14042 // has been removed.
14043 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14044 final ProcessRecord app = mRemovedProcesses.get(i);
14045 if (app.activities.size() == 0
14046 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014047 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014048 TAG, "Exiting empty application process "
14049 + app.processName + " ("
14050 + (app.thread != null ? app.thread.asBinder() : null)
14051 + ")\n");
14052 if (app.pid > 0 && app.pid != MY_PID) {
14053 Process.killProcess(app.pid);
14054 } else {
14055 try {
14056 app.thread.scheduleExit();
14057 } catch (Exception e) {
14058 // Ignore exceptions.
14059 }
14060 }
14061 cleanUpApplicationRecordLocked(app, false, -1);
14062 mRemovedProcesses.remove(i);
14063
14064 if (app.persistent) {
14065 if (app.persistent) {
14066 addAppLocked(app.info);
14067 }
14068 }
14069 }
14070 }
14071
14072 // Now try updating the OOM adjustment for each of the
14073 // application processes based on their current state.
14074 // If the setOomAdj() API is not supported, then go with our
14075 // back-up plan...
14076 if (!updateOomAdjLocked()) {
14077
14078 // Count how many processes are running services.
14079 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014080 for (i=mLruProcesses.size()-1; i>=0; i--) {
14081 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014082
14083 if (app.persistent || app.services.size() != 0
14084 || app.curReceiver != null
14085 || app.persistentActivities > 0) {
14086 // Don't count processes holding services against our
14087 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014088 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014089 TAG, "Not trimming app " + app + " with services: "
14090 + app.services);
14091 numServiceProcs++;
14092 }
14093 }
14094
14095 int curMaxProcs = mProcessLimit;
14096 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14097 if (mAlwaysFinishActivities) {
14098 curMaxProcs = 1;
14099 }
14100 curMaxProcs += numServiceProcs;
14101
14102 // Quit as many processes as we can to get down to the desired
14103 // process count. First remove any processes that no longer
14104 // have activites running in them.
14105 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014106 i<mLruProcesses.size()
14107 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014108 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014109 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014110 // Quit an application only if it is not currently
14111 // running any activities.
14112 if (!app.persistent && app.activities.size() == 0
14113 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014114 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014115 TAG, "Exiting empty application process "
14116 + app.processName + " ("
14117 + (app.thread != null ? app.thread.asBinder() : null)
14118 + ")\n");
14119 if (app.pid > 0 && app.pid != MY_PID) {
14120 Process.killProcess(app.pid);
14121 } else {
14122 try {
14123 app.thread.scheduleExit();
14124 } catch (Exception e) {
14125 // Ignore exceptions.
14126 }
14127 }
14128 // todo: For now we assume the application is not buggy
14129 // or evil, and will quit as a result of our request.
14130 // Eventually we need to drive this off of the death
14131 // notification, and kill the process if it takes too long.
14132 cleanUpApplicationRecordLocked(app, false, i);
14133 i--;
14134 }
14135 }
14136
14137 // If we still have too many processes, now from the least
14138 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014139 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014140 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014141 " of " + curMaxProcs + " processes");
14142 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014143 i<mLruProcesses.size()
14144 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014145 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014146 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014147 // Quit the application only if we have a state saved for
14148 // all of its activities.
14149 boolean canQuit = !app.persistent && app.curReceiver == null
14150 && app.services.size() == 0
14151 && app.persistentActivities == 0;
14152 int NUMA = app.activities.size();
14153 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014154 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014155 TAG, "Looking to quit " + app.processName);
14156 for (j=0; j<NUMA && canQuit; j++) {
14157 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014158 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014159 TAG, " " + r.intent.getComponent().flattenToShortString()
14160 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14161 canQuit = (r.haveState || !r.stateNotNeeded)
14162 && !r.visible && r.stopped;
14163 }
14164 if (canQuit) {
14165 // Finish all of the activities, and then the app itself.
14166 for (j=0; j<NUMA; j++) {
14167 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14168 if (!r.finishing) {
14169 destroyActivityLocked(r, false);
14170 }
14171 r.resultTo = null;
14172 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014173 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014174 + app.processName + " ("
14175 + (app.thread != null ? app.thread.asBinder() : null)
14176 + ")\n");
14177 if (app.pid > 0 && app.pid != MY_PID) {
14178 Process.killProcess(app.pid);
14179 } else {
14180 try {
14181 app.thread.scheduleExit();
14182 } catch (Exception e) {
14183 // Ignore exceptions.
14184 }
14185 }
14186 // todo: For now we assume the application is not buggy
14187 // or evil, and will quit as a result of our request.
14188 // Eventually we need to drive this off of the death
14189 // notification, and kill the process if it takes too long.
14190 cleanUpApplicationRecordLocked(app, false, i);
14191 i--;
14192 //dump();
14193 }
14194 }
14195
14196 }
14197
14198 int curMaxActivities = MAX_ACTIVITIES;
14199 if (mAlwaysFinishActivities) {
14200 curMaxActivities = 1;
14201 }
14202
14203 // Finally, if there are too many activities now running, try to
14204 // finish as many as we can to get back down to the limit.
14205 for ( i=0;
14206 i<mLRUActivities.size()
14207 && mLRUActivities.size() > curMaxActivities;
14208 i++) {
14209 final HistoryRecord r
14210 = (HistoryRecord)mLRUActivities.get(i);
14211
14212 // We can finish this one if we have its icicle saved and
14213 // it is not persistent.
14214 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14215 && r.stopped && !r.persistent && !r.finishing) {
14216 final int origSize = mLRUActivities.size();
14217 destroyActivityLocked(r, true);
14218
14219 // This will remove it from the LRU list, so keep
14220 // our index at the same value. Note that this check to
14221 // see if the size changes is just paranoia -- if
14222 // something unexpected happens, we don't want to end up
14223 // in an infinite loop.
14224 if (origSize > mLRUActivities.size()) {
14225 i--;
14226 }
14227 }
14228 }
14229 }
14230 }
14231
14232 /** This method sends the specified signal to each of the persistent apps */
14233 public void signalPersistentProcesses(int sig) throws RemoteException {
14234 if (sig != Process.SIGNAL_USR1) {
14235 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14236 }
14237
14238 synchronized (this) {
14239 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14240 != PackageManager.PERMISSION_GRANTED) {
14241 throw new SecurityException("Requires permission "
14242 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14243 }
14244
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014245 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14246 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014247 if (r.thread != null && r.persistent) {
14248 Process.sendSignal(r.pid, sig);
14249 }
14250 }
14251 }
14252 }
14253
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014254 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014255 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014256
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014257 try {
14258 synchronized (this) {
14259 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14260 // its own permission.
14261 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14262 != PackageManager.PERMISSION_GRANTED) {
14263 throw new SecurityException("Requires permission "
14264 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014265 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014266
14267 if (start && fd == null) {
14268 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014269 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014270
14271 ProcessRecord proc = null;
14272 try {
14273 int pid = Integer.parseInt(process);
14274 synchronized (mPidsSelfLocked) {
14275 proc = mPidsSelfLocked.get(pid);
14276 }
14277 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014278 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014279
14280 if (proc == null) {
14281 HashMap<String, SparseArray<ProcessRecord>> all
14282 = mProcessNames.getMap();
14283 SparseArray<ProcessRecord> procs = all.get(process);
14284 if (procs != null && procs.size() > 0) {
14285 proc = procs.valueAt(0);
14286 }
14287 }
14288
14289 if (proc == null || proc.thread == null) {
14290 throw new IllegalArgumentException("Unknown process: " + process);
14291 }
14292
14293 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14294 if (isSecure) {
14295 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14296 throw new SecurityException("Process not debuggable: " + proc);
14297 }
14298 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014299
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014300 proc.thread.profilerControl(start, path, fd);
14301 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014302 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014303 }
14304 } catch (RemoteException e) {
14305 throw new IllegalStateException("Process disappeared");
14306 } finally {
14307 if (fd != null) {
14308 try {
14309 fd.close();
14310 } catch (IOException e) {
14311 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014312 }
14313 }
14314 }
14315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014316 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14317 public void monitor() {
14318 synchronized (this) { }
14319 }
14320}