blob: 7e095b588a9337ad41f10e9d611fe8e699a38445 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070020import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.server.IntentResolver;
22import com.android.server.ProcessMap;
23import com.android.server.ProcessStats;
24import com.android.server.SystemServer;
25import com.android.server.Watchdog;
26import com.android.server.WindowManagerService;
27
Dianne Hackborndd71fc82009-12-16 19:24:32 -080028import dalvik.system.Zygote;
29
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.app.Activity;
31import android.app.ActivityManager;
32import android.app.ActivityManagerNative;
33import android.app.ActivityThread;
34import android.app.AlertDialog;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020035import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070037import android.app.IActivityController;
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -080038import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.IActivityWatcher;
40import android.app.IApplicationThread;
41import android.app.IInstrumentationWatcher;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.app.IServiceConnection;
43import android.app.IThumbnailReceiver;
44import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070045import android.app.Notification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.PendingIntent;
47import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070048import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080049import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020050import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080051import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.ComponentName;
53import android.content.ContentResolver;
54import android.content.Context;
55import android.content.Intent;
56import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070057import android.content.IIntentReceiver;
58import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070059import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.content.pm.ActivityInfo;
61import android.content.pm.ApplicationInfo;
62import android.content.pm.ConfigurationInfo;
63import android.content.pm.IPackageDataObserver;
64import android.content.pm.IPackageManager;
65import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080066import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070068import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.content.pm.ProviderInfo;
70import android.content.pm.ResolveInfo;
71import android.content.pm.ServiceInfo;
72import android.content.res.Configuration;
73import android.graphics.Bitmap;
74import android.net.Uri;
75import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080076import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080077import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070078import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080079import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.FileUtils;
83import android.os.Handler;
84import android.os.IBinder;
85import android.os.IPermissionController;
86import android.os.Looper;
87import android.os.Message;
88import android.os.Parcel;
89import android.os.ParcelFileDescriptor;
90import android.os.PowerManager;
91import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070092import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.os.RemoteException;
94import android.os.ServiceManager;
95import android.os.SystemClock;
96import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.util.Config;
99import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800100import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800101import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.PrintWriterPrinter;
103import android.util.SparseArray;
104import android.view.Gravity;
105import android.view.LayoutInflater;
106import android.view.View;
107import android.view.WindowManager;
108import android.view.WindowManagerPolicy;
109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import java.io.File;
111import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200113import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800114import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import java.io.PrintWriter;
116import java.lang.IllegalStateException;
117import java.lang.ref.WeakReference;
118import java.util.ArrayList;
119import java.util.HashMap;
120import java.util.HashSet;
121import java.util.Iterator;
122import java.util.List;
123import java.util.Locale;
124import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700125import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700126import java.util.concurrent.atomic.AtomicBoolean;
127import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128
129public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
130 static final String TAG = "ActivityManager";
131 static final boolean DEBUG = false;
132 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
133 static final boolean DEBUG_SWITCH = localLOGV || false;
134 static final boolean DEBUG_TASKS = localLOGV || false;
135 static final boolean DEBUG_PAUSE = localLOGV || false;
136 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
137 static final boolean DEBUG_TRANSITION = localLOGV || false;
138 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700139 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 static final boolean DEBUG_SERVICE = localLOGV || false;
141 static final boolean DEBUG_VISBILITY = localLOGV || false;
142 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700143 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800144 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700146 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700147 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700148 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 static final boolean VALIDATE_TOKENS = false;
150 static final boolean SHOW_ACTIVITY_START_TIME = true;
151
152 // Control over CPU and battery monitoring.
153 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
154 static final boolean MONITOR_CPU_USAGE = true;
155 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
156 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
157 static final boolean MONITOR_THREAD_CPU_USAGE = false;
158
Dianne Hackborn1655be42009-05-08 14:29:01 -0700159 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700160 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 private static final String SYSTEM_SECURE = "ro.secure";
163
164 // This is the maximum number of application processes we would like
165 // to have running. Due to the asynchronous nature of things, we can
166 // temporarily go beyond this limit.
167 static final int MAX_PROCESSES = 2;
168
169 // Set to false to leave processes running indefinitely, relying on
170 // the kernel killing them as resources are required.
171 static final boolean ENFORCE_PROCESS_LIMIT = false;
172
173 // This is the maximum number of activities that we would like to have
174 // running at a given time.
175 static final int MAX_ACTIVITIES = 20;
176
177 // Maximum number of recent tasks that we can remember.
178 static final int MAX_RECENT_TASKS = 20;
179
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700180 // Amount of time after a call to stopAppSwitches() during which we will
181 // prevent further untrusted switches from happening.
182 static final long APP_SWITCH_DELAY_TIME = 5*1000;
183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 // How long until we reset a task when the user returns to it. Currently
185 // 30 minutes.
186 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
187
188 // Set to true to disable the icon that is shown while a new activity
189 // is being started.
190 static final boolean SHOW_APP_STARTING_ICON = true;
191
192 // How long we wait until giving up on the last activity to pause. This
193 // is short because it directly impacts the responsiveness of starting the
194 // next activity.
195 static final int PAUSE_TIMEOUT = 500;
196
197 /**
198 * How long we can hold the launch wake lock before giving up.
199 */
200 static final int LAUNCH_TIMEOUT = 10*1000;
201
202 // How long we wait for a launched process to attach to the activity manager
203 // before we decide it's never going to come up for real.
204 static final int PROC_START_TIMEOUT = 10*1000;
205
206 // How long we wait until giving up on the last activity telling us it
207 // is idle.
208 static final int IDLE_TIMEOUT = 10*1000;
209
210 // How long to wait after going idle before forcing apps to GC.
211 static final int GC_TIMEOUT = 5*1000;
212
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700213 // The minimum amount of time between successive GC requests for a process.
214 static final int GC_MIN_INTERVAL = 60*1000;
215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 // How long we wait until giving up on an activity telling us it has
217 // finished destroying itself.
218 static final int DESTROY_TIMEOUT = 10*1000;
219
220 // How long we allow a receiver to run before giving up on it.
221 static final int BROADCAST_TIMEOUT = 10*1000;
222
223 // How long we wait for a service to finish executing.
224 static final int SERVICE_TIMEOUT = 20*1000;
225
226 // How long a service needs to be running until restarting its process
227 // is no longer considered to be a relaunch of the service.
228 static final int SERVICE_RESTART_DURATION = 5*1000;
229
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700230 // How long a service needs to be running until it will start back at
231 // SERVICE_RESTART_DURATION after being killed.
232 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
233
234 // Multiplying factor to increase restart duration time by, for each time
235 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
236 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
237
238 // The minimum amount of time between restarting services that we allow.
239 // That is, when multiple services are restarting, we won't allow each
240 // to restart less than this amount of time from the last one.
241 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 // Maximum amount of time for there to be no activity on a service before
244 // we consider it non-essential and allow its process to go on the
245 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700246 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 // How long we wait until we timeout on key dispatching.
249 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
250
251 // The minimum time we allow between crashes, for us to consider this
252 // application to be bad and stop and its services and reject broadcasts.
253 static final int MIN_CRASH_INTERVAL = 60*1000;
254
255 // How long we wait until we timeout on key dispatching during instrumentation.
256 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
257
258 // OOM adjustments for processes in various states:
259
260 // This is a process without anything currently running in it. Definitely
261 // the first to go! Value set in system/rootdir/init.rc on startup.
262 // This value is initalized in the constructor, careful when refering to
263 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800264 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
266 // This is a process only hosting activities that are not visible,
267 // so it can be killed without any disruption. Value set in
268 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 static int HIDDEN_APP_MIN_ADJ;
271
The Android Open Source Project4df24232009-03-05 14:34:35 -0800272 // This is a process holding the home application -- we want to try
273 // avoiding killing it, even if it would normally be in the background,
274 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800276
Christopher Tate6fa95972009-06-05 18:43:55 -0700277 // This is a process currently hosting a backup operation. Killing it
278 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800279 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 // This is a process holding a secondary server -- killing it will not
282 // have much of an impact as far as the user is concerned. Value set in
283 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
286 // This is a process only hosting activities that are visible to the
287 // user, so we'd prefer they don't disappear. Value set in
288 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
291 // This is the process running the current foreground app. We'd really
292 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800293 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294
295 // This is a process running a core server, such as telephony. Definitely
296 // don't want to kill it, but doing so is not completely fatal.
297 static final int CORE_SERVER_ADJ = -12;
298
299 // The system process runs at the default adjustment.
300 static final int SYSTEM_ADJ = -16;
301
302 // Memory pages are 4K.
303 static final int PAGE_SIZE = 4*1024;
304
305 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int EMPTY_APP_MEM;
307 static final int HIDDEN_APP_MEM;
308 static final int HOME_APP_MEM;
309 static final int BACKUP_APP_MEM;
310 static final int SECONDARY_SERVER_MEM;
311 static final int VISIBLE_APP_MEM;
312 static final int FOREGROUND_APP_MEM;
313
314 // The minimum number of hidden apps we want to be able to keep around,
315 // without empty apps being able to push them out of memory.
316 static final int MIN_HIDDEN_APPS = 2;
317
318 // We put empty content processes after any hidden processes that have
319 // been idle for less than 30 seconds.
320 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
321
322 // We put empty content processes after any hidden processes that have
323 // been idle for less than 60 seconds.
324 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
325
326 static {
327 // These values are set in system/rootdir/init.rc on startup.
328 FOREGROUND_APP_ADJ =
329 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
330 VISIBLE_APP_ADJ =
331 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
332 SECONDARY_SERVER_ADJ =
333 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
334 BACKUP_APP_ADJ =
335 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
336 HOME_APP_ADJ =
337 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
338 HIDDEN_APP_MIN_ADJ =
339 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
340 EMPTY_APP_ADJ =
341 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
342 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
343 FOREGROUND_APP_MEM =
344 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
345 VISIBLE_APP_MEM =
346 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
347 SECONDARY_SERVER_MEM =
348 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
349 BACKUP_APP_MEM =
350 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
351 HOME_APP_MEM =
352 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
353 HIDDEN_APP_MEM =
354 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
355 EMPTY_APP_MEM =
356 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358
Dan Egnor42471dd2010-01-07 17:25:22 -0800359 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360
361 static final String[] EMPTY_STRING_ARRAY = new String[0];
362
363 enum ActivityState {
364 INITIALIZING,
365 RESUMED,
366 PAUSING,
367 PAUSED,
368 STOPPING,
369 STOPPED,
370 FINISHING,
371 DESTROYING,
372 DESTROYED
373 }
374
375 /**
376 * The back history of all previous (and possibly still
377 * running) activities. It contains HistoryRecord objects.
378 */
379 final ArrayList mHistory = new ArrayList();
380
381 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700382 * Description of a request to start a new activity, which has been held
383 * due to app switches being disabled.
384 */
385 class PendingActivityLaunch {
386 HistoryRecord r;
387 HistoryRecord sourceRecord;
388 Uri[] grantedUriPermissions;
389 int grantedMode;
390 boolean onlyIfNeeded;
391 }
392
393 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
394 = new ArrayList<PendingActivityLaunch>();
395
396 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800397 * List of people waiting to find out about the next launched activity.
398 */
399 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
400 = new ArrayList<IActivityManager.WaitResult>();
401
402 /**
403 * List of people waiting to find out about the next visible activity.
404 */
405 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
406 = new ArrayList<IActivityManager.WaitResult>();
407
408 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 * List of all active broadcasts that are to be executed immediately
410 * (without waiting for another broadcast to finish). Currently this only
411 * contains broadcasts to registered receivers, to avoid spinning up
412 * a bunch of processes to execute IntentReceiver components.
413 */
414 final ArrayList<BroadcastRecord> mParallelBroadcasts
415 = new ArrayList<BroadcastRecord>();
416
417 /**
418 * List of all active broadcasts that are to be executed one at a time.
419 * The object at the top of the list is the currently activity broadcasts;
420 * those after it are waiting for the top to finish..
421 */
422 final ArrayList<BroadcastRecord> mOrderedBroadcasts
423 = new ArrayList<BroadcastRecord>();
424
425 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800426 * Historical data of past broadcasts, for debugging.
427 */
428 static final int MAX_BROADCAST_HISTORY = 100;
429 final BroadcastRecord[] mBroadcastHistory
430 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
431
432 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 * Set when we current have a BROADCAST_INTENT_MSG in flight.
434 */
435 boolean mBroadcastsScheduled = false;
436
437 /**
438 * Set to indicate whether to issue an onUserLeaving callback when a
439 * newly launched activity is being brought in front of us.
440 */
441 boolean mUserLeaving = false;
442
443 /**
444 * When we are in the process of pausing an activity, before starting the
445 * next one, this variable holds the activity that is currently being paused.
446 */
447 HistoryRecord mPausingActivity = null;
448
449 /**
450 * Current activity that is resumed, or null if there is none.
451 */
452 HistoryRecord mResumedActivity = null;
453
454 /**
455 * Activity we have told the window manager to have key focus.
456 */
457 HistoryRecord mFocusedActivity = null;
458
459 /**
460 * This is the last activity that we put into the paused state. This is
461 * used to determine if we need to do an activity transition while sleeping,
462 * when we normally hold the top activity paused.
463 */
464 HistoryRecord mLastPausedActivity = null;
465
466 /**
467 * List of activities that are waiting for a new activity
468 * to become visible before completing whatever operation they are
469 * supposed to do.
470 */
471 final ArrayList mWaitingVisibleActivities = new ArrayList();
472
473 /**
474 * List of activities that are ready to be stopped, but waiting
475 * for the next activity to settle down before doing so. It contains
476 * HistoryRecord objects.
477 */
478 final ArrayList<HistoryRecord> mStoppingActivities
479 = new ArrayList<HistoryRecord>();
480
481 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700482 * Animations that for the current transition have requested not to
483 * be considered for the transition animation.
484 */
485 final ArrayList<HistoryRecord> mNoAnimActivities
486 = new ArrayList<HistoryRecord>();
487
488 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 * List of intents that were used to start the most recent tasks.
490 */
491 final ArrayList<TaskRecord> mRecentTasks
492 = new ArrayList<TaskRecord>();
493
494 /**
495 * List of activities that are ready to be finished, but waiting
496 * for the previous activity to settle down before doing so. It contains
497 * HistoryRecord objects.
498 */
499 final ArrayList mFinishingActivities = new ArrayList();
500
501 /**
502 * All of the applications we currently have running organized by name.
503 * The keys are strings of the application package name (as
504 * returned by the package manager), and the keys are ApplicationRecord
505 * objects.
506 */
507 final ProcessMap<ProcessRecord> mProcessNames
508 = new ProcessMap<ProcessRecord>();
509
510 /**
511 * The last time that various processes have crashed.
512 */
513 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
514
515 /**
516 * Set of applications that we consider to be bad, and will reject
517 * incoming broadcasts from (which the user has no control over).
518 * Processes are added to this set when they have crashed twice within
519 * a minimum amount of time; they are removed from it when they are
520 * later restarted (hopefully due to some user action). The value is the
521 * time it was added to the list.
522 */
523 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
524
525 /**
526 * All of the processes we currently have running organized by pid.
527 * The keys are the pid running the application.
528 *
529 * <p>NOTE: This object is protected by its own lock, NOT the global
530 * activity manager lock!
531 */
532 final SparseArray<ProcessRecord> mPidsSelfLocked
533 = new SparseArray<ProcessRecord>();
534
535 /**
536 * All of the processes that have been forced to be foreground. The key
537 * is the pid of the caller who requested it (we hold a death
538 * link on it).
539 */
540 abstract class ForegroundToken implements IBinder.DeathRecipient {
541 int pid;
542 IBinder token;
543 }
544 final SparseArray<ForegroundToken> mForegroundProcesses
545 = new SparseArray<ForegroundToken>();
546
547 /**
548 * List of records for processes that someone had tried to start before the
549 * system was ready. We don't start them at that point, but ensure they
550 * are started by the time booting is complete.
551 */
552 final ArrayList<ProcessRecord> mProcessesOnHold
553 = new ArrayList<ProcessRecord>();
554
555 /**
556 * List of records for processes that we have started and are waiting
557 * for them to call back. This is really only needed when running in
558 * single processes mode, in which case we do not have a unique pid for
559 * each process.
560 */
561 final ArrayList<ProcessRecord> mStartingProcesses
562 = new ArrayList<ProcessRecord>();
563
564 /**
565 * List of persistent applications that are in the process
566 * of being started.
567 */
568 final ArrayList<ProcessRecord> mPersistentStartingProcesses
569 = new ArrayList<ProcessRecord>();
570
571 /**
572 * Processes that are being forcibly torn down.
573 */
574 final ArrayList<ProcessRecord> mRemovedProcesses
575 = new ArrayList<ProcessRecord>();
576
577 /**
578 * List of running applications, sorted by recent usage.
579 * The first entry in the list is the least recently used.
580 * It contains ApplicationRecord objects. This list does NOT include
581 * any persistent application records (since we never want to exit them).
582 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800583 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 = new ArrayList<ProcessRecord>();
585
586 /**
587 * List of processes that should gc as soon as things are idle.
588 */
589 final ArrayList<ProcessRecord> mProcessesToGc
590 = new ArrayList<ProcessRecord>();
591
592 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800593 * This is the process holding what we currently consider to be
594 * the "home" activity.
595 */
596 private ProcessRecord mHomeProcess;
597
598 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 * List of running activities, sorted by recent usage.
600 * The first entry in the list is the least recently used.
601 * It contains HistoryRecord objects.
602 */
603 private final ArrayList mLRUActivities = new ArrayList();
604
605 /**
606 * Set of PendingResultRecord objects that are currently active.
607 */
608 final HashSet mPendingResultRecords = new HashSet();
609
610 /**
611 * Set of IntentSenderRecord objects that are currently active.
612 */
613 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
614 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
615
616 /**
617 * Intent broadcast that we have tried to start, but are
618 * waiting for its application's process to be created. We only
619 * need one (instead of a list) because we always process broadcasts
620 * one at a time, so no others can be started while waiting for this
621 * one.
622 */
623 BroadcastRecord mPendingBroadcast = null;
624
625 /**
626 * Keeps track of all IIntentReceivers that have been registered for
627 * broadcasts. Hash keys are the receiver IBinder, hash value is
628 * a ReceiverList.
629 */
630 final HashMap mRegisteredReceivers = new HashMap();
631
632 /**
633 * Resolver for broadcast intents to registered receivers.
634 * Holds BroadcastFilter (subclass of IntentFilter).
635 */
636 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
637 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
638 @Override
639 protected boolean allowFilterResult(
640 BroadcastFilter filter, List<BroadcastFilter> dest) {
641 IBinder target = filter.receiverList.receiver.asBinder();
642 for (int i=dest.size()-1; i>=0; i--) {
643 if (dest.get(i).receiverList.receiver.asBinder() == target) {
644 return false;
645 }
646 }
647 return true;
648 }
649 };
650
651 /**
652 * State of all active sticky broadcasts. Keys are the action of the
653 * sticky Intent, values are an ArrayList of all broadcasted intents with
654 * that action (which should usually be one).
655 */
656 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
657 new HashMap<String, ArrayList<Intent>>();
658
659 /**
660 * All currently running services.
661 */
662 final HashMap<ComponentName, ServiceRecord> mServices =
663 new HashMap<ComponentName, ServiceRecord>();
664
665 /**
666 * All currently running services indexed by the Intent used to start them.
667 */
668 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
669 new HashMap<Intent.FilterComparison, ServiceRecord>();
670
671 /**
672 * All currently bound service connections. Keys are the IBinder of
673 * the client's IServiceConnection.
674 */
675 final HashMap<IBinder, ConnectionRecord> mServiceConnections
676 = new HashMap<IBinder, ConnectionRecord>();
677
678 /**
679 * List of services that we have been asked to start,
680 * but haven't yet been able to. It is used to hold start requests
681 * while waiting for their corresponding application thread to get
682 * going.
683 */
684 final ArrayList<ServiceRecord> mPendingServices
685 = new ArrayList<ServiceRecord>();
686
687 /**
688 * List of services that are scheduled to restart following a crash.
689 */
690 final ArrayList<ServiceRecord> mRestartingServices
691 = new ArrayList<ServiceRecord>();
692
693 /**
694 * List of services that are in the process of being stopped.
695 */
696 final ArrayList<ServiceRecord> mStoppingServices
697 = new ArrayList<ServiceRecord>();
698
699 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700700 * Backup/restore process management
701 */
702 String mBackupAppName = null;
703 BackupRecord mBackupTarget = null;
704
705 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 * List of PendingThumbnailsRecord objects of clients who are still
707 * waiting to receive all of the thumbnails for a task.
708 */
709 final ArrayList mPendingThumbnails = new ArrayList();
710
711 /**
712 * List of HistoryRecord objects that have been finished and must
713 * still report back to a pending thumbnail receiver.
714 */
715 final ArrayList mCancelledThumbnails = new ArrayList();
716
717 /**
718 * All of the currently running global content providers. Keys are a
719 * string containing the provider name and values are a
720 * ContentProviderRecord object containing the data about it. Note
721 * that a single provider may be published under multiple names, so
722 * there may be multiple entries here for a single one in mProvidersByClass.
723 */
724 final HashMap mProvidersByName = new HashMap();
725
726 /**
727 * All of the currently running global content providers. Keys are a
728 * string containing the provider's implementation class and values are a
729 * ContentProviderRecord object containing the data about it.
730 */
731 final HashMap mProvidersByClass = new HashMap();
732
733 /**
734 * List of content providers who have clients waiting for them. The
735 * application is currently being launched and the provider will be
736 * removed from this list once it is published.
737 */
738 final ArrayList mLaunchingProviders = new ArrayList();
739
740 /**
741 * Global set of specific Uri permissions that have been granted.
742 */
743 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
744 = new SparseArray<HashMap<Uri, UriPermission>>();
745
746 /**
747 * Thread-local storage used to carry caller permissions over through
748 * indirect content-provider access.
749 * @see #ActivityManagerService.openContentUri()
750 */
751 private class Identity {
752 public int pid;
753 public int uid;
754
755 Identity(int _pid, int _uid) {
756 pid = _pid;
757 uid = _uid;
758 }
759 }
760 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
761
762 /**
763 * All information we have collected about the runtime performance of
764 * any user id that can impact battery performance.
765 */
766 final BatteryStatsService mBatteryStatsService;
767
768 /**
769 * information about component usage
770 */
771 final UsageStatsService mUsageStatsService;
772
773 /**
774 * Current configuration information. HistoryRecord objects are given
775 * a reference to this object to indicate which configuration they are
776 * currently running in, so this object must be kept immutable.
777 */
778 Configuration mConfiguration = new Configuration();
779
780 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800781 * Current sequencing integer of the configuration, for skipping old
782 * configurations.
783 */
784 int mConfigurationSeq = 0;
785
786 /**
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700787 * Set when we know we are going to be calling updateConfiguration()
788 * soon, so want to skip intermediate config checks.
789 */
790 boolean mConfigWillChange;
791
792 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700793 * Hardware-reported OpenGLES version.
794 */
795 final int GL_ES_VERSION;
796
797 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 * List of initialization arguments to pass to all processes when binding applications to them.
799 * For example, references to the commonly used services.
800 */
801 HashMap<String, IBinder> mAppBindArgs;
802
803 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700804 * Temporary to avoid allocations. Protected by main lock.
805 */
806 final StringBuilder mStringBuilder = new StringBuilder(256);
807
808 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 * Used to control how we initialize the service.
810 */
811 boolean mStartRunning = false;
812 ComponentName mTopComponent;
813 String mTopAction;
814 String mTopData;
815 boolean mSystemReady = false;
816 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700817 boolean mWaitingUpdate = false;
818 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819
820 Context mContext;
821
822 int mFactoryTest;
823
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700824 boolean mCheckedForSetup;
825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700827 * The time at which we will allow normal application switches again,
828 * after a call to {@link #stopAppSwitches()}.
829 */
830 long mAppSwitchesAllowedTime;
831
832 /**
833 * This is set to true after the first switch after mAppSwitchesAllowedTime
834 * is set; any switches after that will clear the time.
835 */
836 boolean mDidAppSwitch;
837
838 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 * Set while we are wanting to sleep, to prevent any
840 * activities from being started/resumed.
841 */
842 boolean mSleeping = false;
843
844 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700845 * Set if we are shutting down the system, similar to sleeping.
846 */
847 boolean mShuttingDown = false;
848
849 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 * Set when the system is going to sleep, until we have
851 * successfully paused the current activity and released our wake lock.
852 * At that point the system is allowed to actually sleep.
853 */
854 PowerManager.WakeLock mGoingToSleep;
855
856 /**
857 * We don't want to allow the device to go to sleep while in the process
858 * of launching an activity. This is primarily to allow alarm intent
859 * receivers to launch an activity and get that to run before the device
860 * goes back to sleep.
861 */
862 PowerManager.WakeLock mLaunchingActivity;
863
864 /**
865 * Task identifier that activities are currently being started
866 * in. Incremented each time a new task is created.
867 * todo: Replace this with a TokenSpace class that generates non-repeating
868 * integers that won't wrap.
869 */
870 int mCurTask = 1;
871
872 /**
873 * Current sequence id for oom_adj computation traversal.
874 */
875 int mAdjSeq = 0;
876
877 /**
878 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
879 * is set, indicating the user wants processes started in such a way
880 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
881 * running in each process (thus no pre-initialized process, etc).
882 */
883 boolean mSimpleProcessManagement = false;
884
885 /**
886 * System monitoring: number of processes that died since the last
887 * N procs were started.
888 */
889 int[] mProcDeaths = new int[20];
890
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700891 /**
892 * This is set if we had to do a delayed dexopt of an app before launching
893 * it, to increasing the ANR timeouts in that case.
894 */
895 boolean mDidDexOpt;
896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 String mDebugApp = null;
898 boolean mWaitForDebugger = false;
899 boolean mDebugTransient = false;
900 String mOrigDebugApp = null;
901 boolean mOrigWaitForDebugger = false;
902 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700903 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700905 final RemoteCallbackList<IActivityWatcher> mWatchers
906 = new RemoteCallbackList<IActivityWatcher>();
907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 /**
909 * Callback of last caller to {@link #requestPss}.
910 */
911 Runnable mRequestPssCallback;
912
913 /**
914 * Remaining processes for which we are waiting results from the last
915 * call to {@link #requestPss}.
916 */
917 final ArrayList<ProcessRecord> mRequestPssList
918 = new ArrayList<ProcessRecord>();
919
920 /**
921 * Runtime statistics collection thread. This object's lock is used to
922 * protect all related state.
923 */
924 final Thread mProcessStatsThread;
925
926 /**
927 * Used to collect process stats when showing not responding dialog.
928 * Protected by mProcessStatsThread.
929 */
930 final ProcessStats mProcessStats = new ProcessStats(
931 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700932 final AtomicLong mLastCpuTime = new AtomicLong(0);
933 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 long mLastWriteTime = 0;
936
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700937 long mInitialStartTime = 0;
938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 /**
940 * Set to true after the system has finished booting.
941 */
942 boolean mBooted = false;
943
944 int mProcessLimit = 0;
945
946 WindowManagerService mWindowManager;
947
948 static ActivityManagerService mSelf;
949 static ActivityThread mSystemThread;
950
951 private final class AppDeathRecipient implements IBinder.DeathRecipient {
952 final ProcessRecord mApp;
953 final int mPid;
954 final IApplicationThread mAppThread;
955
956 AppDeathRecipient(ProcessRecord app, int pid,
957 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800958 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 TAG, "New death recipient " + this
960 + " for thread " + thread.asBinder());
961 mApp = app;
962 mPid = pid;
963 mAppThread = thread;
964 }
965
966 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800967 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 TAG, "Death received in " + this
969 + " for thread " + mAppThread.asBinder());
970 removeRequestedPss(mApp);
971 synchronized(ActivityManagerService.this) {
972 appDiedLocked(mApp, mPid, mAppThread);
973 }
974 }
975 }
976
977 static final int SHOW_ERROR_MSG = 1;
978 static final int SHOW_NOT_RESPONDING_MSG = 2;
979 static final int SHOW_FACTORY_ERROR_MSG = 3;
980 static final int UPDATE_CONFIGURATION_MSG = 4;
981 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
982 static final int WAIT_FOR_DEBUGGER_MSG = 6;
983 static final int BROADCAST_INTENT_MSG = 7;
984 static final int BROADCAST_TIMEOUT_MSG = 8;
985 static final int PAUSE_TIMEOUT_MSG = 9;
986 static final int IDLE_TIMEOUT_MSG = 10;
987 static final int IDLE_NOW_MSG = 11;
988 static final int SERVICE_TIMEOUT_MSG = 12;
989 static final int UPDATE_TIME_ZONE = 13;
990 static final int SHOW_UID_ERROR_MSG = 14;
991 static final int IM_FEELING_LUCKY_MSG = 15;
992 static final int LAUNCH_TIMEOUT_MSG = 16;
993 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 static final int RESUME_TOP_ACTIVITY_MSG = 19;
995 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700996 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700997 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800998 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999
1000 AlertDialog mUidAlert;
1001
1002 final Handler mHandler = new Handler() {
1003 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001004 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 //}
1006
1007 public void handleMessage(Message msg) {
1008 switch (msg.what) {
1009 case SHOW_ERROR_MSG: {
1010 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 synchronized (ActivityManagerService.this) {
1012 ProcessRecord proc = (ProcessRecord)data.get("app");
1013 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001014 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 return;
1016 }
1017 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001018 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001019 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 d.show();
1021 proc.crashDialog = d;
1022 } else {
1023 // The device is asleep, so just pretend that the user
1024 // saw a crash dialog and hit "force quit".
1025 res.set(0);
1026 }
1027 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001028
1029 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 } break;
1031 case SHOW_NOT_RESPONDING_MSG: {
1032 synchronized (ActivityManagerService.this) {
1033 HashMap data = (HashMap) msg.obj;
1034 ProcessRecord proc = (ProcessRecord)data.get("app");
1035 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001036 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 return;
1038 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001039
1040 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1041 null, null, 0, null, null, null,
1042 false, false, MY_PID, Process.SYSTEM_UID);
1043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1045 mContext, proc, (HistoryRecord)data.get("activity"));
1046 d.show();
1047 proc.anrDialog = d;
1048 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001049
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001050 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 } break;
1052 case SHOW_FACTORY_ERROR_MSG: {
1053 Dialog d = new FactoryErrorDialog(
1054 mContext, msg.getData().getCharSequence("msg"));
1055 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001056 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 } break;
1058 case UPDATE_CONFIGURATION_MSG: {
1059 final ContentResolver resolver = mContext.getContentResolver();
1060 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1061 } break;
1062 case GC_BACKGROUND_PROCESSES_MSG: {
1063 synchronized (ActivityManagerService.this) {
1064 performAppGcsIfAppropriateLocked();
1065 }
1066 } break;
1067 case WAIT_FOR_DEBUGGER_MSG: {
1068 synchronized (ActivityManagerService.this) {
1069 ProcessRecord app = (ProcessRecord)msg.obj;
1070 if (msg.arg1 != 0) {
1071 if (!app.waitedForDebugger) {
1072 Dialog d = new AppWaitingForDebuggerDialog(
1073 ActivityManagerService.this,
1074 mContext, app);
1075 app.waitDialog = d;
1076 app.waitedForDebugger = true;
1077 d.show();
1078 }
1079 } else {
1080 if (app.waitDialog != null) {
1081 app.waitDialog.dismiss();
1082 app.waitDialog = null;
1083 }
1084 }
1085 }
1086 } break;
1087 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001088 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 TAG, "Received BROADCAST_INTENT_MSG");
1090 processNextBroadcast(true);
1091 } break;
1092 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001093 if (mDidDexOpt) {
1094 mDidDexOpt = false;
1095 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1096 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1097 return;
1098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 broadcastTimeout();
1100 } break;
1101 case PAUSE_TIMEOUT_MSG: {
1102 IBinder token = (IBinder)msg.obj;
1103 // We don't at this point know if the activity is fullscreen,
1104 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001105 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 activityPaused(token, null, true);
1107 } break;
1108 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001109 if (mDidDexOpt) {
1110 mDidDexOpt = false;
1111 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1112 nmsg.obj = msg.obj;
1113 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1114 return;
1115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 // We don't at this point know if the activity is fullscreen,
1117 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001118 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001119 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001120 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 } break;
1122 case DESTROY_TIMEOUT_MSG: {
1123 IBinder token = (IBinder)msg.obj;
1124 // We don't at this point know if the activity is fullscreen,
1125 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001126 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 activityDestroyed(token);
1128 } break;
1129 case IDLE_NOW_MSG: {
1130 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001131 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 } break;
1133 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001134 if (mDidDexOpt) {
1135 mDidDexOpt = false;
1136 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1137 nmsg.obj = msg.obj;
1138 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1139 return;
1140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 serviceTimeout((ProcessRecord)msg.obj);
1142 } break;
1143 case UPDATE_TIME_ZONE: {
1144 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001145 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1146 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 if (r.thread != null) {
1148 try {
1149 r.thread.updateTimeZone();
1150 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001151 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 }
1153 }
1154 }
1155 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001156 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 case SHOW_UID_ERROR_MSG: {
1158 // XXX This is a temporary dialog, no need to localize.
1159 AlertDialog d = new BaseErrorDialog(mContext);
1160 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1161 d.setCancelable(false);
1162 d.setTitle("System UIDs Inconsistent");
1163 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1164 d.setButton("I'm Feeling Lucky",
1165 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1166 mUidAlert = d;
1167 d.show();
1168 } break;
1169 case IM_FEELING_LUCKY_MSG: {
1170 if (mUidAlert != null) {
1171 mUidAlert.dismiss();
1172 mUidAlert = null;
1173 }
1174 } break;
1175 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001176 if (mDidDexOpt) {
1177 mDidDexOpt = false;
1178 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1179 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1180 return;
1181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 synchronized (ActivityManagerService.this) {
1183 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001184 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 mLaunchingActivity.release();
1186 }
1187 }
1188 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 case RESUME_TOP_ACTIVITY_MSG: {
1190 synchronized (ActivityManagerService.this) {
1191 resumeTopActivityLocked(null);
1192 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001193 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001195 if (mDidDexOpt) {
1196 mDidDexOpt = false;
1197 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1198 nmsg.obj = msg.obj;
1199 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1200 return;
1201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 ProcessRecord app = (ProcessRecord)msg.obj;
1203 synchronized (ActivityManagerService.this) {
1204 processStartTimedOutLocked(app);
1205 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001206 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001207 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1208 synchronized (ActivityManagerService.this) {
1209 doPendingActivityLaunchesLocked(true);
1210 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001211 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001212 case KILL_APPLICATION_MSG: {
1213 synchronized (ActivityManagerService.this) {
1214 int uid = msg.arg1;
1215 boolean restart = (msg.arg2 == 1);
1216 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001217 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001218 }
1219 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001220 case FINALIZE_PENDING_INTENT_MSG: {
1221 ((PendingIntentRecord)msg.obj).completeFinalize();
1222 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 }
1224 }
1225 };
1226
1227 public static void setSystemProcess() {
1228 try {
1229 ActivityManagerService m = mSelf;
1230
1231 ServiceManager.addService("activity", m);
1232 ServiceManager.addService("meminfo", new MemBinder(m));
1233 if (MONITOR_CPU_USAGE) {
1234 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 ServiceManager.addService("permission", new PermissionController(m));
1237
1238 ApplicationInfo info =
1239 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001240 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001241 mSystemThread.installSystemApplicationInfo(info);
1242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 synchronized (mSelf) {
1244 ProcessRecord app = mSelf.newProcessRecordLocked(
1245 mSystemThread.getApplicationThread(), info,
1246 info.processName);
1247 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001248 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 app.maxAdj = SYSTEM_ADJ;
1250 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1251 synchronized (mSelf.mPidsSelfLocked) {
1252 mSelf.mPidsSelfLocked.put(app.pid, app);
1253 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001254 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 }
1256 } catch (PackageManager.NameNotFoundException e) {
1257 throw new RuntimeException(
1258 "Unable to find android system package", e);
1259 }
1260 }
1261
1262 public void setWindowManager(WindowManagerService wm) {
1263 mWindowManager = wm;
1264 }
1265
1266 public static final Context main(int factoryTest) {
1267 AThread thr = new AThread();
1268 thr.start();
1269
1270 synchronized (thr) {
1271 while (thr.mService == null) {
1272 try {
1273 thr.wait();
1274 } catch (InterruptedException e) {
1275 }
1276 }
1277 }
1278
1279 ActivityManagerService m = thr.mService;
1280 mSelf = m;
1281 ActivityThread at = ActivityThread.systemMain();
1282 mSystemThread = at;
1283 Context context = at.getSystemContext();
1284 m.mContext = context;
1285 m.mFactoryTest = factoryTest;
1286 PowerManager pm =
1287 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1288 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1289 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1290 m.mLaunchingActivity.setReferenceCounted(false);
1291
1292 m.mBatteryStatsService.publish(context);
1293 m.mUsageStatsService.publish(context);
1294
1295 synchronized (thr) {
1296 thr.mReady = true;
1297 thr.notifyAll();
1298 }
1299
1300 m.startRunning(null, null, null, null);
1301
1302 return context;
1303 }
1304
1305 public static ActivityManagerService self() {
1306 return mSelf;
1307 }
1308
1309 static class AThread extends Thread {
1310 ActivityManagerService mService;
1311 boolean mReady = false;
1312
1313 public AThread() {
1314 super("ActivityManager");
1315 }
1316
1317 public void run() {
1318 Looper.prepare();
1319
1320 android.os.Process.setThreadPriority(
1321 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1322
1323 ActivityManagerService m = new ActivityManagerService();
1324
1325 synchronized (this) {
1326 mService = m;
1327 notifyAll();
1328 }
1329
1330 synchronized (this) {
1331 while (!mReady) {
1332 try {
1333 wait();
1334 } catch (InterruptedException e) {
1335 }
1336 }
1337 }
1338
1339 Looper.loop();
1340 }
1341 }
1342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 static class MemBinder extends Binder {
1344 ActivityManagerService mActivityManagerService;
1345 MemBinder(ActivityManagerService activityManagerService) {
1346 mActivityManagerService = activityManagerService;
1347 }
1348
1349 @Override
1350 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1351 ActivityManagerService service = mActivityManagerService;
1352 ArrayList<ProcessRecord> procs;
1353 synchronized (mActivityManagerService) {
1354 if (args != null && args.length > 0
1355 && args[0].charAt(0) != '-') {
1356 procs = new ArrayList<ProcessRecord>();
1357 int pid = -1;
1358 try {
1359 pid = Integer.parseInt(args[0]);
1360 } catch (NumberFormatException e) {
1361
1362 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001363 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1364 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 if (proc.pid == pid) {
1366 procs.add(proc);
1367 } else if (proc.processName.equals(args[0])) {
1368 procs.add(proc);
1369 }
1370 }
1371 if (procs.size() <= 0) {
1372 pw.println("No process found for: " + args[0]);
1373 return;
1374 }
1375 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001376 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 }
1378 }
1379 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1380 }
1381 }
1382
1383 static class CpuBinder extends Binder {
1384 ActivityManagerService mActivityManagerService;
1385 CpuBinder(ActivityManagerService activityManagerService) {
1386 mActivityManagerService = activityManagerService;
1387 }
1388
1389 @Override
1390 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1391 synchronized (mActivityManagerService.mProcessStatsThread) {
1392 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1393 }
1394 }
1395 }
1396
1397 private ActivityManagerService() {
1398 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1399 if (v != null && Integer.getInteger(v) != 0) {
1400 mSimpleProcessManagement = true;
1401 }
1402 v = System.getenv("ANDROID_DEBUG_APP");
1403 if (v != null) {
1404 mSimpleProcessManagement = true;
1405 }
1406
Joe Onorato8a9b2202010-02-26 18:56:32 -08001407 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 File dataDir = Environment.getDataDirectory();
1410 File systemDir = new File(dataDir, "system");
1411 systemDir.mkdirs();
1412 mBatteryStatsService = new BatteryStatsService(new File(
1413 systemDir, "batterystats.bin").toString());
1414 mBatteryStatsService.getActiveStatistics().readLocked();
1415 mBatteryStatsService.getActiveStatistics().writeLocked();
1416
1417 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001418 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419
Jack Palevichb90d28c2009-07-22 15:35:24 -07001420 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1421 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1422
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001423 mConfiguration.setToDefaults();
1424 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 mProcessStats.init();
1426
1427 // Add ourself to the Watchdog monitors.
1428 Watchdog.getInstance().addMonitor(this);
1429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 mProcessStatsThread = new Thread("ProcessStats") {
1431 public void run() {
1432 while (true) {
1433 try {
1434 try {
1435 synchronized(this) {
1436 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001437 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001439 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 // + ", write delay=" + nextWriteDelay);
1441 if (nextWriteDelay < nextCpuDelay) {
1442 nextCpuDelay = nextWriteDelay;
1443 }
1444 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001445 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 this.wait(nextCpuDelay);
1447 }
1448 }
1449 } catch (InterruptedException e) {
1450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 updateCpuStatsNow();
1452 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001453 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 }
1455 }
1456 }
1457 };
1458 mProcessStatsThread.start();
1459 }
1460
1461 @Override
1462 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1463 throws RemoteException {
1464 try {
1465 return super.onTransact(code, data, reply, flags);
1466 } catch (RuntimeException e) {
1467 // The activity manager only throws security exceptions, so let's
1468 // log all others.
1469 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001470 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 }
1472 throw e;
1473 }
1474 }
1475
1476 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001477 final long now = SystemClock.uptimeMillis();
1478 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1479 return;
1480 }
1481 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1482 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 mProcessStatsThread.notify();
1484 }
1485 }
1486 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 void updateCpuStatsNow() {
1489 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001490 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 final long now = SystemClock.uptimeMillis();
1492 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001495 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1496 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 haveNewCpuStats = true;
1498 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001499 //Slog.i(TAG, mProcessStats.printCurrentState());
1500 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 // + mProcessStats.getTotalCpuPercent() + "%");
1502
Joe Onorato8a9b2202010-02-26 18:56:32 -08001503 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 if ("true".equals(SystemProperties.get("events.cpu"))) {
1505 int user = mProcessStats.getLastUserTime();
1506 int system = mProcessStats.getLastSystemTime();
1507 int iowait = mProcessStats.getLastIoWaitTime();
1508 int irq = mProcessStats.getLastIrqTime();
1509 int softIrq = mProcessStats.getLastSoftIrqTime();
1510 int idle = mProcessStats.getLastIdleTime();
1511
1512 int total = user + system + iowait + irq + softIrq + idle;
1513 if (total == 0) total = 1;
1514
Doug Zongker2bec3d42009-12-04 12:52:44 -08001515 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 ((user+system+iowait+irq+softIrq) * 100) / total,
1517 (user * 100) / total,
1518 (system * 100) / total,
1519 (iowait * 100) / total,
1520 (irq * 100) / total,
1521 (softIrq * 100) / total);
1522 }
1523 }
1524
Amith Yamasanie43530a2009-08-21 13:11:37 -07001525 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001526 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001527 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 synchronized(mPidsSelfLocked) {
1529 if (haveNewCpuStats) {
1530 if (mBatteryStatsService.isOnBattery()) {
1531 final int N = mProcessStats.countWorkingStats();
1532 for (int i=0; i<N; i++) {
1533 ProcessStats.Stats st
1534 = mProcessStats.getWorkingStats(i);
1535 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1536 if (pr != null) {
1537 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1538 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001539 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001540 } else {
1541 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001542 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001543 if (ps != null) {
1544 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001545 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001546 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 }
1548 }
1549 }
1550 }
1551 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1554 mLastWriteTime = now;
1555 mBatteryStatsService.getActiveStatistics().writeLocked();
1556 }
1557 }
1558 }
1559 }
1560
1561 /**
1562 * Initialize the application bind args. These are passed to each
1563 * process when the bindApplication() IPC is sent to the process. They're
1564 * lazily setup to make sure the services are running when they're asked for.
1565 */
1566 private HashMap<String, IBinder> getCommonServicesLocked() {
1567 if (mAppBindArgs == null) {
1568 mAppBindArgs = new HashMap<String, IBinder>();
1569
1570 // Setup the application init args
1571 mAppBindArgs.put("package", ServiceManager.getService("package"));
1572 mAppBindArgs.put("window", ServiceManager.getService("window"));
1573 mAppBindArgs.put(Context.ALARM_SERVICE,
1574 ServiceManager.getService(Context.ALARM_SERVICE));
1575 }
1576 return mAppBindArgs;
1577 }
1578
1579 private final void setFocusedActivityLocked(HistoryRecord r) {
1580 if (mFocusedActivity != r) {
1581 mFocusedActivity = r;
1582 mWindowManager.setFocusedApp(r, true);
1583 }
1584 }
1585
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001586 private final void updateLruProcessLocked(ProcessRecord app,
1587 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001589 int lrui = mLruProcesses.indexOf(app);
1590 if (lrui >= 0) mLruProcesses.remove(lrui);
1591
1592 int i = mLruProcesses.size()-1;
1593 int skipTop = 0;
1594
1595 // compute the new weight for this process.
1596 if (updateActivityTime) {
1597 app.lastActivityTime = SystemClock.uptimeMillis();
1598 }
1599 if (app.activities.size() > 0) {
1600 // If this process has activities, we more strongly want to keep
1601 // it around.
1602 app.lruWeight = app.lastActivityTime;
1603 } else if (app.pubProviders.size() > 0) {
1604 // If this process contains content providers, we want to keep
1605 // it a little more strongly.
1606 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1607 // Also don't let it kick out the first few "real" hidden processes.
1608 skipTop = MIN_HIDDEN_APPS;
1609 } else {
1610 // If this process doesn't have activities, we less strongly
1611 // want to keep it around, and generally want to avoid getting
1612 // in front of any very recently used activities.
1613 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1614 // Also don't let it kick out the first few "real" hidden processes.
1615 skipTop = MIN_HIDDEN_APPS;
1616 }
1617 while (i >= 0) {
1618 ProcessRecord p = mLruProcesses.get(i);
1619 // If this app shouldn't be in front of the first N background
1620 // apps, then skip over that many that are currently hidden.
1621 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1622 skipTop--;
1623 }
1624 if (p.lruWeight <= app.lruWeight){
1625 mLruProcesses.add(i+1, app);
1626 break;
1627 }
1628 i--;
1629 }
1630 if (i < 0) {
1631 mLruProcesses.add(0, app);
1632 }
1633
Joe Onorato8a9b2202010-02-26 18:56:32 -08001634 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 if (oomAdj) {
1636 updateOomAdjLocked();
1637 }
1638 }
1639
1640 private final boolean updateLRUListLocked(HistoryRecord r) {
1641 final boolean hadit = mLRUActivities.remove(r);
1642 mLRUActivities.add(r);
1643 return hadit;
1644 }
1645
1646 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1647 int i = mHistory.size()-1;
1648 while (i >= 0) {
1649 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1650 if (!r.finishing && r != notTop) {
1651 return r;
1652 }
1653 i--;
1654 }
1655 return null;
1656 }
1657
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001658 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1659 int i = mHistory.size()-1;
1660 while (i >= 0) {
1661 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1662 if (!r.finishing && !r.delayedResume && r != notTop) {
1663 return r;
1664 }
1665 i--;
1666 }
1667 return null;
1668 }
1669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 /**
1671 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001672 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 *
1674 * @param token If non-null, any history records matching this token will be skipped.
1675 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1676 *
1677 * @return Returns the HistoryRecord of the next activity on the stack.
1678 */
1679 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1680 int i = mHistory.size()-1;
1681 while (i >= 0) {
1682 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1683 // Note: the taskId check depends on real taskId fields being non-zero
1684 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1685 return r;
1686 }
1687 i--;
1688 }
1689 return null;
1690 }
1691
1692 private final ProcessRecord getProcessRecordLocked(
1693 String processName, int uid) {
1694 if (uid == Process.SYSTEM_UID) {
1695 // The system gets to run in any process. If there are multiple
1696 // processes with the same uid, just pick the first (this
1697 // should never happen).
1698 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1699 processName);
1700 return procs != null ? procs.valueAt(0) : null;
1701 }
1702 ProcessRecord proc = mProcessNames.get(processName, uid);
1703 return proc;
1704 }
1705
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001706 private void ensurePackageDexOpt(String packageName) {
1707 IPackageManager pm = ActivityThread.getPackageManager();
1708 try {
1709 if (pm.performDexOpt(packageName)) {
1710 mDidDexOpt = true;
1711 }
1712 } catch (RemoteException e) {
1713 }
1714 }
1715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 private boolean isNextTransitionForward() {
1717 int transit = mWindowManager.getPendingAppTransition();
1718 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1719 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1720 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1721 }
1722
1723 private final boolean realStartActivityLocked(HistoryRecord r,
1724 ProcessRecord app, boolean andResume, boolean checkConfig)
1725 throws RemoteException {
1726
1727 r.startFreezingScreenLocked(app, 0);
1728 mWindowManager.setAppVisibility(r, true);
1729
1730 // Have the window manager re-evaluate the orientation of
1731 // the screen based on the new activity order. Note that
1732 // as a result of this, it can call back into the activity
1733 // manager with a new orientation. We don't care about that,
1734 // because the activity is not currently running so we are
1735 // just restarting it anyway.
1736 if (checkConfig) {
1737 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001738 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 r.mayFreezeScreenLocked(app) ? r : null);
1740 updateConfigurationLocked(config, r);
1741 }
1742
1743 r.app = app;
1744
Joe Onorato8a9b2202010-02-26 18:56:32 -08001745 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746
1747 int idx = app.activities.indexOf(r);
1748 if (idx < 0) {
1749 app.activities.add(r);
1750 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001751 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752
1753 try {
1754 if (app.thread == null) {
1755 throw new RemoteException();
1756 }
1757 List<ResultInfo> results = null;
1758 List<Intent> newIntents = null;
1759 if (andResume) {
1760 results = r.results;
1761 newIntents = r.newIntents;
1762 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001763 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 + " icicle=" + r.icicle
1765 + " with results=" + results + " newIntents=" + newIntents
1766 + " andResume=" + andResume);
1767 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001768 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 System.identityHashCode(r),
1770 r.task.taskId, r.shortComponentName);
1771 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001772 if (r.isHomeActivity) {
1773 mHomeProcess = app;
1774 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001775 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001777 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001778 r.info, r.icicle, results, newIntents, !andResume,
1779 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 } catch (RemoteException e) {
1781 if (r.launchFailed) {
1782 // This is the second time we failed -- finish activity
1783 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001784 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 + r.intent.getComponent().flattenToShortString()
1786 + ", giving up", e);
1787 appDiedLocked(app, app.pid, app.thread);
1788 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1789 "2nd-crash");
1790 return false;
1791 }
1792
1793 // This is the first time we failed -- restart process and
1794 // retry.
1795 app.activities.remove(r);
1796 throw e;
1797 }
1798
1799 r.launchFailed = false;
1800 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001801 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 + " being launched, but already in LRU list");
1803 }
1804
1805 if (andResume) {
1806 // As part of the process of launching, ActivityThread also performs
1807 // a resume.
1808 r.state = ActivityState.RESUMED;
1809 r.icicle = null;
1810 r.haveState = false;
1811 r.stopped = false;
1812 mResumedActivity = r;
1813 r.task.touchActiveTime();
1814 completeResumeLocked(r);
1815 pauseIfSleepingLocked();
1816 } else {
1817 // This activity is not starting in the resumed state... which
1818 // should look like we asked it to pause+stop (but remain visible),
1819 // and it has done so and reported back the current icicle and
1820 // other state.
1821 r.state = ActivityState.STOPPED;
1822 r.stopped = true;
1823 }
1824
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001825 // Launch the new version setup screen if needed. We do this -after-
1826 // launching the initial activity (that is, home), so that it can have
1827 // a chance to initialize itself while in the background, making the
1828 // switch back to it faster and look better.
1829 startSetupActivityLocked();
1830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 return true;
1832 }
1833
1834 private final void startSpecificActivityLocked(HistoryRecord r,
1835 boolean andResume, boolean checkConfig) {
1836 // Is this activity's application already running?
1837 ProcessRecord app = getProcessRecordLocked(r.processName,
1838 r.info.applicationInfo.uid);
1839
1840 if (r.startTime == 0) {
1841 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001842 if (mInitialStartTime == 0) {
1843 mInitialStartTime = r.startTime;
1844 }
1845 } else if (mInitialStartTime == 0) {
1846 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 }
1848
1849 if (app != null && app.thread != null) {
1850 try {
1851 realStartActivityLocked(r, app, andResume, checkConfig);
1852 return;
1853 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001854 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 + r.intent.getComponent().flattenToShortString(), e);
1856 }
1857
1858 // If a dead object exception was thrown -- fall through to
1859 // restart the application.
1860 }
1861
1862 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001863 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 }
1865
1866 private final ProcessRecord startProcessLocked(String processName,
1867 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001868 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1870 // We don't have to do anything more if:
1871 // (1) There is an existing application record; and
1872 // (2) The caller doesn't think it is dead, OR there is no thread
1873 // object attached to it so we know it couldn't have crashed; and
1874 // (3) There is a pid assigned to it, so it is either starting or
1875 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001876 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 + " app=" + app + " knownToBeDead=" + knownToBeDead
1878 + " thread=" + (app != null ? app.thread : null)
1879 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001880 if (app != null && app.pid > 0) {
1881 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001882 // We already have the app running, or are waiting for it to
1883 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001884 return app;
1885 } else {
1886 // An application record is attached to a previous process,
1887 // clean it up now.
1888 handleAppDiedLocked(app, true);
1889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 String hostingNameStr = hostingName != null
1893 ? hostingName.flattenToShortString() : null;
1894
1895 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1896 // If we are in the background, then check to see if this process
1897 // is bad. If so, we will just silently fail.
1898 if (mBadProcesses.get(info.processName, info.uid) != null) {
1899 return null;
1900 }
1901 } else {
1902 // When the user is explicitly starting a process, then clear its
1903 // crash count so that we won't make it bad until they see at
1904 // least one crash dialog again, and make the process good again
1905 // if it had been bad.
1906 mProcessCrashTimes.remove(info.processName, info.uid);
1907 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001908 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 info.processName);
1910 mBadProcesses.remove(info.processName, info.uid);
1911 if (app != null) {
1912 app.bad = false;
1913 }
1914 }
1915 }
1916
1917 if (app == null) {
1918 app = newProcessRecordLocked(null, info, processName);
1919 mProcessNames.put(processName, info.uid, app);
1920 } else {
1921 // If this is a new package in the process, add the package to the list
1922 app.addPackage(info.packageName);
1923 }
1924
1925 // If the system is not ready yet, then hold off on starting this
1926 // process until it is.
1927 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001928 && !isAllowedWhileBooting(info)
1929 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 if (!mProcessesOnHold.contains(app)) {
1931 mProcessesOnHold.add(app);
1932 }
1933 return app;
1934 }
1935
1936 startProcessLocked(app, hostingType, hostingNameStr);
1937 return (app.pid != 0) ? app : null;
1938 }
1939
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001940 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1941 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1942 }
1943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001944 private final void startProcessLocked(ProcessRecord app,
1945 String hostingType, String hostingNameStr) {
1946 if (app.pid > 0 && app.pid != MY_PID) {
1947 synchronized (mPidsSelfLocked) {
1948 mPidsSelfLocked.remove(app.pid);
1949 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1950 }
1951 app.pid = 0;
1952 }
1953
1954 mProcessesOnHold.remove(app);
1955
1956 updateCpuStats();
1957
1958 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1959 mProcDeaths[0] = 0;
1960
1961 try {
1962 int uid = app.info.uid;
1963 int[] gids = null;
1964 try {
1965 gids = mContext.getPackageManager().getPackageGids(
1966 app.info.packageName);
1967 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001968 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001969 }
1970 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1971 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1972 && mTopComponent != null
1973 && app.processName.equals(mTopComponent.getPackageName())) {
1974 uid = 0;
1975 }
1976 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1977 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1978 uid = 0;
1979 }
1980 }
1981 int debugFlags = 0;
1982 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1983 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1984 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001985 // Run the app in safe mode if its manifest requests so or the
1986 // system is booted in safe mode.
1987 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1988 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001989 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1990 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001991 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1992 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1993 }
1994 if ("1".equals(SystemProperties.get("debug.assert"))) {
1995 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1996 }
1997 int pid = Process.start("android.app.ActivityThread",
1998 mSimpleProcessManagement ? app.processName : null, uid, uid,
1999 gids, debugFlags, null);
2000 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2001 synchronized (bs) {
2002 if (bs.isOnBattery()) {
2003 app.batteryStats.incStartsLocked();
2004 }
2005 }
2006
Doug Zongker2bec3d42009-12-04 12:52:44 -08002007 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002008 app.processName, hostingType,
2009 hostingNameStr != null ? hostingNameStr : "");
2010
2011 if (app.persistent) {
2012 Watchdog.getInstance().processStarted(app, app.processName, pid);
2013 }
2014
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002015 StringBuilder buf = mStringBuilder;
2016 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 buf.append("Start proc ");
2018 buf.append(app.processName);
2019 buf.append(" for ");
2020 buf.append(hostingType);
2021 if (hostingNameStr != null) {
2022 buf.append(" ");
2023 buf.append(hostingNameStr);
2024 }
2025 buf.append(": pid=");
2026 buf.append(pid);
2027 buf.append(" uid=");
2028 buf.append(uid);
2029 buf.append(" gids={");
2030 if (gids != null) {
2031 for (int gi=0; gi<gids.length; gi++) {
2032 if (gi != 0) buf.append(", ");
2033 buf.append(gids[gi]);
2034
2035 }
2036 }
2037 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002038 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039 if (pid == 0 || pid == MY_PID) {
2040 // Processes are being emulated with threads.
2041 app.pid = MY_PID;
2042 app.removed = false;
2043 mStartingProcesses.add(app);
2044 } else if (pid > 0) {
2045 app.pid = pid;
2046 app.removed = false;
2047 synchronized (mPidsSelfLocked) {
2048 this.mPidsSelfLocked.put(pid, app);
2049 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2050 msg.obj = app;
2051 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2052 }
2053 } else {
2054 app.pid = 0;
2055 RuntimeException e = new RuntimeException(
2056 "Failure starting process " + app.processName
2057 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002058 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 }
2060 } catch (RuntimeException e) {
2061 // XXX do better error recovery.
2062 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002063 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 }
2065 }
2066
2067 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2068 if (mPausingActivity != null) {
2069 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002070 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 + mPausingActivity, e);
2072 }
2073 HistoryRecord prev = mResumedActivity;
2074 if (prev == null) {
2075 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002076 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 resumeTopActivityLocked(null);
2078 return;
2079 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002080 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 mResumedActivity = null;
2082 mPausingActivity = prev;
2083 mLastPausedActivity = prev;
2084 prev.state = ActivityState.PAUSING;
2085 prev.task.touchActiveTime();
2086
2087 updateCpuStats();
2088
2089 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002090 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002092 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 System.identityHashCode(prev),
2094 prev.shortComponentName);
2095 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2096 prev.configChangeFlags);
2097 updateUsageStats(prev, false);
2098 } catch (Exception e) {
2099 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002100 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002101 mPausingActivity = null;
2102 mLastPausedActivity = null;
2103 }
2104 } else {
2105 mPausingActivity = null;
2106 mLastPausedActivity = null;
2107 }
2108
2109 // If we are not going to sleep, we want to ensure the device is
2110 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002111 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002112 mLaunchingActivity.acquire();
2113 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2114 // To be safe, don't allow the wake lock to be held for too long.
2115 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2116 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2117 }
2118 }
2119
2120
2121 if (mPausingActivity != null) {
2122 // Have the window manager pause its key dispatching until the new
2123 // activity has started. If we're pausing the activity just because
2124 // the screen is being turned off and the UI is sleeping, don't interrupt
2125 // key dispatch; the same activity will pick it up again on wakeup.
2126 if (!uiSleeping) {
2127 prev.pauseKeyDispatchingLocked();
2128 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002129 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 }
2131
2132 // Schedule a pause timeout in case the app doesn't respond.
2133 // We don't give it much time because this directly impacts the
2134 // responsiveness seen by the user.
2135 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2136 msg.obj = prev;
2137 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002138 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 } else {
2140 // This activity failed to schedule the
2141 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002142 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 resumeTopActivityLocked(null);
2144 }
2145 }
2146
2147 private final void completePauseLocked() {
2148 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002149 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002150
2151 if (prev != null) {
2152 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002153 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2155 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002156 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 if (prev.waitingVisible) {
2158 prev.waitingVisible = false;
2159 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002160 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002161 TAG, "Complete pause, no longer waiting: " + prev);
2162 }
2163 if (prev.configDestroy) {
2164 // The previous is being paused because the configuration
2165 // is changing, which means it is actually stopping...
2166 // To juggle the fact that we are also starting a new
2167 // instance right now, we need to first completely stop
2168 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002169 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 destroyActivityLocked(prev, true);
2171 } else {
2172 mStoppingActivities.add(prev);
2173 if (mStoppingActivities.size() > 3) {
2174 // If we already have a few activities waiting to stop,
2175 // then give up on things going idle and start clearing
2176 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002177 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 Message msg = Message.obtain();
2179 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2180 mHandler.sendMessage(msg);
2181 }
2182 }
2183 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002184 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 prev = null;
2186 }
2187 mPausingActivity = null;
2188 }
2189
Dianne Hackborn55280a92009-05-07 15:53:46 -07002190 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002191 resumeTopActivityLocked(prev);
2192 } else {
2193 if (mGoingToSleep.isHeld()) {
2194 mGoingToSleep.release();
2195 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002196 if (mShuttingDown) {
2197 notifyAll();
2198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002199 }
2200
2201 if (prev != null) {
2202 prev.resumeKeyDispatchingLocked();
2203 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002204
2205 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2206 long diff = 0;
2207 synchronized (mProcessStatsThread) {
2208 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2209 }
2210 if (diff > 0) {
2211 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2212 synchronized (bsi) {
2213 BatteryStatsImpl.Uid.Proc ps =
2214 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2215 prev.info.packageName);
2216 if (ps != null) {
2217 ps.addForegroundTimeLocked(diff);
2218 }
2219 }
2220 }
2221 }
2222 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 }
2224
2225 /**
2226 * Once we know that we have asked an application to put an activity in
2227 * the resumed state (either by launching it or explicitly telling it),
2228 * this function updates the rest of our state to match that fact.
2229 */
2230 private final void completeResumeLocked(HistoryRecord next) {
2231 next.idle = false;
2232 next.results = null;
2233 next.newIntents = null;
2234
2235 // schedule an idle timeout in case the app doesn't do it for us.
2236 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2237 msg.obj = next;
2238 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2239
2240 if (false) {
2241 // The activity was never told to pause, so just keep
2242 // things going as-is. To maintain our own state,
2243 // we need to emulate it coming back and saying it is
2244 // idle.
2245 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2246 msg.obj = next;
2247 mHandler.sendMessage(msg);
2248 }
2249
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002250 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 next.thumbnail = null;
2253 setFocusedActivityLocked(next);
2254 next.resumeKeyDispatchingLocked();
2255 ensureActivitiesVisibleLocked(null, 0);
2256 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002257 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002258
2259 // Mark the point when the activity is resuming
2260 // TODO: To be more accurate, the mark should be before the onCreate,
2261 // not after the onResume. But for subsequent starts, onResume is fine.
2262 if (next.app != null) {
2263 synchronized (mProcessStatsThread) {
2264 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2265 }
2266 } else {
2267 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 }
2270
2271 /**
2272 * Make sure that all activities that need to be visible (that is, they
2273 * currently can be seen by the user) actually are.
2274 */
2275 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2276 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002277 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278 TAG, "ensureActivitiesVisible behind " + top
2279 + " configChanges=0x" + Integer.toHexString(configChanges));
2280
2281 // If the top activity is not fullscreen, then we need to
2282 // make sure any activities under it are now visible.
2283 final int count = mHistory.size();
2284 int i = count-1;
2285 while (mHistory.get(i) != top) {
2286 i--;
2287 }
2288 HistoryRecord r;
2289 boolean behindFullscreen = false;
2290 for (; i>=0; i--) {
2291 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002292 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 TAG, "Make visible? " + r + " finishing=" + r.finishing
2294 + " state=" + r.state);
2295 if (r.finishing) {
2296 continue;
2297 }
2298
2299 final boolean doThisProcess = onlyThisProcess == null
2300 || onlyThisProcess.equals(r.processName);
2301
2302 // First: if this is not the current activity being started, make
2303 // sure it matches the current configuration.
2304 if (r != starting && doThisProcess) {
2305 ensureActivityConfigurationLocked(r, 0);
2306 }
2307
2308 if (r.app == null || r.app.thread == null) {
2309 if (onlyThisProcess == null
2310 || onlyThisProcess.equals(r.processName)) {
2311 // This activity needs to be visible, but isn't even
2312 // running... get it started, but don't resume it
2313 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002314 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 TAG, "Start and freeze screen for " + r);
2316 if (r != starting) {
2317 r.startFreezingScreenLocked(r.app, configChanges);
2318 }
2319 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002320 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002321 TAG, "Starting and making visible: " + r);
2322 mWindowManager.setAppVisibility(r, true);
2323 }
2324 if (r != starting) {
2325 startSpecificActivityLocked(r, false, false);
2326 }
2327 }
2328
2329 } else if (r.visible) {
2330 // If this activity is already visible, then there is nothing
2331 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002332 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 TAG, "Skipping: already visible at " + r);
2334 r.stopFreezingScreenLocked(false);
2335
2336 } else if (onlyThisProcess == null) {
2337 // This activity is not currently visible, but is running.
2338 // Tell it to become visible.
2339 r.visible = true;
2340 if (r.state != ActivityState.RESUMED && r != starting) {
2341 // If this activity is paused, tell it
2342 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002343 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002344 TAG, "Making visible and scheduling visibility: " + r);
2345 try {
2346 mWindowManager.setAppVisibility(r, true);
2347 r.app.thread.scheduleWindowVisibility(r, true);
2348 r.stopFreezingScreenLocked(false);
2349 } catch (Exception e) {
2350 // Just skip on any failure; we'll make it
2351 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002352 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 + r.intent.getComponent(), e);
2354 }
2355 }
2356 }
2357
2358 // Aggregate current change flags.
2359 configChanges |= r.configChangeFlags;
2360
2361 if (r.fullscreen) {
2362 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002363 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002364 TAG, "Stopping: fullscreen at " + r);
2365 behindFullscreen = true;
2366 i--;
2367 break;
2368 }
2369 }
2370
2371 // Now for any activities that aren't visible to the user, make
2372 // sure they no longer are keeping the screen frozen.
2373 while (i >= 0) {
2374 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002375 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2377 + " state=" + r.state
2378 + " behindFullscreen=" + behindFullscreen);
2379 if (!r.finishing) {
2380 if (behindFullscreen) {
2381 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002382 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 TAG, "Making invisible: " + r);
2384 r.visible = false;
2385 try {
2386 mWindowManager.setAppVisibility(r, false);
2387 if ((r.state == ActivityState.STOPPING
2388 || r.state == ActivityState.STOPPED)
2389 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002390 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002391 TAG, "Scheduling invisibility: " + r);
2392 r.app.thread.scheduleWindowVisibility(r, false);
2393 }
2394 } catch (Exception e) {
2395 // Just skip on any failure; we'll make it
2396 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002397 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 + r.intent.getComponent(), e);
2399 }
2400 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002401 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 TAG, "Already invisible: " + r);
2403 }
2404 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002405 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002406 TAG, "Now behindFullscreen: " + r);
2407 behindFullscreen = true;
2408 }
2409 }
2410 i--;
2411 }
2412 }
2413
2414 /**
2415 * Version of ensureActivitiesVisible that can easily be called anywhere.
2416 */
2417 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2418 int configChanges) {
2419 HistoryRecord r = topRunningActivityLocked(null);
2420 if (r != null) {
2421 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2422 }
2423 }
2424
2425 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2426 if (resumed) {
2427 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2428 } else {
2429 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2430 }
2431 }
2432
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002433 private boolean startHomeActivityLocked() {
2434 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2435 && mTopAction == null) {
2436 // We are running in factory test mode, but unable to find
2437 // the factory test app, so just sit around displaying the
2438 // error message and don't try to start anything.
2439 return false;
2440 }
2441 Intent intent = new Intent(
2442 mTopAction,
2443 mTopData != null ? Uri.parse(mTopData) : null);
2444 intent.setComponent(mTopComponent);
2445 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2446 intent.addCategory(Intent.CATEGORY_HOME);
2447 }
2448 ActivityInfo aInfo =
2449 intent.resolveActivityInfo(mContext.getPackageManager(),
2450 STOCK_PM_FLAGS);
2451 if (aInfo != null) {
2452 intent.setComponent(new ComponentName(
2453 aInfo.applicationInfo.packageName, aInfo.name));
2454 // Don't do this if the home app is currently being
2455 // instrumented.
2456 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2457 aInfo.applicationInfo.uid);
2458 if (app == null || app.instrumentationClass == null) {
2459 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2460 startActivityLocked(null, intent, null, null, 0, aInfo,
2461 null, null, 0, 0, 0, false, false);
2462 }
2463 }
2464
2465
2466 return true;
2467 }
2468
2469 /**
2470 * Starts the "new version setup screen" if appropriate.
2471 */
2472 private void startSetupActivityLocked() {
2473 // Only do this once per boot.
2474 if (mCheckedForSetup) {
2475 return;
2476 }
2477
2478 // We will show this screen if the current one is a different
2479 // version than the last one shown, and we are not running in
2480 // low-level factory test mode.
2481 final ContentResolver resolver = mContext.getContentResolver();
2482 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2483 Settings.Secure.getInt(resolver,
2484 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2485 mCheckedForSetup = true;
2486
2487 // See if we should be showing the platform update setup UI.
2488 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2489 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2490 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2491
2492 // We don't allow third party apps to replace this.
2493 ResolveInfo ri = null;
2494 for (int i=0; ris != null && i<ris.size(); i++) {
2495 if ((ris.get(i).activityInfo.applicationInfo.flags
2496 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2497 ri = ris.get(i);
2498 break;
2499 }
2500 }
2501
2502 if (ri != null) {
2503 String vers = ri.activityInfo.metaData != null
2504 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2505 : null;
2506 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2507 vers = ri.activityInfo.applicationInfo.metaData.getString(
2508 Intent.METADATA_SETUP_VERSION);
2509 }
2510 String lastVers = Settings.Secure.getString(
2511 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2512 if (vers != null && !vers.equals(lastVers)) {
2513 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2514 intent.setComponent(new ComponentName(
2515 ri.activityInfo.packageName, ri.activityInfo.name));
2516 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2517 null, null, 0, 0, 0, false, false);
2518 }
2519 }
2520 }
2521 }
2522
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002523 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002524 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002525
2526 final int identHash = System.identityHashCode(r);
2527 updateUsageStats(r, true);
2528
2529 int i = mWatchers.beginBroadcast();
2530 while (i > 0) {
2531 i--;
2532 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2533 if (w != null) {
2534 try {
2535 w.activityResuming(identHash);
2536 } catch (RemoteException e) {
2537 }
2538 }
2539 }
2540 mWatchers.finishBroadcast();
2541 }
2542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002543 /**
2544 * Ensure that the top activity in the stack is resumed.
2545 *
2546 * @param prev The previously resumed activity, for when in the process
2547 * of pausing; can be null to call from elsewhere.
2548 *
2549 * @return Returns true if something is being resumed, or false if
2550 * nothing happened.
2551 */
2552 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2553 // Find the first activity that is not finishing.
2554 HistoryRecord next = topRunningActivityLocked(null);
2555
2556 // Remember how we'll process this pause/resume situation, and ensure
2557 // that the state is reset however we wind up proceeding.
2558 final boolean userLeaving = mUserLeaving;
2559 mUserLeaving = false;
2560
2561 if (next == null) {
2562 // There are no more activities! Let's just start up the
2563 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002564 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002565 }
2566
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002567 next.delayedResume = false;
2568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 // If the top activity is the resumed one, nothing to do.
2570 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2571 // Make sure we have executed any pending transitions, since there
2572 // should be nothing left to do at this point.
2573 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002574 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 return false;
2576 }
2577
2578 // If we are sleeping, and there is no resumed activity, and the top
2579 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002580 if ((mSleeping || mShuttingDown)
2581 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582 // Make sure we have executed any pending transitions, since there
2583 // should be nothing left to do at this point.
2584 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002585 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 return false;
2587 }
2588
2589 // The activity may be waiting for stop, but that is no longer
2590 // appropriate for it.
2591 mStoppingActivities.remove(next);
2592 mWaitingVisibleActivities.remove(next);
2593
Joe Onorato8a9b2202010-02-26 18:56:32 -08002594 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595
2596 // If we are currently pausing an activity, then don't do anything
2597 // until that is done.
2598 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002599 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 return false;
2601 }
2602
2603 // We need to start pausing the current activity so the top one
2604 // can be resumed...
2605 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002606 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 startPausingLocked(userLeaving, false);
2608 return true;
2609 }
2610
2611 if (prev != null && prev != next) {
2612 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2613 prev.waitingVisible = true;
2614 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002615 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616 TAG, "Resuming top, waiting visible to hide: " + prev);
2617 } else {
2618 // The next activity is already visible, so hide the previous
2619 // activity's windows right now so we can show the new one ASAP.
2620 // We only do this if the previous is finishing, which should mean
2621 // it is on top of the one being resumed so hiding it quickly
2622 // is good. Otherwise, we want to do the normal route of allowing
2623 // the resumed activity to be shown so we can decide if the
2624 // previous should actually be hidden depending on whether the
2625 // new one is found to be full-screen or not.
2626 if (prev.finishing) {
2627 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002628 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 + prev + ", waitingVisible="
2630 + (prev != null ? prev.waitingVisible : null)
2631 + ", nowVisible=" + next.nowVisible);
2632 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002633 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 + prev + ", waitingVisible="
2635 + (prev != null ? prev.waitingVisible : null)
2636 + ", nowVisible=" + next.nowVisible);
2637 }
2638 }
2639 }
2640
2641 // We are starting up the next activity, so tell the window manager
2642 // that the previous one will be hidden soon. This way it can know
2643 // to ignore it when computing the desired screen orientation.
2644 if (prev != null) {
2645 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002646 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002647 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002648 if (mNoAnimActivities.contains(prev)) {
2649 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2650 } else {
2651 mWindowManager.prepareAppTransition(prev.task == next.task
2652 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2653 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2654 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 mWindowManager.setAppWillBeHidden(prev);
2656 mWindowManager.setAppVisibility(prev, false);
2657 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002658 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002659 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002660 if (mNoAnimActivities.contains(next)) {
2661 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2662 } else {
2663 mWindowManager.prepareAppTransition(prev.task == next.task
2664 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2665 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002667 }
2668 if (false) {
2669 mWindowManager.setAppWillBeHidden(prev);
2670 mWindowManager.setAppVisibility(prev, false);
2671 }
2672 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002673 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002675 if (mNoAnimActivities.contains(next)) {
2676 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2677 } else {
2678 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2679 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 }
2681
2682 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002683 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684
2685 // This activity is now becoming visible.
2686 mWindowManager.setAppVisibility(next, true);
2687
2688 HistoryRecord lastResumedActivity = mResumedActivity;
2689 ActivityState lastState = next.state;
2690
2691 updateCpuStats();
2692
2693 next.state = ActivityState.RESUMED;
2694 mResumedActivity = next;
2695 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002696 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 updateLRUListLocked(next);
2698
2699 // Have the window manager re-evaluate the orientation of
2700 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002701 boolean updated;
2702 synchronized (this) {
2703 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2704 mConfiguration,
2705 next.mayFreezeScreenLocked(next.app) ? next : null);
2706 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002707 next.frozenBeforeDestroy = true;
2708 }
2709 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002711 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 // The configuration update wasn't able to keep the existing
2713 // instance of the activity, and instead started a new one.
2714 // We should be all done, but let's just make sure our activity
2715 // is still at the top and schedule another run if something
2716 // weird happened.
2717 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002718 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 "Activity config changed during resume: " + next
2720 + ", new next: " + nextNext);
2721 if (nextNext != next) {
2722 // Do over!
2723 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2724 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002725 setFocusedActivityLocked(next);
2726 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002728 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002729 return true;
2730 }
2731
2732 try {
2733 // Deliver all pending results.
2734 ArrayList a = next.results;
2735 if (a != null) {
2736 final int N = a.size();
2737 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002738 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002739 TAG, "Delivering results to " + next
2740 + ": " + a);
2741 next.app.thread.scheduleSendResult(next, a);
2742 }
2743 }
2744
2745 if (next.newIntents != null) {
2746 next.app.thread.scheduleNewIntent(next.newIntents, next);
2747 }
2748
Doug Zongker2bec3d42009-12-04 12:52:44 -08002749 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 System.identityHashCode(next),
2751 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752
2753 next.app.thread.scheduleResumeActivity(next,
2754 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002756 pauseIfSleepingLocked();
2757
2758 } catch (Exception e) {
2759 // Whoops, need to restart this activity!
2760 next.state = lastState;
2761 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002762 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 if (!next.hasBeenLaunched) {
2764 next.hasBeenLaunched = true;
2765 } else {
2766 if (SHOW_APP_STARTING_ICON) {
2767 mWindowManager.setAppStartingWindow(
2768 next, next.packageName, next.theme,
2769 next.nonLocalizedLabel,
2770 next.labelRes, next.icon, null, true);
2771 }
2772 }
2773 startSpecificActivityLocked(next, true, false);
2774 return true;
2775 }
2776
2777 // From this point on, if something goes wrong there is no way
2778 // to recover the activity.
2779 try {
2780 next.visible = true;
2781 completeResumeLocked(next);
2782 } catch (Exception e) {
2783 // If any exception gets thrown, toss away this
2784 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002785 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2787 "resume-exception");
2788 return true;
2789 }
2790
2791 // Didn't need to use the icicle, and it is now out of date.
2792 next.icicle = null;
2793 next.haveState = false;
2794 next.stopped = false;
2795
2796 } else {
2797 // Whoops, need to restart this activity!
2798 if (!next.hasBeenLaunched) {
2799 next.hasBeenLaunched = true;
2800 } else {
2801 if (SHOW_APP_STARTING_ICON) {
2802 mWindowManager.setAppStartingWindow(
2803 next, next.packageName, next.theme,
2804 next.nonLocalizedLabel,
2805 next.labelRes, next.icon, null, true);
2806 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002807 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 }
2809 startSpecificActivityLocked(next, true, true);
2810 }
2811
2812 return true;
2813 }
2814
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002815 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2816 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 final int NH = mHistory.size();
2818
2819 int addPos = -1;
2820
2821 if (!newTask) {
2822 // If starting in an existing task, find where that is...
2823 HistoryRecord next = null;
2824 boolean startIt = true;
2825 for (int i = NH-1; i >= 0; i--) {
2826 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2827 if (p.finishing) {
2828 continue;
2829 }
2830 if (p.task == r.task) {
2831 // Here it is! Now, if this is not yet visible to the
2832 // user, then just add it without starting; it will
2833 // get started when the user navigates back to it.
2834 addPos = i+1;
2835 if (!startIt) {
2836 mHistory.add(addPos, r);
2837 r.inHistory = true;
2838 r.task.numActivities++;
2839 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2840 r.info.screenOrientation, r.fullscreen);
2841 if (VALIDATE_TOKENS) {
2842 mWindowManager.validateAppTokens(mHistory);
2843 }
2844 return;
2845 }
2846 break;
2847 }
2848 if (p.fullscreen) {
2849 startIt = false;
2850 }
2851 next = p;
2852 }
2853 }
2854
2855 // Place a new activity at top of stack, so it is next to interact
2856 // with the user.
2857 if (addPos < 0) {
2858 addPos = mHistory.size();
2859 }
2860
2861 // If we are not placing the new activity frontmost, we do not want
2862 // to deliver the onUserLeaving callback to the actual frontmost
2863 // activity
2864 if (addPos < NH) {
2865 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002866 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002867 }
2868
2869 // Slot the activity into the history stack and proceed
2870 mHistory.add(addPos, r);
2871 r.inHistory = true;
2872 r.frontOfTask = newTask;
2873 r.task.numActivities++;
2874 if (NH > 0) {
2875 // We want to show the starting preview window if we are
2876 // switching to a new task, or the next activity's process is
2877 // not currently running.
2878 boolean showStartingIcon = newTask;
2879 ProcessRecord proc = r.app;
2880 if (proc == null) {
2881 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2882 }
2883 if (proc == null || proc.thread == null) {
2884 showStartingIcon = true;
2885 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002886 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002888 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2889 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2890 mNoAnimActivities.add(r);
2891 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2892 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2893 mNoAnimActivities.remove(r);
2894 } else {
2895 mWindowManager.prepareAppTransition(newTask
2896 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2897 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2898 mNoAnimActivities.remove(r);
2899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 mWindowManager.addAppToken(
2901 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2902 boolean doShow = true;
2903 if (newTask) {
2904 // Even though this activity is starting fresh, we still need
2905 // to reset it to make sure we apply affinities to move any
2906 // existing activities from other tasks in to it.
2907 // If the caller has requested that the target task be
2908 // reset, then do so.
2909 if ((r.intent.getFlags()
2910 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2911 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002912 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002913 }
2914 }
2915 if (SHOW_APP_STARTING_ICON && doShow) {
2916 // Figure out if we are transitioning from another activity that is
2917 // "has the same starting icon" as the next one. This allows the
2918 // window manager to keep the previous window it had previously
2919 // created, if it still had one.
2920 HistoryRecord prev = mResumedActivity;
2921 if (prev != null) {
2922 // We don't want to reuse the previous starting preview if:
2923 // (1) The current activity is in a different task.
2924 if (prev.task != r.task) prev = null;
2925 // (2) The current activity is already displayed.
2926 else if (prev.nowVisible) prev = null;
2927 }
2928 mWindowManager.setAppStartingWindow(
2929 r, r.packageName, r.theme, r.nonLocalizedLabel,
2930 r.labelRes, r.icon, prev, showStartingIcon);
2931 }
2932 } else {
2933 // If this is the first activity, don't do any fancy animations,
2934 // because there is nothing for it to animate on top of.
2935 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2936 r.info.screenOrientation, r.fullscreen);
2937 }
2938 if (VALIDATE_TOKENS) {
2939 mWindowManager.validateAppTokens(mHistory);
2940 }
2941
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002942 if (doResume) {
2943 resumeTopActivityLocked(null);
2944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 }
2946
2947 /**
2948 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002949 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2950 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 * an instance of that activity in the stack and, if found, finish all
2952 * activities on top of it and return the instance.
2953 *
2954 * @param newR Description of the new activity being started.
2955 * @return Returns the old activity that should be continue to be used,
2956 * or null if none was found.
2957 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002958 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002959 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002961
2962 // First find the requested task.
2963 while (i > 0) {
2964 i--;
2965 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2966 if (r.task.taskId == taskId) {
2967 i++;
2968 break;
2969 }
2970 }
2971
2972 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 while (i > 0) {
2974 i--;
2975 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2976 if (r.finishing) {
2977 continue;
2978 }
2979 if (r.task.taskId != taskId) {
2980 return null;
2981 }
2982 if (r.realActivity.equals(newR.realActivity)) {
2983 // Here it is! Now finish everything in front...
2984 HistoryRecord ret = r;
2985 if (doClear) {
2986 while (i < (mHistory.size()-1)) {
2987 i++;
2988 r = (HistoryRecord)mHistory.get(i);
2989 if (r.finishing) {
2990 continue;
2991 }
2992 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2993 null, "clear")) {
2994 i--;
2995 }
2996 }
2997 }
2998
2999 // Finally, if this is a normal launch mode (that is, not
3000 // expecting onNewIntent()), then we will finish the current
3001 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003002 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3003 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003004 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003005 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003007 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003008 null, "clear");
3009 }
3010 return null;
3011 }
3012 }
3013
3014 return ret;
3015 }
3016 }
3017
3018 return null;
3019 }
3020
3021 /**
3022 * Find the activity in the history stack within the given task. Returns
3023 * the index within the history at which it's found, or < 0 if not found.
3024 */
3025 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3026 int i = mHistory.size();
3027 while (i > 0) {
3028 i--;
3029 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3030 if (candidate.task.taskId != task) {
3031 break;
3032 }
3033 if (candidate.realActivity.equals(r.realActivity)) {
3034 return i;
3035 }
3036 }
3037
3038 return -1;
3039 }
3040
3041 /**
3042 * Reorder the history stack so that the activity at the given index is
3043 * brought to the front.
3044 */
3045 private final HistoryRecord moveActivityToFrontLocked(int where) {
3046 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3047 int top = mHistory.size();
3048 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3049 mHistory.add(top, newTop);
3050 oldTop.frontOfTask = false;
3051 newTop.frontOfTask = true;
3052 return newTop;
3053 }
3054
3055 /**
3056 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3057 * method will be called at the proper time.
3058 */
3059 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3060 boolean sent = false;
3061 if (r.state == ActivityState.RESUMED
3062 && r.app != null && r.app.thread != null) {
3063 try {
3064 ArrayList<Intent> ar = new ArrayList<Intent>();
3065 ar.add(new Intent(intent));
3066 r.app.thread.scheduleNewIntent(ar, r);
3067 sent = true;
3068 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003069 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 }
3071 }
3072 if (!sent) {
3073 r.addNewIntentLocked(new Intent(intent));
3074 }
3075 }
3076
3077 private final void logStartActivity(int tag, HistoryRecord r,
3078 TaskRecord task) {
3079 EventLog.writeEvent(tag,
3080 System.identityHashCode(r), task.taskId,
3081 r.shortComponentName, r.intent.getAction(),
3082 r.intent.getType(), r.intent.getDataString(),
3083 r.intent.getFlags());
3084 }
3085
3086 private final int startActivityLocked(IApplicationThread caller,
3087 Intent intent, String resolvedType,
3088 Uri[] grantedUriPermissions,
3089 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3090 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003091 int callingPid, int callingUid, boolean onlyIfNeeded,
3092 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003093 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094
3095 HistoryRecord sourceRecord = null;
3096 HistoryRecord resultRecord = null;
3097 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003098 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003099 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3101 if (index >= 0) {
3102 sourceRecord = (HistoryRecord)mHistory.get(index);
3103 if (requestCode >= 0 && !sourceRecord.finishing) {
3104 resultRecord = sourceRecord;
3105 }
3106 }
3107 }
3108
3109 int launchFlags = intent.getFlags();
3110
3111 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3112 && sourceRecord != null) {
3113 // Transfer the result target from the source activity to the new
3114 // one being started, including any failures.
3115 if (requestCode >= 0) {
3116 return START_FORWARD_AND_REQUEST_CONFLICT;
3117 }
3118 resultRecord = sourceRecord.resultTo;
3119 resultWho = sourceRecord.resultWho;
3120 requestCode = sourceRecord.requestCode;
3121 sourceRecord.resultTo = null;
3122 if (resultRecord != null) {
3123 resultRecord.removeResultsLocked(
3124 sourceRecord, resultWho, requestCode);
3125 }
3126 }
3127
3128 int err = START_SUCCESS;
3129
3130 if (intent.getComponent() == null) {
3131 // We couldn't find a class that can handle the given Intent.
3132 // That's the end of that!
3133 err = START_INTENT_NOT_RESOLVED;
3134 }
3135
3136 if (err == START_SUCCESS && aInfo == null) {
3137 // We couldn't find the specific class specified in the Intent.
3138 // Also the end of the line.
3139 err = START_CLASS_NOT_FOUND;
3140 }
3141
3142 ProcessRecord callerApp = null;
3143 if (err == START_SUCCESS && caller != null) {
3144 callerApp = getRecordForAppLocked(caller);
3145 if (callerApp != null) {
3146 callingPid = callerApp.pid;
3147 callingUid = callerApp.info.uid;
3148 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003149 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150 + " (pid=" + callingPid + ") when starting: "
3151 + intent.toString());
3152 err = START_PERMISSION_DENIED;
3153 }
3154 }
3155
3156 if (err != START_SUCCESS) {
3157 if (resultRecord != null) {
3158 sendActivityResultLocked(-1,
3159 resultRecord, resultWho, requestCode,
3160 Activity.RESULT_CANCELED, null);
3161 }
3162 return err;
3163 }
3164
3165 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3166 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3167 if (perm != PackageManager.PERMISSION_GRANTED) {
3168 if (resultRecord != null) {
3169 sendActivityResultLocked(-1,
3170 resultRecord, resultWho, requestCode,
3171 Activity.RESULT_CANCELED, null);
3172 }
3173 String msg = "Permission Denial: starting " + intent.toString()
3174 + " from " + callerApp + " (pid=" + callingPid
3175 + ", uid=" + callingUid + ")"
3176 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003177 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 throw new SecurityException(msg);
3179 }
3180
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003181 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003182 boolean abort = false;
3183 try {
3184 // The Intent we give to the watcher has the extra data
3185 // stripped off, since it can contain private information.
3186 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003187 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003188 aInfo.applicationInfo.packageName);
3189 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003190 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003191 }
3192
3193 if (abort) {
3194 if (resultRecord != null) {
3195 sendActivityResultLocked(-1,
3196 resultRecord, resultWho, requestCode,
3197 Activity.RESULT_CANCELED, null);
3198 }
3199 // We pretend to the caller that it was really started, but
3200 // they will just get a cancel result.
3201 return START_SUCCESS;
3202 }
3203 }
3204
3205 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3206 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003207 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003209 if (mResumedActivity == null
3210 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3211 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3212 PendingActivityLaunch pal = new PendingActivityLaunch();
3213 pal.r = r;
3214 pal.sourceRecord = sourceRecord;
3215 pal.grantedUriPermissions = grantedUriPermissions;
3216 pal.grantedMode = grantedMode;
3217 pal.onlyIfNeeded = onlyIfNeeded;
3218 mPendingActivityLaunches.add(pal);
3219 return START_SWITCHES_CANCELED;
3220 }
3221 }
3222
3223 if (mDidAppSwitch) {
3224 // This is the second allowed switch since we stopped switches,
3225 // so now just generally allow switches. Use case: user presses
3226 // home (switches disabled, switch to home, mDidAppSwitch now true);
3227 // user taps a home icon (coming from home so allowed, we hit here
3228 // and now allow anyone to switch again).
3229 mAppSwitchesAllowedTime = 0;
3230 } else {
3231 mDidAppSwitch = true;
3232 }
3233
3234 doPendingActivityLaunchesLocked(false);
3235
3236 return startActivityUncheckedLocked(r, sourceRecord,
3237 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3238 }
3239
3240 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3241 final int N = mPendingActivityLaunches.size();
3242 if (N <= 0) {
3243 return;
3244 }
3245 for (int i=0; i<N; i++) {
3246 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3247 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3248 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3249 doResume && i == (N-1));
3250 }
3251 mPendingActivityLaunches.clear();
3252 }
3253
3254 private final int startActivityUncheckedLocked(HistoryRecord r,
3255 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3256 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3257 final Intent intent = r.intent;
3258 final int callingUid = r.launchedFromUid;
3259
3260 int launchFlags = intent.getFlags();
3261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 // We'll invoke onUserLeaving before onPause only if the launching
3263 // activity did not explicitly state that this is an automated launch.
3264 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003265 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003266 "startActivity() => mUserLeaving=" + mUserLeaving);
3267
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003268 // If the caller has asked not to resume at this point, we make note
3269 // of this in the record so that we can skip it when trying to find
3270 // the top running activity.
3271 if (!doResume) {
3272 r.delayedResume = true;
3273 }
3274
3275 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3276 != 0 ? r : null;
3277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 // If the onlyIfNeeded flag is set, then we can do this if the activity
3279 // being launched is the same as the one making the call... or, as
3280 // a special case, if we do not know the caller then we count the
3281 // current top activity as the caller.
3282 if (onlyIfNeeded) {
3283 HistoryRecord checkedCaller = sourceRecord;
3284 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003285 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003286 }
3287 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3288 // Caller is not the same as launcher, so always needed.
3289 onlyIfNeeded = false;
3290 }
3291 }
3292
3293 if (grantedUriPermissions != null && callingUid > 0) {
3294 for (int i=0; i<grantedUriPermissions.length; i++) {
3295 grantUriPermissionLocked(callingUid, r.packageName,
3296 grantedUriPermissions[i], grantedMode, r);
3297 }
3298 }
3299
3300 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3301 intent, r);
3302
3303 if (sourceRecord == null) {
3304 // This activity is not being started from another... in this
3305 // case we -always- start a new task.
3306 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003307 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 -08003308 + intent);
3309 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3310 }
3311 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3312 // The original activity who is starting us is running as a single
3313 // instance... this new activity it is starting must go on its
3314 // own task.
3315 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3316 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3317 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3318 // The activity being started is a single instance... it always
3319 // gets launched into its own task.
3320 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3321 }
3322
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003323 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 // For whatever reason this activity is being launched into a new
3325 // task... yet the caller has requested a result back. Well, that
3326 // is pretty messed up, so instead immediately send back a cancel
3327 // and let the new task continue launched as normal without a
3328 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003329 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003330 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003331 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 Activity.RESULT_CANCELED, null);
3333 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003334 }
3335
3336 boolean addingToTask = false;
3337 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3338 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3339 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3340 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3341 // If bring to front is requested, and no result is requested, and
3342 // we can find a task that was started with this same
3343 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003344 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 // See if there is a task to bring to the front. If this is
3346 // a SINGLE_INSTANCE activity, there can be one and only one
3347 // instance of it in the history, and it is always in its own
3348 // unique task, so we do a special search.
3349 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3350 ? findTaskLocked(intent, r.info)
3351 : findActivityLocked(intent, r.info);
3352 if (taskTop != null) {
3353 if (taskTop.task.intent == null) {
3354 // This task was started because of movement of
3355 // the activity based on affinity... now that we
3356 // are actually launching it, we can assign the
3357 // base intent.
3358 taskTop.task.setIntent(intent, r.info);
3359 }
3360 // If the target task is not in the front, then we need
3361 // to bring it to the front... except... well, with
3362 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3363 // to have the same behavior as if a new instance was
3364 // being started, which means not bringing it to the front
3365 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003366 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 if (curTop.task != taskTop.task) {
3368 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3369 boolean callerAtFront = sourceRecord == null
3370 || curTop.task == sourceRecord.task;
3371 if (callerAtFront) {
3372 // We really do want to push this one into the
3373 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003374 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003375 }
3376 }
3377 // If the caller has requested that the target task be
3378 // reset, then do so.
3379 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3380 taskTop = resetTaskIfNeededLocked(taskTop, r);
3381 }
3382 if (onlyIfNeeded) {
3383 // We don't need to start a new activity, and
3384 // the client said not to do anything if that
3385 // is the case, so this is it! And for paranoia, make
3386 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003387 if (doResume) {
3388 resumeTopActivityLocked(null);
3389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003390 return START_RETURN_INTENT_TO_CALLER;
3391 }
3392 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3393 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3394 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3395 // In this situation we want to remove all activities
3396 // from the task up to the one being started. In most
3397 // cases this means we are resetting the task to its
3398 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003399 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003400 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 if (top != null) {
3402 if (top.frontOfTask) {
3403 // Activity aliases may mean we use different
3404 // intents for the top activity, so make sure
3405 // the task now has the identity of the new
3406 // intent.
3407 top.task.setIntent(r.intent, r.info);
3408 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003409 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 deliverNewIntentLocked(top, r.intent);
3411 } else {
3412 // A special case: we need to
3413 // start the activity because it is not currently
3414 // running, and the caller has asked to clear the
3415 // current task to have this activity at the top.
3416 addingToTask = true;
3417 // Now pretend like this activity is being started
3418 // by the top of its task, so it is put in the
3419 // right place.
3420 sourceRecord = taskTop;
3421 }
3422 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3423 // In this case the top activity on the task is the
3424 // same as the one being launched, so we take that
3425 // as a request to bring the task to the foreground.
3426 // If the top activity in the task is the root
3427 // activity, deliver this new intent to it if it
3428 // desires.
3429 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3430 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003431 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 if (taskTop.frontOfTask) {
3433 taskTop.task.setIntent(r.intent, r.info);
3434 }
3435 deliverNewIntentLocked(taskTop, r.intent);
3436 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3437 // In this case we are launching the root activity
3438 // of the task, but with a different intent. We
3439 // should start a new instance on top.
3440 addingToTask = true;
3441 sourceRecord = taskTop;
3442 }
3443 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3444 // In this case an activity is being launched in to an
3445 // existing task, without resetting that task. This
3446 // is typically the situation of launching an activity
3447 // from a notification or shortcut. We want to place
3448 // the new activity on top of the current task.
3449 addingToTask = true;
3450 sourceRecord = taskTop;
3451 } else if (!taskTop.task.rootWasReset) {
3452 // In this case we are launching in to an existing task
3453 // that has not yet been started from its front door.
3454 // The current task has been brought to the front.
3455 // Ideally, we'd probably like to place this new task
3456 // at the bottom of its stack, but that's a little hard
3457 // to do with the current organization of the code so
3458 // for now we'll just drop it.
3459 taskTop.task.setIntent(r.intent, r.info);
3460 }
3461 if (!addingToTask) {
3462 // We didn't do anything... but it was needed (a.k.a., client
3463 // don't use that intent!) And for paranoia, make
3464 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003465 if (doResume) {
3466 resumeTopActivityLocked(null);
3467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 return START_TASK_TO_FRONT;
3469 }
3470 }
3471 }
3472 }
3473
3474 //String uri = r.intent.toURI();
3475 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003476 //Slog.i(TAG, "Given intent: " + r.intent);
3477 //Slog.i(TAG, "URI is: " + uri);
3478 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479
3480 if (r.packageName != null) {
3481 // If the activity being launched is the same as the one currently
3482 // at the top, then we need to check if it should only be launched
3483 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003484 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3485 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486 if (top.realActivity.equals(r.realActivity)) {
3487 if (top.app != null && top.app.thread != null) {
3488 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3489 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3490 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003491 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 // For paranoia, make sure we have correctly
3493 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003494 if (doResume) {
3495 resumeTopActivityLocked(null);
3496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 if (onlyIfNeeded) {
3498 // We don't need to start a new activity, and
3499 // the client said not to do anything if that
3500 // is the case, so this is it!
3501 return START_RETURN_INTENT_TO_CALLER;
3502 }
3503 deliverNewIntentLocked(top, r.intent);
3504 return START_DELIVERED_TO_TOP;
3505 }
3506 }
3507 }
3508 }
3509
3510 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003511 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003513 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 Activity.RESULT_CANCELED, null);
3515 }
3516 return START_CLASS_NOT_FOUND;
3517 }
3518
3519 boolean newTask = false;
3520
3521 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003522 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3524 // todo: should do better management of integers.
3525 mCurTask++;
3526 if (mCurTask <= 0) {
3527 mCurTask = 1;
3528 }
3529 r.task = new TaskRecord(mCurTask, r.info, intent,
3530 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003531 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003532 + " in new task " + r.task);
3533 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003534 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535
3536 } else if (sourceRecord != null) {
3537 if (!addingToTask &&
3538 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3539 // In this case, we are adding the activity to an existing
3540 // task, but the caller has asked to clear that task if the
3541 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003542 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003543 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003544 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003545 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546 deliverNewIntentLocked(top, r.intent);
3547 // For paranoia, make sure we have correctly
3548 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003549 if (doResume) {
3550 resumeTopActivityLocked(null);
3551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 return START_DELIVERED_TO_TOP;
3553 }
3554 } else if (!addingToTask &&
3555 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3556 // In this case, we are launching an activity in our own task
3557 // that may already be running somewhere in the history, and
3558 // we want to shuffle it to the front of the stack if so.
3559 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3560 if (where >= 0) {
3561 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003562 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003564 if (doResume) {
3565 resumeTopActivityLocked(null);
3566 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 return START_DELIVERED_TO_TOP;
3568 }
3569 }
3570 // An existing activity is starting this new activity, so we want
3571 // to keep the new one in the same task as the one that is starting
3572 // it.
3573 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003574 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003575 + " in existing task " + r.task);
3576
3577 } else {
3578 // This not being started from an existing activity, and not part
3579 // of a new task... just put it in the top task, though these days
3580 // this case should never happen.
3581 final int N = mHistory.size();
3582 HistoryRecord prev =
3583 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3584 r.task = prev != null
3585 ? prev.task
3586 : new TaskRecord(mCurTask, r.info, intent,
3587 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003588 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 + " in new guessed " + r.task);
3590 }
3591 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003592 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003594 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003595 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003596 return START_SUCCESS;
3597 }
3598
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003599 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3600 long thisTime, long totalTime) {
3601 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3602 WaitResult w = mWaitingActivityLaunched.get(i);
3603 w.timeout = timeout;
3604 if (r != null) {
3605 w.who = new ComponentName(r.info.packageName, r.info.name);
3606 }
3607 w.thisTime = thisTime;
3608 w.totalTime = totalTime;
3609 }
3610 notify();
3611 }
3612
3613 void reportActivityVisibleLocked(HistoryRecord r) {
3614 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3615 WaitResult w = mWaitingActivityVisible.get(i);
3616 w.timeout = false;
3617 if (r != null) {
3618 w.who = new ComponentName(r.info.packageName, r.info.name);
3619 }
3620 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3621 w.thisTime = w.totalTime;
3622 }
3623 notify();
3624 }
3625
3626 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3628 int grantedMode, IBinder resultTo,
3629 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003630 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003631 // Refuse possible leaked file descriptors
3632 if (intent != null && intent.hasFileDescriptors()) {
3633 throw new IllegalArgumentException("File descriptors passed in Intent");
3634 }
3635
The Android Open Source Project4df24232009-03-05 14:34:35 -08003636 final boolean componentSpecified = intent.getComponent() != null;
3637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 // Don't modify the client's object!
3639 intent = new Intent(intent);
3640
3641 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 ActivityInfo aInfo;
3643 try {
3644 ResolveInfo rInfo =
3645 ActivityThread.getPackageManager().resolveIntent(
3646 intent, resolvedType,
3647 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003648 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003649 aInfo = rInfo != null ? rInfo.activityInfo : null;
3650 } catch (RemoteException e) {
3651 aInfo = null;
3652 }
3653
3654 if (aInfo != null) {
3655 // Store the found target back into the intent, because now that
3656 // we have it we never want to do this again. For example, if the
3657 // user navigates back to this point in the history, we should
3658 // always restart the exact same activity.
3659 intent.setComponent(new ComponentName(
3660 aInfo.applicationInfo.packageName, aInfo.name));
3661
3662 // Don't debug things in the system process
3663 if (debug) {
3664 if (!aInfo.processName.equals("system")) {
3665 setDebugApp(aInfo.processName, true, false);
3666 }
3667 }
3668 }
3669
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003670 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003671 int callingPid;
3672 int callingUid;
3673 if (caller == null) {
3674 callingPid = Binder.getCallingPid();
3675 callingUid = Binder.getCallingUid();
3676 } else {
3677 callingPid = callingUid = -1;
3678 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003679
3680 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003681 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3682 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003686 int res = startActivityLocked(caller, intent, resolvedType,
3687 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003688 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003689 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003690
Dianne Hackborne2522462010-03-29 18:41:30 -07003691 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003692 // If the caller also wants to switch to a new configuration,
3693 // do so now. This allows a clean switch, as we are waiting
3694 // for the current activity to pause (so we will not destroy
3695 // it), and have not yet started the next activity.
3696 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3697 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003698 mConfigWillChange = false;
3699 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3700 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003701 updateConfigurationLocked(config, null);
3702 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003704 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003705
3706 if (outResult != null) {
3707 outResult.result = res;
3708 if (res == IActivityManager.START_SUCCESS) {
3709 mWaitingActivityLaunched.add(outResult);
3710 do {
3711 try {
3712 wait();
3713 } catch (InterruptedException e) {
3714 }
3715 } while (!outResult.timeout && outResult.who == null);
3716 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3717 HistoryRecord r = this.topRunningActivityLocked(null);
3718 if (r.nowVisible) {
3719 outResult.timeout = false;
3720 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3721 outResult.totalTime = 0;
3722 outResult.thisTime = 0;
3723 } else {
3724 outResult.thisTime = SystemClock.uptimeMillis();
3725 mWaitingActivityVisible.add(outResult);
3726 do {
3727 try {
3728 wait();
3729 } catch (InterruptedException e) {
3730 }
3731 } while (!outResult.timeout && outResult.who == null);
3732 }
3733 }
3734 }
3735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003736 return res;
3737 }
3738 }
3739
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003740 public final int startActivity(IApplicationThread caller,
3741 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3742 int grantedMode, IBinder resultTo,
3743 String resultWho, int requestCode, boolean onlyIfNeeded,
3744 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003745 return startActivityMayWait(caller, intent, resolvedType,
3746 grantedUriPermissions, grantedMode, resultTo, resultWho,
3747 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003748 }
3749
3750 public final WaitResult startActivityAndWait(IApplicationThread caller,
3751 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3752 int grantedMode, IBinder resultTo,
3753 String resultWho, int requestCode, boolean onlyIfNeeded,
3754 boolean debug) {
3755 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003756 startActivityMayWait(caller, intent, resolvedType,
3757 grantedUriPermissions, grantedMode, resultTo, resultWho,
3758 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003759 return res;
3760 }
3761
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003762 public final int startActivityWithConfig(IApplicationThread caller,
3763 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3764 int grantedMode, IBinder resultTo,
3765 String resultWho, int requestCode, boolean onlyIfNeeded,
3766 boolean debug, Configuration config) {
3767 return startActivityMayWait(caller, intent, resolvedType,
3768 grantedUriPermissions, grantedMode, resultTo, resultWho,
3769 requestCode, onlyIfNeeded, debug, null, config);
3770 }
3771
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003772 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003773 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003774 IBinder resultTo, String resultWho, int requestCode,
3775 int flagsMask, int flagsValues) {
3776 // Refuse possible leaked file descriptors
3777 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3778 throw new IllegalArgumentException("File descriptors passed in Intent");
3779 }
3780
3781 IIntentSender sender = intent.getTarget();
3782 if (!(sender instanceof PendingIntentRecord)) {
3783 throw new IllegalArgumentException("Bad PendingIntent object");
3784 }
3785
3786 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003787
3788 synchronized (this) {
3789 // If this is coming from the currently resumed activity, it is
3790 // effectively saying that app switches are allowed at this point.
3791 if (mResumedActivity != null
3792 && mResumedActivity.info.applicationInfo.uid ==
3793 Binder.getCallingUid()) {
3794 mAppSwitchesAllowedTime = 0;
3795 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003796 }
3797
3798 return pir.sendInner(0, fillInIntent, resolvedType,
3799 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3800 }
3801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003802 public boolean startNextMatchingActivity(IBinder callingActivity,
3803 Intent intent) {
3804 // Refuse possible leaked file descriptors
3805 if (intent != null && intent.hasFileDescriptors() == true) {
3806 throw new IllegalArgumentException("File descriptors passed in Intent");
3807 }
3808
3809 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003810 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 if (index < 0) {
3812 return false;
3813 }
3814 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3815 if (r.app == null || r.app.thread == null) {
3816 // The caller is not running... d'oh!
3817 return false;
3818 }
3819 intent = new Intent(intent);
3820 // The caller is not allowed to change the data.
3821 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3822 // And we are resetting to find the next component...
3823 intent.setComponent(null);
3824
3825 ActivityInfo aInfo = null;
3826 try {
3827 List<ResolveInfo> resolves =
3828 ActivityThread.getPackageManager().queryIntentActivities(
3829 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003830 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831
3832 // Look for the original activity in the list...
3833 final int N = resolves != null ? resolves.size() : 0;
3834 for (int i=0; i<N; i++) {
3835 ResolveInfo rInfo = resolves.get(i);
3836 if (rInfo.activityInfo.packageName.equals(r.packageName)
3837 && rInfo.activityInfo.name.equals(r.info.name)) {
3838 // We found the current one... the next matching is
3839 // after it.
3840 i++;
3841 if (i<N) {
3842 aInfo = resolves.get(i).activityInfo;
3843 }
3844 break;
3845 }
3846 }
3847 } catch (RemoteException e) {
3848 }
3849
3850 if (aInfo == null) {
3851 // Nobody who is next!
3852 return false;
3853 }
3854
3855 intent.setComponent(new ComponentName(
3856 aInfo.applicationInfo.packageName, aInfo.name));
3857 intent.setFlags(intent.getFlags()&~(
3858 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3859 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3860 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3861 Intent.FLAG_ACTIVITY_NEW_TASK));
3862
3863 // Okay now we need to start the new activity, replacing the
3864 // currently running activity. This is a little tricky because
3865 // we want to start the new one as if the current one is finished,
3866 // but not finish the current one first so that there is no flicker.
3867 // And thus...
3868 final boolean wasFinishing = r.finishing;
3869 r.finishing = true;
3870
3871 // Propagate reply information over to the new activity.
3872 final HistoryRecord resultTo = r.resultTo;
3873 final String resultWho = r.resultWho;
3874 final int requestCode = r.requestCode;
3875 r.resultTo = null;
3876 if (resultTo != null) {
3877 resultTo.removeResultsLocked(r, resultWho, requestCode);
3878 }
3879
3880 final long origId = Binder.clearCallingIdentity();
3881 // XXX we are not dealing with propagating grantedUriPermissions...
3882 // those are not yet exposed to user code, so there is no need.
3883 int res = startActivityLocked(r.app.thread, intent,
3884 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003885 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003886 Binder.restoreCallingIdentity(origId);
3887
3888 r.finishing = wasFinishing;
3889 if (res != START_SUCCESS) {
3890 return false;
3891 }
3892 return true;
3893 }
3894 }
3895
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003896 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 Intent intent, String resolvedType, IBinder resultTo,
3898 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003899
3900 // This is so super not safe, that only the system (or okay root)
3901 // can do it.
3902 final int callingUid = Binder.getCallingUid();
3903 if (callingUid != 0 && callingUid != Process.myUid()) {
3904 throw new SecurityException(
3905 "startActivityInPackage only available to the system");
3906 }
3907
The Android Open Source Project4df24232009-03-05 14:34:35 -08003908 final boolean componentSpecified = intent.getComponent() != null;
3909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 // Don't modify the client's object!
3911 intent = new Intent(intent);
3912
3913 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003914 ActivityInfo aInfo;
3915 try {
3916 ResolveInfo rInfo =
3917 ActivityThread.getPackageManager().resolveIntent(
3918 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003919 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 aInfo = rInfo != null ? rInfo.activityInfo : null;
3921 } catch (RemoteException e) {
3922 aInfo = null;
3923 }
3924
3925 if (aInfo != null) {
3926 // Store the found target back into the intent, because now that
3927 // we have it we never want to do this again. For example, if the
3928 // user navigates back to this point in the history, we should
3929 // always restart the exact same activity.
3930 intent.setComponent(new ComponentName(
3931 aInfo.applicationInfo.packageName, aInfo.name));
3932 }
3933
3934 synchronized(this) {
3935 return startActivityLocked(null, intent, resolvedType,
3936 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003937 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 }
3939 }
3940
Josh Bartel7f208742010-02-25 11:01:44 -06003941 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 // Remove any existing entries that are the same kind of task.
3943 int N = mRecentTasks.size();
3944 for (int i=0; i<N; i++) {
3945 TaskRecord tr = mRecentTasks.get(i);
3946 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3947 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3948 mRecentTasks.remove(i);
3949 i--;
3950 N--;
3951 if (task.intent == null) {
3952 // If the new recent task we are adding is not fully
3953 // specified, then replace it with the existing recent task.
3954 task = tr;
3955 }
3956 }
3957 }
3958 if (N >= MAX_RECENT_TASKS) {
3959 mRecentTasks.remove(N-1);
3960 }
3961 mRecentTasks.add(0, task);
3962 }
3963
3964 public void setRequestedOrientation(IBinder token,
3965 int requestedOrientation) {
3966 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003967 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 if (index < 0) {
3969 return;
3970 }
3971 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3972 final long origId = Binder.clearCallingIdentity();
3973 mWindowManager.setAppOrientation(r, requestedOrientation);
3974 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003975 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003976 r.mayFreezeScreenLocked(r.app) ? r : null);
3977 if (config != null) {
3978 r.frozenBeforeDestroy = true;
3979 if (!updateConfigurationLocked(config, r)) {
3980 resumeTopActivityLocked(null);
3981 }
3982 }
3983 Binder.restoreCallingIdentity(origId);
3984 }
3985 }
3986
3987 public int getRequestedOrientation(IBinder token) {
3988 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003989 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003990 if (index < 0) {
3991 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3992 }
3993 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3994 return mWindowManager.getAppOrientation(r);
3995 }
3996 }
3997
3998 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003999 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4001 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4002 if (!r.finishing) {
4003 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4004 "no-history");
4005 }
4006 } else if (r.app != null && r.app.thread != null) {
4007 if (mFocusedActivity == r) {
4008 setFocusedActivityLocked(topRunningActivityLocked(null));
4009 }
4010 r.resumeKeyDispatchingLocked();
4011 try {
4012 r.stopped = false;
4013 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004014 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 TAG, "Stopping visible=" + r.visible + " for " + r);
4016 if (!r.visible) {
4017 mWindowManager.setAppVisibility(r, false);
4018 }
4019 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4020 } catch (Exception e) {
4021 // Maybe just ignore exceptions here... if the process
4022 // has crashed, our death notification will clean things
4023 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004024 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004025 // Just in case, assume it to be stopped.
4026 r.stopped = true;
4027 r.state = ActivityState.STOPPED;
4028 if (r.configDestroy) {
4029 destroyActivityLocked(r, true);
4030 }
4031 }
4032 }
4033 }
4034
4035 /**
4036 * @return Returns true if the activity is being finished, false if for
4037 * some reason it is being left as-is.
4038 */
4039 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4040 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004041 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004042 TAG, "Finishing activity: token=" + token
4043 + ", result=" + resultCode + ", data=" + resultData);
4044
Dianne Hackborn75b03852009-06-12 15:43:26 -07004045 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004046 if (index < 0) {
4047 return false;
4048 }
4049 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4050
4051 // Is this the last activity left?
4052 boolean lastActivity = true;
4053 for (int i=mHistory.size()-1; i>=0; i--) {
4054 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4055 if (!p.finishing && p != r) {
4056 lastActivity = false;
4057 break;
4058 }
4059 }
4060
4061 // If this is the last activity, but it is the home activity, then
4062 // just don't finish it.
4063 if (lastActivity) {
4064 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4065 return false;
4066 }
4067 }
4068
4069 finishActivityLocked(r, index, resultCode, resultData, reason);
4070 return true;
4071 }
4072
4073 /**
4074 * @return Returns true if this activity has been removed from the history
4075 * list, or false if it is still in the list and will be removed later.
4076 */
4077 private final boolean finishActivityLocked(HistoryRecord r, int index,
4078 int resultCode, Intent resultData, String reason) {
4079 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004080 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081 return false;
4082 }
4083
4084 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004085 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086 System.identityHashCode(r),
4087 r.task.taskId, r.shortComponentName, reason);
4088 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004089 if (index < (mHistory.size()-1)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004090 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4091 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004092 if (r.frontOfTask) {
4093 // The next activity is now the front of the task.
4094 next.frontOfTask = true;
4095 }
4096 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4097 // If the caller asked that this activity (and all above it)
4098 // be cleared when the task is reset, don't lose that information,
4099 // but propagate it up to the next activity.
4100 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 }
4103 }
4104
4105 r.pauseKeyDispatchingLocked();
4106 if (mFocusedActivity == r) {
4107 setFocusedActivityLocked(topRunningActivityLocked(null));
4108 }
4109
4110 // send the result
4111 HistoryRecord resultTo = r.resultTo;
4112 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004113 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004114 + " who=" + r.resultWho + " req=" + r.requestCode
4115 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 if (r.info.applicationInfo.uid > 0) {
4117 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4118 r.packageName, resultData, r);
4119 }
4120 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4121 resultData);
4122 r.resultTo = null;
4123 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004124 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125
4126 // Make sure this HistoryRecord is not holding on to other resources,
4127 // because clients have remote IPC references to this object so we
4128 // can't assume that will go away and want to avoid circular IPC refs.
4129 r.results = null;
4130 r.pendingResults = null;
4131 r.newIntents = null;
4132 r.icicle = null;
4133
4134 if (mPendingThumbnails.size() > 0) {
4135 // There are clients waiting to receive thumbnails so, in case
4136 // this is an activity that someone is waiting for, add it
4137 // to the pending list so we can correctly update the clients.
4138 mCancelledThumbnails.add(r);
4139 }
4140
4141 if (mResumedActivity == r) {
4142 boolean endTask = index <= 0
4143 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004144 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004145 "Prepare close transition: finishing " + r);
4146 mWindowManager.prepareAppTransition(endTask
4147 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4148 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4149
4150 // Tell window manager to prepare for this one to be removed.
4151 mWindowManager.setAppVisibility(r, false);
4152
4153 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004154 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4155 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004156 startPausingLocked(false, false);
4157 }
4158
4159 } else if (r.state != ActivityState.PAUSING) {
4160 // If the activity is PAUSING, we will complete the finish once
4161 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004162 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004163 return finishCurrentActivityLocked(r, index,
4164 FINISH_AFTER_PAUSE) == null;
4165 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004166 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004167 }
4168
4169 return false;
4170 }
4171
4172 private static final int FINISH_IMMEDIATELY = 0;
4173 private static final int FINISH_AFTER_PAUSE = 1;
4174 private static final int FINISH_AFTER_VISIBLE = 2;
4175
4176 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4177 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004178 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 if (index < 0) {
4180 return null;
4181 }
4182
4183 return finishCurrentActivityLocked(r, index, mode);
4184 }
4185
4186 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4187 int index, int mode) {
4188 // First things first: if this activity is currently visible,
4189 // and the resumed activity is not yet visible, then hold off on
4190 // finishing until the resumed one becomes visible.
4191 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4192 if (!mStoppingActivities.contains(r)) {
4193 mStoppingActivities.add(r);
4194 if (mStoppingActivities.size() > 3) {
4195 // If we already have a few activities waiting to stop,
4196 // then give up on things going idle and start clearing
4197 // them out.
4198 Message msg = Message.obtain();
4199 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4200 mHandler.sendMessage(msg);
4201 }
4202 }
4203 r.state = ActivityState.STOPPING;
4204 updateOomAdjLocked();
4205 return r;
4206 }
4207
4208 // make sure the record is cleaned out of other places.
4209 mStoppingActivities.remove(r);
4210 mWaitingVisibleActivities.remove(r);
4211 if (mResumedActivity == r) {
4212 mResumedActivity = null;
4213 }
4214 final ActivityState prevState = r.state;
4215 r.state = ActivityState.FINISHING;
4216
4217 if (mode == FINISH_IMMEDIATELY
4218 || prevState == ActivityState.STOPPED
4219 || prevState == ActivityState.INITIALIZING) {
4220 // If this activity is already stopped, we can just finish
4221 // it right now.
4222 return destroyActivityLocked(r, true) ? null : r;
4223 } else {
4224 // Need to go through the full pause cycle to get this
4225 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004226 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004227 mFinishingActivities.add(r);
4228 resumeTopActivityLocked(null);
4229 }
4230 return r;
4231 }
4232
4233 /**
4234 * This is the internal entry point for handling Activity.finish().
4235 *
4236 * @param token The Binder token referencing the Activity we want to finish.
4237 * @param resultCode Result code, if any, from this Activity.
4238 * @param resultData Result data (Intent), if any, from this Activity.
4239 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004240 * @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 -08004241 */
4242 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4243 // Refuse possible leaked file descriptors
4244 if (resultData != null && resultData.hasFileDescriptors() == true) {
4245 throw new IllegalArgumentException("File descriptors passed in Intent");
4246 }
4247
4248 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004249 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 // Find the first activity that is not finishing.
4251 HistoryRecord next = topRunningActivityLocked(token, 0);
4252 if (next != null) {
4253 // ask watcher if this is allowed
4254 boolean resumeOK = true;
4255 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004256 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004257 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004258 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 }
4260
4261 if (!resumeOK) {
4262 return false;
4263 }
4264 }
4265 }
4266 final long origId = Binder.clearCallingIdentity();
4267 boolean res = requestFinishActivityLocked(token, resultCode,
4268 resultData, "app-request");
4269 Binder.restoreCallingIdentity(origId);
4270 return res;
4271 }
4272 }
4273
4274 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4275 String resultWho, int requestCode, int resultCode, Intent data) {
4276
4277 if (callingUid > 0) {
4278 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4279 data, r);
4280 }
4281
Joe Onorato8a9b2202010-02-26 18:56:32 -08004282 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004283 + " : who=" + resultWho + " req=" + requestCode
4284 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4286 try {
4287 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4288 list.add(new ResultInfo(resultWho, requestCode,
4289 resultCode, data));
4290 r.app.thread.scheduleSendResult(r, list);
4291 return;
4292 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004293 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004294 }
4295 }
4296
4297 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4298 }
4299
4300 public final void finishSubActivity(IBinder token, String resultWho,
4301 int requestCode) {
4302 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004303 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 if (index < 0) {
4305 return;
4306 }
4307 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4308
4309 final long origId = Binder.clearCallingIdentity();
4310
4311 int i;
4312 for (i=mHistory.size()-1; i>=0; i--) {
4313 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4314 if (r.resultTo == self && r.requestCode == requestCode) {
4315 if ((r.resultWho == null && resultWho == null) ||
4316 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4317 finishActivityLocked(r, i,
4318 Activity.RESULT_CANCELED, null, "request-sub");
4319 }
4320 }
4321 }
4322
4323 Binder.restoreCallingIdentity(origId);
4324 }
4325 }
4326
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004327 public boolean willActivityBeVisible(IBinder token) {
4328 synchronized(this) {
4329 int i;
4330 for (i=mHistory.size()-1; i>=0; i--) {
4331 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4332 if (r == token) {
4333 return true;
4334 }
4335 if (r.fullscreen && !r.finishing) {
4336 return false;
4337 }
4338 }
4339 return true;
4340 }
4341 }
4342
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004343 public void overridePendingTransition(IBinder token, String packageName,
4344 int enterAnim, int exitAnim) {
4345 synchronized(this) {
4346 int index = indexOfTokenLocked(token);
4347 if (index < 0) {
4348 return;
4349 }
4350 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4351
4352 final long origId = Binder.clearCallingIdentity();
4353
4354 if (self.state == ActivityState.RESUMED
4355 || self.state == ActivityState.PAUSING) {
4356 mWindowManager.overridePendingAppTransition(packageName,
4357 enterAnim, exitAnim);
4358 }
4359
4360 Binder.restoreCallingIdentity(origId);
4361 }
4362 }
4363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004364 /**
4365 * Perform clean-up of service connections in an activity record.
4366 */
4367 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4368 // Throw away any services that have been bound by this activity.
4369 if (r.connections != null) {
4370 Iterator<ConnectionRecord> it = r.connections.iterator();
4371 while (it.hasNext()) {
4372 ConnectionRecord c = it.next();
4373 removeConnectionLocked(c, null, r);
4374 }
4375 r.connections = null;
4376 }
4377 }
4378
4379 /**
4380 * Perform the common clean-up of an activity record. This is called both
4381 * as part of destroyActivityLocked() (when destroying the client-side
4382 * representation) and cleaning things up as a result of its hosting
4383 * processing going away, in which case there is no remaining client-side
4384 * state to destroy so only the cleanup here is needed.
4385 */
4386 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4387 if (mResumedActivity == r) {
4388 mResumedActivity = null;
4389 }
4390 if (mFocusedActivity == r) {
4391 mFocusedActivity = null;
4392 }
4393
4394 r.configDestroy = false;
4395 r.frozenBeforeDestroy = false;
4396
4397 // Make sure this record is no longer in the pending finishes list.
4398 // This could happen, for example, if we are trimming activities
4399 // down to the max limit while they are still waiting to finish.
4400 mFinishingActivities.remove(r);
4401 mWaitingVisibleActivities.remove(r);
4402
4403 // Remove any pending results.
4404 if (r.finishing && r.pendingResults != null) {
4405 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4406 PendingIntentRecord rec = apr.get();
4407 if (rec != null) {
4408 cancelIntentSenderLocked(rec, false);
4409 }
4410 }
4411 r.pendingResults = null;
4412 }
4413
4414 if (cleanServices) {
4415 cleanUpActivityServicesLocked(r);
4416 }
4417
4418 if (mPendingThumbnails.size() > 0) {
4419 // There are clients waiting to receive thumbnails so, in case
4420 // this is an activity that someone is waiting for, add it
4421 // to the pending list so we can correctly update the clients.
4422 mCancelledThumbnails.add(r);
4423 }
4424
4425 // Get rid of any pending idle timeouts.
4426 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4427 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4428 }
4429
4430 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4431 if (r.state != ActivityState.DESTROYED) {
4432 mHistory.remove(r);
4433 r.inHistory = false;
4434 r.state = ActivityState.DESTROYED;
4435 mWindowManager.removeAppToken(r);
4436 if (VALIDATE_TOKENS) {
4437 mWindowManager.validateAppTokens(mHistory);
4438 }
4439 cleanUpActivityServicesLocked(r);
4440 removeActivityUriPermissionsLocked(r);
4441 }
4442 }
4443
4444 /**
4445 * Destroy the current CLIENT SIDE instance of an activity. This may be
4446 * called both when actually finishing an activity, or when performing
4447 * a configuration switch where we destroy the current client-side object
4448 * but then create a new client-side object for this same HistoryRecord.
4449 */
4450 private final boolean destroyActivityLocked(HistoryRecord r,
4451 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004452 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004453 TAG, "Removing activity: token=" + r
4454 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004455 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 System.identityHashCode(r),
4457 r.task.taskId, r.shortComponentName);
4458
4459 boolean removedFromHistory = false;
4460
4461 cleanUpActivityLocked(r, false);
4462
Dianne Hackborn03abb812010-01-04 18:43:19 -08004463 final boolean hadApp = r.app != null;
4464
4465 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 if (removeFromApp) {
4467 int idx = r.app.activities.indexOf(r);
4468 if (idx >= 0) {
4469 r.app.activities.remove(idx);
4470 }
4471 if (r.persistent) {
4472 decPersistentCountLocked(r.app);
4473 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004474 if (r.app.activities.size() == 0) {
4475 // No longer have activities, so update location in
4476 // LRU list.
4477 updateLruProcessLocked(r.app, true, false);
4478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 }
4480
4481 boolean skipDestroy = false;
4482
4483 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004484 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4486 r.configChangeFlags);
4487 } catch (Exception e) {
4488 // We can just ignore exceptions here... if the process
4489 // has crashed, our death notification will clean things
4490 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004491 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 if (r.finishing) {
4493 removeActivityFromHistoryLocked(r);
4494 removedFromHistory = true;
4495 skipDestroy = true;
4496 }
4497 }
4498
4499 r.app = null;
4500 r.nowVisible = false;
4501
4502 if (r.finishing && !skipDestroy) {
4503 r.state = ActivityState.DESTROYING;
4504 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4505 msg.obj = r;
4506 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4507 } else {
4508 r.state = ActivityState.DESTROYED;
4509 }
4510 } else {
4511 // remove this record from the history.
4512 if (r.finishing) {
4513 removeActivityFromHistoryLocked(r);
4514 removedFromHistory = true;
4515 } else {
4516 r.state = ActivityState.DESTROYED;
4517 }
4518 }
4519
4520 r.configChangeFlags = 0;
4521
Dianne Hackborn03abb812010-01-04 18:43:19 -08004522 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004523 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 }
4525
4526 return removedFromHistory;
4527 }
4528
Dianne Hackborn03abb812010-01-04 18:43:19 -08004529 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004530 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004531 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004532 TAG, "Removing app " + app + " from list " + list
4533 + " with " + i + " entries");
4534 while (i > 0) {
4535 i--;
4536 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004537 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004538 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4539 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004540 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004541 list.remove(i);
4542 }
4543 }
4544 }
4545
4546 /**
4547 * Main function for removing an existing process from the activity manager
4548 * as a result of that process going away. Clears out all connections
4549 * to the process.
4550 */
4551 private final void handleAppDiedLocked(ProcessRecord app,
4552 boolean restarting) {
4553 cleanUpApplicationRecordLocked(app, restarting, -1);
4554 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004555 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 }
4557
4558 // Just in case...
4559 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004560 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 mPausingActivity = null;
4562 }
4563 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4564 mLastPausedActivity = null;
4565 }
4566
4567 // Remove this application's activities from active lists.
4568 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4569 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4570 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4571 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4572
4573 boolean atTop = true;
4574 boolean hasVisibleActivities = false;
4575
4576 // Clean out the history list.
4577 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004578 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 TAG, "Removing app " + app + " from history with " + i + " entries");
4580 while (i > 0) {
4581 i--;
4582 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004583 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4585 if (r.app == app) {
4586 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004587 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 TAG, "Removing this entry! frozen=" + r.haveState
4589 + " finishing=" + r.finishing);
4590 mHistory.remove(i);
4591
4592 r.inHistory = false;
4593 mWindowManager.removeAppToken(r);
4594 if (VALIDATE_TOKENS) {
4595 mWindowManager.validateAppTokens(mHistory);
4596 }
4597 removeActivityUriPermissionsLocked(r);
4598
4599 } else {
4600 // We have the current state for this activity, so
4601 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004602 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 TAG, "Keeping entry, setting app to null");
4604 if (r.visible) {
4605 hasVisibleActivities = true;
4606 }
4607 r.app = null;
4608 r.nowVisible = false;
4609 if (!r.haveState) {
4610 r.icicle = null;
4611 }
4612 }
4613
4614 cleanUpActivityLocked(r, true);
4615 r.state = ActivityState.STOPPED;
4616 }
4617 atTop = false;
4618 }
4619
4620 app.activities.clear();
4621
4622 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004623 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004624 + " running instrumentation " + app.instrumentationClass);
4625 Bundle info = new Bundle();
4626 info.putString("shortMsg", "Process crashed.");
4627 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4628 }
4629
4630 if (!restarting) {
4631 if (!resumeTopActivityLocked(null)) {
4632 // If there was nothing to resume, and we are not already
4633 // restarting this process, but there is a visible activity that
4634 // is hosted by the process... then make sure all visible
4635 // activities are running, taking care of restarting this
4636 // process.
4637 if (hasVisibleActivities) {
4638 ensureActivitiesVisibleLocked(null, 0);
4639 }
4640 }
4641 }
4642 }
4643
4644 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4645 IBinder threadBinder = thread.asBinder();
4646
4647 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004648 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4649 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4651 return i;
4652 }
4653 }
4654 return -1;
4655 }
4656
4657 private final ProcessRecord getRecordForAppLocked(
4658 IApplicationThread thread) {
4659 if (thread == null) {
4660 return null;
4661 }
4662
4663 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004664 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 }
4666
4667 private final void appDiedLocked(ProcessRecord app, int pid,
4668 IApplicationThread thread) {
4669
4670 mProcDeaths[0]++;
4671
Magnus Edlund7bb25812010-02-24 15:45:06 +01004672 // Clean up already done if the process has been re-started.
4673 if (app.pid == pid && app.thread != null &&
4674 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004675 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004676 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004677 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004678 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 TAG, "Dying app: " + app + ", pid: " + pid
4680 + ", thread: " + thread.asBinder());
4681 boolean doLowMem = app.instrumentationClass == null;
4682 handleAppDiedLocked(app, false);
4683
4684 if (doLowMem) {
4685 // If there are no longer any background processes running,
4686 // and the app that died was not running instrumentation,
4687 // then tell everyone we are now low on memory.
4688 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004689 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4690 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4692 haveBg = true;
4693 break;
4694 }
4695 }
4696
4697 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004698 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004699 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004700 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004701 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4702 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004703 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004704 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4705 // The low memory report is overriding any current
4706 // state for a GC request. Make sure to do
4707 // visible/foreground processes first.
4708 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4709 rec.lastRequestedGc = 0;
4710 } else {
4711 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004713 rec.reportLowMemory = true;
4714 rec.lastLowMemory = now;
4715 mProcessesToGc.remove(rec);
4716 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 }
4718 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004719 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 }
4721 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004722 } else if (app.pid != pid) {
4723 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004724 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004725 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004726 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004727 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004728 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729 + thread.asBinder());
4730 }
4731 }
4732
Dan Egnor42471dd2010-01-07 17:25:22 -08004733 /**
4734 * If a stack trace dump file is configured, dump process stack traces.
4735 * @param pids of dalvik VM processes to dump stack traces for
4736 * @return file containing stack traces, or null if no dump file is configured
4737 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004738 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004739 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4740 if (tracesPath == null || tracesPath.length() == 0) {
4741 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004743
4744 File tracesFile = new File(tracesPath);
4745 try {
4746 File tracesDir = tracesFile.getParentFile();
4747 if (!tracesDir.exists()) tracesFile.mkdirs();
4748 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4749
4750 if (tracesFile.exists()) tracesFile.delete();
4751 tracesFile.createNewFile();
4752 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4753 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004754 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004755 return null;
4756 }
4757
4758 // Use a FileObserver to detect when traces finish writing.
4759 // The order of traces is considered important to maintain for legibility.
4760 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4761 public synchronized void onEvent(int event, String path) { notify(); }
4762 };
4763
4764 try {
4765 observer.startWatching();
4766 int num = pids.size();
4767 for (int i = 0; i < num; i++) {
4768 synchronized (observer) {
4769 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4770 observer.wait(200); // Wait for write-close, give up after 200msec
4771 }
4772 }
4773 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004774 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004775 } finally {
4776 observer.stopWatching();
4777 }
4778
4779 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 }
4781
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004782 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08004783 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004784 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004785
4786 synchronized (this) {
4787 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4788 if (mShuttingDown) {
4789 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
4790 return;
4791 } else if (app.notResponding) {
4792 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
4793 return;
4794 } else if (app.crashing) {
4795 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
4796 return;
4797 }
4798
4799 // In case we come through here for the same app before completing
4800 // this one, mark as anring now so we will bail out.
4801 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08004802
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004803 // Log the ANR to the event log.
4804 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4805 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08004806
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004807 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4808 pids.add(app.pid);
4809
4810 int parentPid = app.pid;
4811 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4812 if (parentPid != app.pid) pids.add(parentPid);
4813
4814 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08004815
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004816 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4817 ProcessRecord r = mLruProcesses.get(i);
4818 if (r != null && r.thread != null) {
4819 int pid = r.pid;
4820 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
4821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004822 }
4823 }
4824
Dan Egnor42471dd2010-01-07 17:25:22 -08004825 File tracesFile = dumpStackTraces(pids);
4826
4827 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004828 StringBuilder info = mStringBuilder;
4829 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004830 info.append("ANR in ").append(app.processName);
4831 if (activity != null && activity.shortComponentName != null) {
4832 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004833 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004834 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004836 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004838 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004839 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841
Dan Egnor42471dd2010-01-07 17:25:22 -08004842 String cpuInfo = null;
4843 if (MONITOR_CPU_USAGE) {
4844 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004845 synchronized (mProcessStatsThread) {
4846 cpuInfo = mProcessStats.printCurrentState();
4847 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004848 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004849 }
4850
Joe Onorato8a9b2202010-02-26 18:56:32 -08004851 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004852 if (tracesFile == null) {
4853 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4854 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4855 }
4856
4857 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4858
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004859 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004861 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4862 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004864 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4865 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 }
4867 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004868 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869 }
4870 }
4871
Dan Egnor42471dd2010-01-07 17:25:22 -08004872 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4873 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4874 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004875
4876 synchronized (this) {
4877 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4878 Process.killProcess(app.pid);
4879 return;
4880 }
4881
4882 // Set the app's notResponding state, and look up the errorReportReceiver
4883 makeAppNotRespondingLocked(app,
4884 activity != null ? activity.shortComponentName : null,
4885 annotation != null ? "ANR " + annotation : "ANR",
4886 info.toString());
4887
4888 // Bring up the infamous App Not Responding dialog
4889 Message msg = Message.obtain();
4890 HashMap map = new HashMap();
4891 msg.what = SHOW_NOT_RESPONDING_MSG;
4892 msg.obj = map;
4893 map.put("app", app);
4894 if (activity != null) {
4895 map.put("activity", activity);
4896 }
4897
4898 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08004899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004900 }
4901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004902 private final void decPersistentCountLocked(ProcessRecord app)
4903 {
4904 app.persistentActivities--;
4905 if (app.persistentActivities > 0) {
4906 // Still more of 'em...
4907 return;
4908 }
4909 if (app.persistent) {
4910 // Ah, but the application itself is persistent. Whatever!
4911 return;
4912 }
4913
4914 // App is no longer persistent... make sure it and the ones
4915 // following it in the LRU list have the correc oom_adj.
4916 updateOomAdjLocked();
4917 }
4918
4919 public void setPersistent(IBinder token, boolean isPersistent) {
4920 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4921 != PackageManager.PERMISSION_GRANTED) {
4922 String msg = "Permission Denial: setPersistent() from pid="
4923 + Binder.getCallingPid()
4924 + ", uid=" + Binder.getCallingUid()
4925 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004926 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927 throw new SecurityException(msg);
4928 }
4929
4930 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004931 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004932 if (index < 0) {
4933 return;
4934 }
4935 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4936 ProcessRecord app = r.app;
4937
Joe Onorato8a9b2202010-02-26 18:56:32 -08004938 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 TAG, "Setting persistence " + isPersistent + ": " + r);
4940
4941 if (isPersistent) {
4942 if (r.persistent) {
4943 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004944 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 return;
4946 }
4947 r.persistent = true;
4948 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004949 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950 if (app.persistentActivities > 1) {
4951 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004952 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004953 return;
4954 }
4955 if (app.persistent) {
4956 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004957 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958 return;
4959 }
4960
4961 // App is now persistent... make sure it and the ones
4962 // following it now have the correct oom_adj.
4963 final long origId = Binder.clearCallingIdentity();
4964 updateOomAdjLocked();
4965 Binder.restoreCallingIdentity(origId);
4966
4967 } else {
4968 if (!r.persistent) {
4969 // Okay okay, I heard you already!
4970 return;
4971 }
4972 r.persistent = false;
4973 final long origId = Binder.clearCallingIdentity();
4974 decPersistentCountLocked(app);
4975 Binder.restoreCallingIdentity(origId);
4976
4977 }
4978 }
4979 }
4980
4981 public boolean clearApplicationUserData(final String packageName,
4982 final IPackageDataObserver observer) {
4983 int uid = Binder.getCallingUid();
4984 int pid = Binder.getCallingPid();
4985 long callingId = Binder.clearCallingIdentity();
4986 try {
4987 IPackageManager pm = ActivityThread.getPackageManager();
4988 int pkgUid = -1;
4989 synchronized(this) {
4990 try {
4991 pkgUid = pm.getPackageUid(packageName);
4992 } catch (RemoteException e) {
4993 }
4994 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004995 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 return false;
4997 }
4998 if (uid == pkgUid || checkComponentPermission(
4999 android.Manifest.permission.CLEAR_APP_USER_DATA,
5000 pid, uid, -1)
5001 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005002 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005003 } else {
5004 throw new SecurityException(pid+" does not have permission:"+
5005 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5006 "for process:"+packageName);
5007 }
5008 }
5009
5010 try {
5011 //clear application user data
5012 pm.clearApplicationUserData(packageName, observer);
5013 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5014 Uri.fromParts("package", packageName, null));
5015 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005016 synchronized (this) {
5017 broadcastIntentLocked(null, null, intent,
5018 null, null, 0, null, null, null,
5019 false, false, MY_PID, Process.SYSTEM_UID);
5020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005021 } catch (RemoteException e) {
5022 }
5023 } finally {
5024 Binder.restoreCallingIdentity(callingId);
5025 }
5026 return true;
5027 }
5028
Dianne Hackborn03abb812010-01-04 18:43:19 -08005029 public void killBackgroundProcesses(final String packageName) {
5030 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5031 != PackageManager.PERMISSION_GRANTED &&
5032 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5033 != PackageManager.PERMISSION_GRANTED) {
5034 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005035 + Binder.getCallingPid()
5036 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005037 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005038 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005039 throw new SecurityException(msg);
5040 }
5041
5042 long callingId = Binder.clearCallingIdentity();
5043 try {
5044 IPackageManager pm = ActivityThread.getPackageManager();
5045 int pkgUid = -1;
5046 synchronized(this) {
5047 try {
5048 pkgUid = pm.getPackageUid(packageName);
5049 } catch (RemoteException e) {
5050 }
5051 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005052 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 return;
5054 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005055 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005056 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005057 }
5058 } finally {
5059 Binder.restoreCallingIdentity(callingId);
5060 }
5061 }
5062
5063 public void forceStopPackage(final String packageName) {
5064 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5065 != PackageManager.PERMISSION_GRANTED) {
5066 String msg = "Permission Denial: forceStopPackage() from pid="
5067 + Binder.getCallingPid()
5068 + ", uid=" + Binder.getCallingUid()
5069 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005070 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005071 throw new SecurityException(msg);
5072 }
5073
5074 long callingId = Binder.clearCallingIdentity();
5075 try {
5076 IPackageManager pm = ActivityThread.getPackageManager();
5077 int pkgUid = -1;
5078 synchronized(this) {
5079 try {
5080 pkgUid = pm.getPackageUid(packageName);
5081 } catch (RemoteException e) {
5082 }
5083 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005084 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005085 return;
5086 }
5087 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005088 }
5089 } finally {
5090 Binder.restoreCallingIdentity(callingId);
5091 }
5092 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005093
5094 /*
5095 * The pkg name and uid have to be specified.
5096 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5097 */
5098 public void killApplicationWithUid(String pkg, int uid) {
5099 if (pkg == null) {
5100 return;
5101 }
5102 // Make sure the uid is valid.
5103 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005104 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005105 return;
5106 }
5107 int callerUid = Binder.getCallingUid();
5108 // Only the system server can kill an application
5109 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005110 // Post an aysnc message to kill the application
5111 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5112 msg.arg1 = uid;
5113 msg.arg2 = 0;
5114 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005115 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005116 } else {
5117 throw new SecurityException(callerUid + " cannot kill pkg: " +
5118 pkg);
5119 }
5120 }
5121
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005122 public void closeSystemDialogs(String reason) {
5123 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5124 if (reason != null) {
5125 intent.putExtra("reason", reason);
5126 }
5127
5128 final int uid = Binder.getCallingUid();
5129 final long origId = Binder.clearCallingIdentity();
5130 synchronized (this) {
5131 int i = mWatchers.beginBroadcast();
5132 while (i > 0) {
5133 i--;
5134 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5135 if (w != null) {
5136 try {
5137 w.closingSystemDialogs(reason);
5138 } catch (RemoteException e) {
5139 }
5140 }
5141 }
5142 mWatchers.finishBroadcast();
5143
Dianne Hackbornffa42482009-09-23 22:20:11 -07005144 mWindowManager.closeSystemDialogs(reason);
5145
5146 for (i=mHistory.size()-1; i>=0; i--) {
5147 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5148 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5149 finishActivityLocked(r, i,
5150 Activity.RESULT_CANCELED, null, "close-sys");
5151 }
5152 }
5153
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005154 broadcastIntentLocked(null, null, intent, null,
5155 null, 0, null, null, null, false, false, -1, uid);
5156 }
5157 Binder.restoreCallingIdentity(origId);
5158 }
5159
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005160 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005161 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005162 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5163 for (int i=pids.length-1; i>=0; i--) {
5164 infos[i] = new Debug.MemoryInfo();
5165 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005166 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005167 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005168 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005169
5170 public void killApplicationProcess(String processName, int uid) {
5171 if (processName == null) {
5172 return;
5173 }
5174
5175 int callerUid = Binder.getCallingUid();
5176 // Only the system server can kill an application
5177 if (callerUid == Process.SYSTEM_UID) {
5178 synchronized (this) {
5179 ProcessRecord app = getProcessRecordLocked(processName, uid);
5180 if (app != null) {
5181 try {
5182 app.thread.scheduleSuicide();
5183 } catch (RemoteException e) {
5184 // If the other end already died, then our work here is done.
5185 }
5186 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005187 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005188 + processName + " / " + uid);
5189 }
5190 }
5191 } else {
5192 throw new SecurityException(callerUid + " cannot kill app process: " +
5193 processName);
5194 }
5195 }
5196
Dianne Hackborn03abb812010-01-04 18:43:19 -08005197 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005198 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005199 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5200 Uri.fromParts("package", packageName, null));
5201 intent.putExtra(Intent.EXTRA_UID, uid);
5202 broadcastIntentLocked(null, null, intent,
5203 null, null, 0, null, null, null,
5204 false, false, MY_PID, Process.SYSTEM_UID);
5205 }
5206
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005207 private final boolean killPackageProcessesLocked(String packageName, int uid,
5208 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005209 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210
Dianne Hackborn03abb812010-01-04 18:43:19 -08005211 // Remove all processes this package may have touched: all with the
5212 // same UID (except for the system or root user), and all whose name
5213 // matches the package name.
5214 final String procNamePrefix = packageName + ":";
5215 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5216 final int NA = apps.size();
5217 for (int ia=0; ia<NA; ia++) {
5218 ProcessRecord app = apps.valueAt(ia);
5219 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005220 if (doit) {
5221 procs.add(app);
5222 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005223 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5224 || app.processName.equals(packageName)
5225 || app.processName.startsWith(procNamePrefix)) {
5226 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005227 if (!doit) {
5228 return true;
5229 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005230 app.removed = true;
5231 procs.add(app);
5232 }
5233 }
5234 }
5235 }
5236
5237 int N = procs.size();
5238 for (int i=0; i<N; i++) {
5239 removeProcessLocked(procs.get(i), callerWillRestart);
5240 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005241 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005242 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005243
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005244 private final boolean forceStopPackageLocked(String name, int uid,
5245 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005246 int i, N;
5247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 if (uid < 0) {
5249 try {
5250 uid = ActivityThread.getPackageManager().getPackageUid(name);
5251 } catch (RemoteException e) {
5252 }
5253 }
5254
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005255 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005256 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005257
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005258 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5259 while (badApps.hasNext()) {
5260 SparseArray<Long> ba = badApps.next();
5261 if (ba.get(uid) != null) {
5262 badApps.remove();
5263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005264 }
5265 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005266
5267 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5268 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269
5270 for (i=mHistory.size()-1; i>=0; i--) {
5271 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5272 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005273 if (!doit) {
5274 return true;
5275 }
5276 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005277 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 if (r.app != null) {
5279 r.app.removed = true;
5280 }
5281 r.app = null;
5282 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5283 }
5284 }
5285
5286 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5287 for (ServiceRecord service : mServices.values()) {
5288 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005289 if (!doit) {
5290 return true;
5291 }
5292 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005293 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 if (service.app != null) {
5295 service.app.removed = true;
5296 }
5297 service.app = null;
5298 services.add(service);
5299 }
5300 }
5301
5302 N = services.size();
5303 for (i=0; i<N; i++) {
5304 bringDownServiceLocked(services.get(i), true);
5305 }
5306
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005307 if (doit) {
5308 if (purgeCache) {
5309 AttributeCache ac = AttributeCache.instance();
5310 if (ac != null) {
5311 ac.removePackage(name);
5312 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005313 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005314 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005315 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005316
5317 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 }
5319
5320 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5321 final String name = app.processName;
5322 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005323 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 TAG, "Force removing process " + app + " (" + name
5325 + "/" + uid + ")");
5326
5327 mProcessNames.remove(name, uid);
5328 boolean needRestart = false;
5329 if (app.pid > 0 && app.pid != MY_PID) {
5330 int pid = app.pid;
5331 synchronized (mPidsSelfLocked) {
5332 mPidsSelfLocked.remove(pid);
5333 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5334 }
5335 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005336 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005337 Process.killProcess(pid);
5338
5339 if (app.persistent) {
5340 if (!callerWillRestart) {
5341 addAppLocked(app.info);
5342 } else {
5343 needRestart = true;
5344 }
5345 }
5346 } else {
5347 mRemovedProcesses.add(app);
5348 }
5349
5350 return needRestart;
5351 }
5352
5353 private final void processStartTimedOutLocked(ProcessRecord app) {
5354 final int pid = app.pid;
5355 boolean gone = false;
5356 synchronized (mPidsSelfLocked) {
5357 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5358 if (knownApp != null && knownApp.thread == null) {
5359 mPidsSelfLocked.remove(pid);
5360 gone = true;
5361 }
5362 }
5363
5364 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005365 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005366 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005367 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005369 // Take care of any launching providers waiting for this process.
5370 checkAppInLaunchingProvidersLocked(app, true);
5371 // Take care of any services that are waiting for the process.
5372 for (int i=0; i<mPendingServices.size(); i++) {
5373 ServiceRecord sr = mPendingServices.get(i);
5374 if (app.info.uid == sr.appInfo.uid
5375 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005376 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005377 mPendingServices.remove(i);
5378 i--;
5379 bringDownServiceLocked(sr, true);
5380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005381 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005382 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005383 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005384 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005385 try {
5386 IBackupManager bm = IBackupManager.Stub.asInterface(
5387 ServiceManager.getService(Context.BACKUP_SERVICE));
5388 bm.agentDisconnected(app.info.packageName);
5389 } catch (RemoteException e) {
5390 // Can't happen; the backup manager is local
5391 }
5392 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005393 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005394 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005395 mPendingBroadcast = null;
5396 scheduleBroadcastsLocked();
5397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005398 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005399 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005400 }
5401 }
5402
5403 private final boolean attachApplicationLocked(IApplicationThread thread,
5404 int pid) {
5405
5406 // Find the application record that is being attached... either via
5407 // the pid if we are running in multiple processes, or just pull the
5408 // next app record if we are emulating process with anonymous threads.
5409 ProcessRecord app;
5410 if (pid != MY_PID && pid >= 0) {
5411 synchronized (mPidsSelfLocked) {
5412 app = mPidsSelfLocked.get(pid);
5413 }
5414 } else if (mStartingProcesses.size() > 0) {
5415 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005416 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005417 } else {
5418 app = null;
5419 }
5420
5421 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005422 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005423 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005424 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005425 if (pid > 0 && pid != MY_PID) {
5426 Process.killProcess(pid);
5427 } else {
5428 try {
5429 thread.scheduleExit();
5430 } catch (Exception e) {
5431 // Ignore exceptions.
5432 }
5433 }
5434 return false;
5435 }
5436
5437 // If this application record is still attached to a previous
5438 // process, clean it up now.
5439 if (app.thread != null) {
5440 handleAppDiedLocked(app, true);
5441 }
5442
5443 // Tell the process all about itself.
5444
Joe Onorato8a9b2202010-02-26 18:56:32 -08005445 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 TAG, "Binding process pid " + pid + " to record " + app);
5447
5448 String processName = app.processName;
5449 try {
5450 thread.asBinder().linkToDeath(new AppDeathRecipient(
5451 app, pid, thread), 0);
5452 } catch (RemoteException e) {
5453 app.resetPackageList();
5454 startProcessLocked(app, "link fail", processName);
5455 return false;
5456 }
5457
Doug Zongker2bec3d42009-12-04 12:52:44 -08005458 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459
5460 app.thread = thread;
5461 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005462 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5463 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005464 app.forcingToForeground = null;
5465 app.foregroundServices = false;
5466 app.debugging = false;
5467
5468 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5469
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005470 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5471 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005473 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005474 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005475 }
5476
Joe Onorato8a9b2202010-02-26 18:56:32 -08005477 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 TAG, "New app record " + app
5479 + " thread=" + thread.asBinder() + " pid=" + pid);
5480 try {
5481 int testMode = IApplicationThread.DEBUG_OFF;
5482 if (mDebugApp != null && mDebugApp.equals(processName)) {
5483 testMode = mWaitForDebugger
5484 ? IApplicationThread.DEBUG_WAIT
5485 : IApplicationThread.DEBUG_ON;
5486 app.debugging = true;
5487 if (mDebugTransient) {
5488 mDebugApp = mOrigDebugApp;
5489 mWaitForDebugger = mOrigWaitForDebugger;
5490 }
5491 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005492
Christopher Tate181fafa2009-05-14 11:12:14 -07005493 // If the app is being launched for restore or full backup, set it up specially
5494 boolean isRestrictedBackupMode = false;
5495 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5496 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5497 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5498 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005499
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005500 ensurePackageDexOpt(app.instrumentationInfo != null
5501 ? app.instrumentationInfo.packageName
5502 : app.info.packageName);
5503 if (app.instrumentationClass != null) {
5504 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005505 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005506 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005507 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005508 thread.bindApplication(processName, app.instrumentationInfo != null
5509 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 app.instrumentationClass, app.instrumentationProfileFile,
5511 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005512 isRestrictedBackupMode || !normalMode,
5513 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005514 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005515 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005516 } catch (Exception e) {
5517 // todo: Yikes! What should we do? For now we will try to
5518 // start another process, but that could easily get us in
5519 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005520 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521
5522 app.resetPackageList();
5523 startProcessLocked(app, "bind fail", processName);
5524 return false;
5525 }
5526
5527 // Remove this record from the list of starting applications.
5528 mPersistentStartingProcesses.remove(app);
5529 mProcessesOnHold.remove(app);
5530
5531 boolean badApp = false;
5532 boolean didSomething = false;
5533
5534 // See if the top visible activity is waiting to run in this process...
5535 HistoryRecord hr = topRunningActivityLocked(null);
5536 if (hr != null) {
5537 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5538 && processName.equals(hr.processName)) {
5539 try {
5540 if (realStartActivityLocked(hr, app, true, true)) {
5541 didSomething = true;
5542 }
5543 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005544 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005545 + hr.intent.getComponent().flattenToShortString(), e);
5546 badApp = true;
5547 }
5548 } else {
5549 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5550 }
5551 }
5552
5553 // Find any services that should be running in this process...
5554 if (!badApp && mPendingServices.size() > 0) {
5555 ServiceRecord sr = null;
5556 try {
5557 for (int i=0; i<mPendingServices.size(); i++) {
5558 sr = mPendingServices.get(i);
5559 if (app.info.uid != sr.appInfo.uid
5560 || !processName.equals(sr.processName)) {
5561 continue;
5562 }
5563
5564 mPendingServices.remove(i);
5565 i--;
5566 realStartServiceLocked(sr, app);
5567 didSomething = true;
5568 }
5569 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005570 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005571 + sr.shortName, e);
5572 badApp = true;
5573 }
5574 }
5575
5576 // Check if the next broadcast receiver is in this process...
5577 BroadcastRecord br = mPendingBroadcast;
5578 if (!badApp && br != null && br.curApp == app) {
5579 try {
5580 mPendingBroadcast = null;
5581 processCurBroadcastLocked(br, app);
5582 didSomething = true;
5583 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005584 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005585 + br.curComponent.flattenToShortString(), e);
5586 badApp = true;
5587 logBroadcastReceiverDiscard(br);
5588 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5589 br.resultExtras, br.resultAbort, true);
5590 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005591 // We need to reset the state if we fails to start the receiver.
5592 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005593 }
5594 }
5595
Christopher Tate181fafa2009-05-14 11:12:14 -07005596 // Check whether the next backup agent is in this process...
5597 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005598 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005599 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005600 try {
5601 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5602 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005603 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005604 e.printStackTrace();
5605 }
5606 }
5607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005608 if (badApp) {
5609 // todo: Also need to kill application to deal with all
5610 // kinds of exceptions.
5611 handleAppDiedLocked(app, false);
5612 return false;
5613 }
5614
5615 if (!didSomething) {
5616 updateOomAdjLocked();
5617 }
5618
5619 return true;
5620 }
5621
5622 public final void attachApplication(IApplicationThread thread) {
5623 synchronized (this) {
5624 int callingPid = Binder.getCallingPid();
5625 final long origId = Binder.clearCallingIdentity();
5626 attachApplicationLocked(thread, callingPid);
5627 Binder.restoreCallingIdentity(origId);
5628 }
5629 }
5630
Dianne Hackborne88846e2009-09-30 21:34:25 -07005631 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005633 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005634 Binder.restoreCallingIdentity(origId);
5635 }
5636
5637 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5638 boolean remove) {
5639 int N = mStoppingActivities.size();
5640 if (N <= 0) return null;
5641
5642 ArrayList<HistoryRecord> stops = null;
5643
5644 final boolean nowVisible = mResumedActivity != null
5645 && mResumedActivity.nowVisible
5646 && !mResumedActivity.waitingVisible;
5647 for (int i=0; i<N; i++) {
5648 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005649 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005650 + nowVisible + " waitingVisible=" + s.waitingVisible
5651 + " finishing=" + s.finishing);
5652 if (s.waitingVisible && nowVisible) {
5653 mWaitingVisibleActivities.remove(s);
5654 s.waitingVisible = false;
5655 if (s.finishing) {
5656 // If this activity is finishing, it is sitting on top of
5657 // everyone else but we now know it is no longer needed...
5658 // so get rid of it. Otherwise, we need to go through the
5659 // normal flow and hide it once we determine that it is
5660 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005661 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005662 mWindowManager.setAppVisibility(s, false);
5663 }
5664 }
5665 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005666 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667 if (stops == null) {
5668 stops = new ArrayList<HistoryRecord>();
5669 }
5670 stops.add(s);
5671 mStoppingActivities.remove(i);
5672 N--;
5673 i--;
5674 }
5675 }
5676
5677 return stops;
5678 }
5679
5680 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005681 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005682 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005683 mWindowManager.enableScreenAfterBoot();
5684 }
5685
Dianne Hackborne88846e2009-09-30 21:34:25 -07005686 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5687 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005688 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005689
5690 ArrayList<HistoryRecord> stops = null;
5691 ArrayList<HistoryRecord> finishes = null;
5692 ArrayList<HistoryRecord> thumbnails = null;
5693 int NS = 0;
5694 int NF = 0;
5695 int NT = 0;
5696 IApplicationThread sendThumbnail = null;
5697 boolean booting = false;
5698 boolean enableScreen = false;
5699
5700 synchronized (this) {
5701 if (token != null) {
5702 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5703 }
5704
5705 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005706 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005707 if (index >= 0) {
5708 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5709
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005710 if (fromTimeout) {
5711 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5712 }
5713
Dianne Hackborne88846e2009-09-30 21:34:25 -07005714 // This is a hack to semi-deal with a race condition
5715 // in the client where it can be constructed with a
5716 // newer configuration from when we asked it to launch.
5717 // We'll update with whatever configuration it now says
5718 // it used to launch.
5719 if (config != null) {
5720 r.configuration = config;
5721 }
5722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005723 // No longer need to keep the device awake.
5724 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5725 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5726 mLaunchingActivity.release();
5727 }
5728
5729 // We are now idle. If someone is waiting for a thumbnail from
5730 // us, we can now deliver.
5731 r.idle = true;
5732 scheduleAppGcsLocked();
5733 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5734 sendThumbnail = r.app.thread;
5735 r.thumbnailNeeded = false;
5736 }
5737
5738 // If this activity is fullscreen, set up to hide those under it.
5739
Joe Onorato8a9b2202010-02-26 18:56:32 -08005740 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 ensureActivitiesVisibleLocked(null, 0);
5742
Joe Onorato8a9b2202010-02-26 18:56:32 -08005743 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005744 if (!mBooted && !fromTimeout) {
5745 mBooted = true;
5746 enableScreen = true;
5747 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005748
5749 } else if (fromTimeout) {
5750 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005751 }
5752
5753 // Atomically retrieve all of the other things to do.
5754 stops = processStoppingActivitiesLocked(true);
5755 NS = stops != null ? stops.size() : 0;
5756 if ((NF=mFinishingActivities.size()) > 0) {
5757 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5758 mFinishingActivities.clear();
5759 }
5760 if ((NT=mCancelledThumbnails.size()) > 0) {
5761 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5762 mCancelledThumbnails.clear();
5763 }
5764
5765 booting = mBooting;
5766 mBooting = false;
5767 }
5768
5769 int i;
5770
5771 // Send thumbnail if requested.
5772 if (sendThumbnail != null) {
5773 try {
5774 sendThumbnail.requestThumbnail(token);
5775 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005776 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005777 sendPendingThumbnail(null, token, null, null, true);
5778 }
5779 }
5780
5781 // Stop any activities that are scheduled to do so but have been
5782 // waiting for the next one to start.
5783 for (i=0; i<NS; i++) {
5784 HistoryRecord r = (HistoryRecord)stops.get(i);
5785 synchronized (this) {
5786 if (r.finishing) {
5787 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5788 } else {
5789 stopActivityLocked(r);
5790 }
5791 }
5792 }
5793
5794 // Finish any activities that are scheduled to do so but have been
5795 // waiting for the next one to start.
5796 for (i=0; i<NF; i++) {
5797 HistoryRecord r = (HistoryRecord)finishes.get(i);
5798 synchronized (this) {
5799 destroyActivityLocked(r, true);
5800 }
5801 }
5802
5803 // Report back to any thumbnail receivers.
5804 for (i=0; i<NT; i++) {
5805 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5806 sendPendingThumbnail(r, null, null, null, true);
5807 }
5808
5809 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005810 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 }
5812
5813 trimApplications();
5814 //dump();
5815 //mWindowManager.dump();
5816
5817 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818 enableScreenAfterBoot();
5819 }
5820 }
5821
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005822 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005823 IntentFilter pkgFilter = new IntentFilter();
5824 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5825 pkgFilter.addDataScheme("package");
5826 mContext.registerReceiver(new BroadcastReceiver() {
5827 @Override
5828 public void onReceive(Context context, Intent intent) {
5829 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5830 if (pkgs != null) {
5831 for (String pkg : pkgs) {
5832 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5833 setResultCode(Activity.RESULT_OK);
5834 return;
5835 }
5836 }
5837 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005838 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005839 }, pkgFilter);
5840
5841 synchronized (this) {
5842 // Ensure that any processes we had put on hold are now started
5843 // up.
5844 final int NP = mProcessesOnHold.size();
5845 if (NP > 0) {
5846 ArrayList<ProcessRecord> procs =
5847 new ArrayList<ProcessRecord>(mProcessesOnHold);
5848 for (int ip=0; ip<NP; ip++) {
5849 this.startProcessLocked(procs.get(ip), "on-hold", null);
5850 }
5851 }
5852
5853 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5854 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005855 broadcastIntentLocked(null, null,
5856 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5857 null, null, 0, null, null,
5858 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5859 false, false, MY_PID, Process.SYSTEM_UID);
5860 }
5861 }
5862 }
5863
5864 final void ensureBootCompleted() {
5865 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005866 boolean enableScreen;
5867 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005868 booting = mBooting;
5869 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005870 enableScreen = !mBooted;
5871 mBooted = true;
5872 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005873
5874 if (booting) {
5875 finishBooting();
5876 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005877
5878 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005879 enableScreenAfterBoot();
5880 }
5881 }
5882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005883 public final void activityPaused(IBinder token, Bundle icicle) {
5884 // Refuse possible leaked file descriptors
5885 if (icicle != null && icicle.hasFileDescriptors()) {
5886 throw new IllegalArgumentException("File descriptors passed in Bundle");
5887 }
5888
5889 final long origId = Binder.clearCallingIdentity();
5890 activityPaused(token, icicle, false);
5891 Binder.restoreCallingIdentity(origId);
5892 }
5893
5894 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005895 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005896 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5897 + ", timeout=" + timeout);
5898
5899 HistoryRecord r = null;
5900
5901 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005902 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 if (index >= 0) {
5904 r = (HistoryRecord)mHistory.get(index);
5905 if (!timeout) {
5906 r.icicle = icicle;
5907 r.haveState = true;
5908 }
5909 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5910 if (mPausingActivity == r) {
5911 r.state = ActivityState.PAUSED;
5912 completePauseLocked();
5913 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005914 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 System.identityHashCode(r), r.shortComponentName,
5916 mPausingActivity != null
5917 ? mPausingActivity.shortComponentName : "(none)");
5918 }
5919 }
5920 }
5921 }
5922
5923 public final void activityStopped(IBinder token, Bitmap thumbnail,
5924 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005925 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005926 TAG, "Activity stopped: token=" + token);
5927
5928 HistoryRecord r = null;
5929
5930 final long origId = Binder.clearCallingIdentity();
5931
5932 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005933 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005934 if (index >= 0) {
5935 r = (HistoryRecord)mHistory.get(index);
5936 r.thumbnail = thumbnail;
5937 r.description = description;
5938 r.stopped = true;
5939 r.state = ActivityState.STOPPED;
5940 if (!r.finishing) {
5941 if (r.configDestroy) {
5942 destroyActivityLocked(r, true);
5943 resumeTopActivityLocked(null);
5944 }
5945 }
5946 }
5947 }
5948
5949 if (r != null) {
5950 sendPendingThumbnail(r, null, null, null, false);
5951 }
5952
5953 trimApplications();
5954
5955 Binder.restoreCallingIdentity(origId);
5956 }
5957
5958 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005959 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 synchronized (this) {
5961 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5962
Dianne Hackborn75b03852009-06-12 15:43:26 -07005963 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 if (index >= 0) {
5965 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5966 if (r.state == ActivityState.DESTROYING) {
5967 final long origId = Binder.clearCallingIdentity();
5968 removeActivityFromHistoryLocked(r);
5969 Binder.restoreCallingIdentity(origId);
5970 }
5971 }
5972 }
5973 }
5974
5975 public String getCallingPackage(IBinder token) {
5976 synchronized (this) {
5977 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005978 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 }
5980 }
5981
5982 public ComponentName getCallingActivity(IBinder token) {
5983 synchronized (this) {
5984 HistoryRecord r = getCallingRecordLocked(token);
5985 return r != null ? r.intent.getComponent() : null;
5986 }
5987 }
5988
5989 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005990 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005991 if (index >= 0) {
5992 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5993 if (r != null) {
5994 return r.resultTo;
5995 }
5996 }
5997 return null;
5998 }
5999
6000 public ComponentName getActivityClassForToken(IBinder token) {
6001 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006002 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006003 if (index >= 0) {
6004 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6005 return r.intent.getComponent();
6006 }
6007 return null;
6008 }
6009 }
6010
6011 public String getPackageForToken(IBinder token) {
6012 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006013 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006014 if (index >= 0) {
6015 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6016 return r.packageName;
6017 }
6018 return null;
6019 }
6020 }
6021
6022 public IIntentSender getIntentSender(int type,
6023 String packageName, IBinder token, String resultWho,
6024 int requestCode, Intent intent, String resolvedType, int flags) {
6025 // Refuse possible leaked file descriptors
6026 if (intent != null && intent.hasFileDescriptors() == true) {
6027 throw new IllegalArgumentException("File descriptors passed in Intent");
6028 }
6029
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006030 if (type == INTENT_SENDER_BROADCAST) {
6031 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6032 throw new IllegalArgumentException(
6033 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6034 }
6035 }
6036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006037 synchronized(this) {
6038 int callingUid = Binder.getCallingUid();
6039 try {
6040 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6041 Process.supportsProcesses()) {
6042 int uid = ActivityThread.getPackageManager()
6043 .getPackageUid(packageName);
6044 if (uid != Binder.getCallingUid()) {
6045 String msg = "Permission Denial: getIntentSender() from pid="
6046 + Binder.getCallingPid()
6047 + ", uid=" + Binder.getCallingUid()
6048 + ", (need uid=" + uid + ")"
6049 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006050 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006051 throw new SecurityException(msg);
6052 }
6053 }
6054 } catch (RemoteException e) {
6055 throw new SecurityException(e);
6056 }
6057 HistoryRecord activity = null;
6058 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006059 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006060 if (index < 0) {
6061 return null;
6062 }
6063 activity = (HistoryRecord)mHistory.get(index);
6064 if (activity.finishing) {
6065 return null;
6066 }
6067 }
6068
6069 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6070 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6071 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6072 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6073 |PendingIntent.FLAG_UPDATE_CURRENT);
6074
6075 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6076 type, packageName, activity, resultWho,
6077 requestCode, intent, resolvedType, flags);
6078 WeakReference<PendingIntentRecord> ref;
6079 ref = mIntentSenderRecords.get(key);
6080 PendingIntentRecord rec = ref != null ? ref.get() : null;
6081 if (rec != null) {
6082 if (!cancelCurrent) {
6083 if (updateCurrent) {
6084 rec.key.requestIntent.replaceExtras(intent);
6085 }
6086 return rec;
6087 }
6088 rec.canceled = true;
6089 mIntentSenderRecords.remove(key);
6090 }
6091 if (noCreate) {
6092 return rec;
6093 }
6094 rec = new PendingIntentRecord(this, key, callingUid);
6095 mIntentSenderRecords.put(key, rec.ref);
6096 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6097 if (activity.pendingResults == null) {
6098 activity.pendingResults
6099 = new HashSet<WeakReference<PendingIntentRecord>>();
6100 }
6101 activity.pendingResults.add(rec.ref);
6102 }
6103 return rec;
6104 }
6105 }
6106
6107 public void cancelIntentSender(IIntentSender sender) {
6108 if (!(sender instanceof PendingIntentRecord)) {
6109 return;
6110 }
6111 synchronized(this) {
6112 PendingIntentRecord rec = (PendingIntentRecord)sender;
6113 try {
6114 int uid = ActivityThread.getPackageManager()
6115 .getPackageUid(rec.key.packageName);
6116 if (uid != Binder.getCallingUid()) {
6117 String msg = "Permission Denial: cancelIntentSender() from pid="
6118 + Binder.getCallingPid()
6119 + ", uid=" + Binder.getCallingUid()
6120 + " is not allowed to cancel packges "
6121 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006122 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006123 throw new SecurityException(msg);
6124 }
6125 } catch (RemoteException e) {
6126 throw new SecurityException(e);
6127 }
6128 cancelIntentSenderLocked(rec, true);
6129 }
6130 }
6131
6132 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6133 rec.canceled = true;
6134 mIntentSenderRecords.remove(rec.key);
6135 if (cleanActivity && rec.key.activity != null) {
6136 rec.key.activity.pendingResults.remove(rec.ref);
6137 }
6138 }
6139
6140 public String getPackageForIntentSender(IIntentSender pendingResult) {
6141 if (!(pendingResult instanceof PendingIntentRecord)) {
6142 return null;
6143 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006144 try {
6145 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6146 return res.key.packageName;
6147 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006148 }
6149 return null;
6150 }
6151
6152 public void setProcessLimit(int max) {
6153 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6154 "setProcessLimit()");
6155 mProcessLimit = max;
6156 }
6157
6158 public int getProcessLimit() {
6159 return mProcessLimit;
6160 }
6161
6162 void foregroundTokenDied(ForegroundToken token) {
6163 synchronized (ActivityManagerService.this) {
6164 synchronized (mPidsSelfLocked) {
6165 ForegroundToken cur
6166 = mForegroundProcesses.get(token.pid);
6167 if (cur != token) {
6168 return;
6169 }
6170 mForegroundProcesses.remove(token.pid);
6171 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6172 if (pr == null) {
6173 return;
6174 }
6175 pr.forcingToForeground = null;
6176 pr.foregroundServices = false;
6177 }
6178 updateOomAdjLocked();
6179 }
6180 }
6181
6182 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6183 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6184 "setProcessForeground()");
6185 synchronized(this) {
6186 boolean changed = false;
6187
6188 synchronized (mPidsSelfLocked) {
6189 ProcessRecord pr = mPidsSelfLocked.get(pid);
6190 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006191 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006192 return;
6193 }
6194 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6195 if (oldToken != null) {
6196 oldToken.token.unlinkToDeath(oldToken, 0);
6197 mForegroundProcesses.remove(pid);
6198 pr.forcingToForeground = null;
6199 changed = true;
6200 }
6201 if (isForeground && token != null) {
6202 ForegroundToken newToken = new ForegroundToken() {
6203 public void binderDied() {
6204 foregroundTokenDied(this);
6205 }
6206 };
6207 newToken.pid = pid;
6208 newToken.token = token;
6209 try {
6210 token.linkToDeath(newToken, 0);
6211 mForegroundProcesses.put(pid, newToken);
6212 pr.forcingToForeground = token;
6213 changed = true;
6214 } catch (RemoteException e) {
6215 // If the process died while doing this, we will later
6216 // do the cleanup with the process death link.
6217 }
6218 }
6219 }
6220
6221 if (changed) {
6222 updateOomAdjLocked();
6223 }
6224 }
6225 }
6226
6227 // =========================================================
6228 // PERMISSIONS
6229 // =========================================================
6230
6231 static class PermissionController extends IPermissionController.Stub {
6232 ActivityManagerService mActivityManagerService;
6233 PermissionController(ActivityManagerService activityManagerService) {
6234 mActivityManagerService = activityManagerService;
6235 }
6236
6237 public boolean checkPermission(String permission, int pid, int uid) {
6238 return mActivityManagerService.checkPermission(permission, pid,
6239 uid) == PackageManager.PERMISSION_GRANTED;
6240 }
6241 }
6242
6243 /**
6244 * This can be called with or without the global lock held.
6245 */
6246 int checkComponentPermission(String permission, int pid, int uid,
6247 int reqUid) {
6248 // We might be performing an operation on behalf of an indirect binder
6249 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6250 // client identity accordingly before proceeding.
6251 Identity tlsIdentity = sCallerIdentity.get();
6252 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006253 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006254 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6255 uid = tlsIdentity.uid;
6256 pid = tlsIdentity.pid;
6257 }
6258
6259 // Root, system server and our own process get to do everything.
6260 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6261 !Process.supportsProcesses()) {
6262 return PackageManager.PERMISSION_GRANTED;
6263 }
6264 // If the target requires a specific UID, always fail for others.
6265 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006266 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006267 return PackageManager.PERMISSION_DENIED;
6268 }
6269 if (permission == null) {
6270 return PackageManager.PERMISSION_GRANTED;
6271 }
6272 try {
6273 return ActivityThread.getPackageManager()
6274 .checkUidPermission(permission, uid);
6275 } catch (RemoteException e) {
6276 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006277 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006278 }
6279 return PackageManager.PERMISSION_DENIED;
6280 }
6281
6282 /**
6283 * As the only public entry point for permissions checking, this method
6284 * can enforce the semantic that requesting a check on a null global
6285 * permission is automatically denied. (Internally a null permission
6286 * string is used when calling {@link #checkComponentPermission} in cases
6287 * when only uid-based security is needed.)
6288 *
6289 * This can be called with or without the global lock held.
6290 */
6291 public int checkPermission(String permission, int pid, int uid) {
6292 if (permission == null) {
6293 return PackageManager.PERMISSION_DENIED;
6294 }
6295 return checkComponentPermission(permission, pid, uid, -1);
6296 }
6297
6298 /**
6299 * Binder IPC calls go through the public entry point.
6300 * This can be called with or without the global lock held.
6301 */
6302 int checkCallingPermission(String permission) {
6303 return checkPermission(permission,
6304 Binder.getCallingPid(),
6305 Binder.getCallingUid());
6306 }
6307
6308 /**
6309 * This can be called with or without the global lock held.
6310 */
6311 void enforceCallingPermission(String permission, String func) {
6312 if (checkCallingPermission(permission)
6313 == PackageManager.PERMISSION_GRANTED) {
6314 return;
6315 }
6316
6317 String msg = "Permission Denial: " + func + " from pid="
6318 + Binder.getCallingPid()
6319 + ", uid=" + Binder.getCallingUid()
6320 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006321 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 throw new SecurityException(msg);
6323 }
6324
6325 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6326 ProviderInfo pi, int uid, int modeFlags) {
6327 try {
6328 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6329 if ((pi.readPermission != null) &&
6330 (pm.checkUidPermission(pi.readPermission, uid)
6331 != PackageManager.PERMISSION_GRANTED)) {
6332 return false;
6333 }
6334 }
6335 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6336 if ((pi.writePermission != null) &&
6337 (pm.checkUidPermission(pi.writePermission, uid)
6338 != PackageManager.PERMISSION_GRANTED)) {
6339 return false;
6340 }
6341 }
6342 return true;
6343 } catch (RemoteException e) {
6344 return false;
6345 }
6346 }
6347
6348 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6349 int modeFlags) {
6350 // Root gets to do everything.
6351 if (uid == 0 || !Process.supportsProcesses()) {
6352 return true;
6353 }
6354 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6355 if (perms == null) return false;
6356 UriPermission perm = perms.get(uri);
6357 if (perm == null) return false;
6358 return (modeFlags&perm.modeFlags) == modeFlags;
6359 }
6360
6361 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6362 // Another redirected-binder-call permissions check as in
6363 // {@link checkComponentPermission}.
6364 Identity tlsIdentity = sCallerIdentity.get();
6365 if (tlsIdentity != null) {
6366 uid = tlsIdentity.uid;
6367 pid = tlsIdentity.pid;
6368 }
6369
6370 // Our own process gets to do everything.
6371 if (pid == MY_PID) {
6372 return PackageManager.PERMISSION_GRANTED;
6373 }
6374 synchronized(this) {
6375 return checkUriPermissionLocked(uri, uid, modeFlags)
6376 ? PackageManager.PERMISSION_GRANTED
6377 : PackageManager.PERMISSION_DENIED;
6378 }
6379 }
6380
6381 private void grantUriPermissionLocked(int callingUid,
6382 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6383 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6384 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6385 if (modeFlags == 0) {
6386 return;
6387 }
6388
Joe Onorato8a9b2202010-02-26 18:56:32 -08006389 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006390 "Requested grant " + targetPkg + " permission to " + uri);
6391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006392 final IPackageManager pm = ActivityThread.getPackageManager();
6393
6394 // If this is not a content: uri, we can't do anything with it.
6395 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006396 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006397 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006398 return;
6399 }
6400
6401 String name = uri.getAuthority();
6402 ProviderInfo pi = null;
6403 ContentProviderRecord cpr
6404 = (ContentProviderRecord)mProvidersByName.get(name);
6405 if (cpr != null) {
6406 pi = cpr.info;
6407 } else {
6408 try {
6409 pi = pm.resolveContentProvider(name,
6410 PackageManager.GET_URI_PERMISSION_PATTERNS);
6411 } catch (RemoteException ex) {
6412 }
6413 }
6414 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006415 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 return;
6417 }
6418
6419 int targetUid;
6420 try {
6421 targetUid = pm.getPackageUid(targetPkg);
6422 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006423 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006424 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006425 return;
6426 }
6427 } catch (RemoteException ex) {
6428 return;
6429 }
6430
6431 // First... does the target actually need this permission?
6432 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6433 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006434 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006435 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006436 return;
6437 }
6438
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006439 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 if (!pi.grantUriPermissions) {
6441 throw new SecurityException("Provider " + pi.packageName
6442 + "/" + pi.name
6443 + " does not allow granting of Uri permissions (uri "
6444 + uri + ")");
6445 }
6446 if (pi.uriPermissionPatterns != null) {
6447 final int N = pi.uriPermissionPatterns.length;
6448 boolean allowed = false;
6449 for (int i=0; i<N; i++) {
6450 if (pi.uriPermissionPatterns[i] != null
6451 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6452 allowed = true;
6453 break;
6454 }
6455 }
6456 if (!allowed) {
6457 throw new SecurityException("Provider " + pi.packageName
6458 + "/" + pi.name
6459 + " does not allow granting of permission to path of Uri "
6460 + uri);
6461 }
6462 }
6463
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006464 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 // this uri?
6466 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6467 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6468 throw new SecurityException("Uid " + callingUid
6469 + " does not have permission to uri " + uri);
6470 }
6471 }
6472
6473 // Okay! So here we are: the caller has the assumed permission
6474 // to the uri, and the target doesn't. Let's now give this to
6475 // the target.
6476
Joe Onorato8a9b2202010-02-26 18:56:32 -08006477 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006478 "Granting " + targetPkg + " permission to " + uri);
6479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 HashMap<Uri, UriPermission> targetUris
6481 = mGrantedUriPermissions.get(targetUid);
6482 if (targetUris == null) {
6483 targetUris = new HashMap<Uri, UriPermission>();
6484 mGrantedUriPermissions.put(targetUid, targetUris);
6485 }
6486
6487 UriPermission perm = targetUris.get(uri);
6488 if (perm == null) {
6489 perm = new UriPermission(targetUid, uri);
6490 targetUris.put(uri, perm);
6491
6492 }
6493 perm.modeFlags |= modeFlags;
6494 if (activity == null) {
6495 perm.globalModeFlags |= modeFlags;
6496 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6497 perm.readActivities.add(activity);
6498 if (activity.readUriPermissions == null) {
6499 activity.readUriPermissions = new HashSet<UriPermission>();
6500 }
6501 activity.readUriPermissions.add(perm);
6502 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6503 perm.writeActivities.add(activity);
6504 if (activity.writeUriPermissions == null) {
6505 activity.writeUriPermissions = new HashSet<UriPermission>();
6506 }
6507 activity.writeUriPermissions.add(perm);
6508 }
6509 }
6510
6511 private void grantUriPermissionFromIntentLocked(int callingUid,
6512 String targetPkg, Intent intent, HistoryRecord activity) {
6513 if (intent == null) {
6514 return;
6515 }
6516 Uri data = intent.getData();
6517 if (data == null) {
6518 return;
6519 }
6520 grantUriPermissionLocked(callingUid, targetPkg, data,
6521 intent.getFlags(), activity);
6522 }
6523
6524 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6525 Uri uri, int modeFlags) {
6526 synchronized(this) {
6527 final ProcessRecord r = getRecordForAppLocked(caller);
6528 if (r == null) {
6529 throw new SecurityException("Unable to find app for caller "
6530 + caller
6531 + " when granting permission to uri " + uri);
6532 }
6533 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006534 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006535 return;
6536 }
6537 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006538 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006539 return;
6540 }
6541
6542 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6543 null);
6544 }
6545 }
6546
6547 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6548 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6549 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6550 HashMap<Uri, UriPermission> perms
6551 = mGrantedUriPermissions.get(perm.uid);
6552 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006553 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006554 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006555 perms.remove(perm.uri);
6556 if (perms.size() == 0) {
6557 mGrantedUriPermissions.remove(perm.uid);
6558 }
6559 }
6560 }
6561 }
6562
6563 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6564 if (activity.readUriPermissions != null) {
6565 for (UriPermission perm : activity.readUriPermissions) {
6566 perm.readActivities.remove(activity);
6567 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6568 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6569 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6570 removeUriPermissionIfNeededLocked(perm);
6571 }
6572 }
6573 }
6574 if (activity.writeUriPermissions != null) {
6575 for (UriPermission perm : activity.writeUriPermissions) {
6576 perm.writeActivities.remove(activity);
6577 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6578 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6579 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6580 removeUriPermissionIfNeededLocked(perm);
6581 }
6582 }
6583 }
6584 }
6585
6586 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6587 int modeFlags) {
6588 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6589 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6590 if (modeFlags == 0) {
6591 return;
6592 }
6593
Joe Onorato8a9b2202010-02-26 18:56:32 -08006594 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006595 "Revoking all granted permissions to " + uri);
6596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006597 final IPackageManager pm = ActivityThread.getPackageManager();
6598
6599 final String authority = uri.getAuthority();
6600 ProviderInfo pi = null;
6601 ContentProviderRecord cpr
6602 = (ContentProviderRecord)mProvidersByName.get(authority);
6603 if (cpr != null) {
6604 pi = cpr.info;
6605 } else {
6606 try {
6607 pi = pm.resolveContentProvider(authority,
6608 PackageManager.GET_URI_PERMISSION_PATTERNS);
6609 } catch (RemoteException ex) {
6610 }
6611 }
6612 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006613 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006614 return;
6615 }
6616
6617 // Does the caller have this permission on the URI?
6618 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6619 // Right now, if you are not the original owner of the permission,
6620 // you are not allowed to revoke it.
6621 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6622 throw new SecurityException("Uid " + callingUid
6623 + " does not have permission to uri " + uri);
6624 //}
6625 }
6626
6627 // Go through all of the permissions and remove any that match.
6628 final List<String> SEGMENTS = uri.getPathSegments();
6629 if (SEGMENTS != null) {
6630 final int NS = SEGMENTS.size();
6631 int N = mGrantedUriPermissions.size();
6632 for (int i=0; i<N; i++) {
6633 HashMap<Uri, UriPermission> perms
6634 = mGrantedUriPermissions.valueAt(i);
6635 Iterator<UriPermission> it = perms.values().iterator();
6636 toploop:
6637 while (it.hasNext()) {
6638 UriPermission perm = it.next();
6639 Uri targetUri = perm.uri;
6640 if (!authority.equals(targetUri.getAuthority())) {
6641 continue;
6642 }
6643 List<String> targetSegments = targetUri.getPathSegments();
6644 if (targetSegments == null) {
6645 continue;
6646 }
6647 if (targetSegments.size() < NS) {
6648 continue;
6649 }
6650 for (int j=0; j<NS; j++) {
6651 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6652 continue toploop;
6653 }
6654 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006655 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006656 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006657 perm.clearModes(modeFlags);
6658 if (perm.modeFlags == 0) {
6659 it.remove();
6660 }
6661 }
6662 if (perms.size() == 0) {
6663 mGrantedUriPermissions.remove(
6664 mGrantedUriPermissions.keyAt(i));
6665 N--;
6666 i--;
6667 }
6668 }
6669 }
6670 }
6671
6672 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6673 int modeFlags) {
6674 synchronized(this) {
6675 final ProcessRecord r = getRecordForAppLocked(caller);
6676 if (r == null) {
6677 throw new SecurityException("Unable to find app for caller "
6678 + caller
6679 + " when revoking permission to uri " + uri);
6680 }
6681 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006682 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006683 return;
6684 }
6685
6686 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6687 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6688 if (modeFlags == 0) {
6689 return;
6690 }
6691
6692 final IPackageManager pm = ActivityThread.getPackageManager();
6693
6694 final String authority = uri.getAuthority();
6695 ProviderInfo pi = null;
6696 ContentProviderRecord cpr
6697 = (ContentProviderRecord)mProvidersByName.get(authority);
6698 if (cpr != null) {
6699 pi = cpr.info;
6700 } else {
6701 try {
6702 pi = pm.resolveContentProvider(authority,
6703 PackageManager.GET_URI_PERMISSION_PATTERNS);
6704 } catch (RemoteException ex) {
6705 }
6706 }
6707 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006708 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006709 return;
6710 }
6711
6712 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6713 }
6714 }
6715
6716 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6717 synchronized (this) {
6718 ProcessRecord app =
6719 who != null ? getRecordForAppLocked(who) : null;
6720 if (app == null) return;
6721
6722 Message msg = Message.obtain();
6723 msg.what = WAIT_FOR_DEBUGGER_MSG;
6724 msg.obj = app;
6725 msg.arg1 = waiting ? 1 : 0;
6726 mHandler.sendMessage(msg);
6727 }
6728 }
6729
6730 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6731 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006732 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006733 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006734 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006735 }
6736
6737 // =========================================================
6738 // TASK MANAGEMENT
6739 // =========================================================
6740
6741 public List getTasks(int maxNum, int flags,
6742 IThumbnailReceiver receiver) {
6743 ArrayList list = new ArrayList();
6744
6745 PendingThumbnailsRecord pending = null;
6746 IApplicationThread topThumbnail = null;
6747 HistoryRecord topRecord = null;
6748
6749 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006750 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006751 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6752 + ", receiver=" + receiver);
6753
6754 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6755 != PackageManager.PERMISSION_GRANTED) {
6756 if (receiver != null) {
6757 // If the caller wants to wait for pending thumbnails,
6758 // it ain't gonna get them.
6759 try {
6760 receiver.finished();
6761 } catch (RemoteException ex) {
6762 }
6763 }
6764 String msg = "Permission Denial: getTasks() from pid="
6765 + Binder.getCallingPid()
6766 + ", uid=" + Binder.getCallingUid()
6767 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006768 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769 throw new SecurityException(msg);
6770 }
6771
6772 int pos = mHistory.size()-1;
6773 HistoryRecord next =
6774 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6775 HistoryRecord top = null;
6776 CharSequence topDescription = null;
6777 TaskRecord curTask = null;
6778 int numActivities = 0;
6779 int numRunning = 0;
6780 while (pos >= 0 && maxNum > 0) {
6781 final HistoryRecord r = next;
6782 pos--;
6783 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6784
6785 // Initialize state for next task if needed.
6786 if (top == null ||
6787 (top.state == ActivityState.INITIALIZING
6788 && top.task == r.task)) {
6789 top = r;
6790 topDescription = r.description;
6791 curTask = r.task;
6792 numActivities = numRunning = 0;
6793 }
6794
6795 // Add 'r' into the current task.
6796 numActivities++;
6797 if (r.app != null && r.app.thread != null) {
6798 numRunning++;
6799 }
6800 if (topDescription == null) {
6801 topDescription = r.description;
6802 }
6803
Joe Onorato8a9b2202010-02-26 18:56:32 -08006804 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006805 TAG, r.intent.getComponent().flattenToShortString()
6806 + ": task=" + r.task);
6807
6808 // If the next one is a different task, generate a new
6809 // TaskInfo entry for what we have.
6810 if (next == null || next.task != curTask) {
6811 ActivityManager.RunningTaskInfo ci
6812 = new ActivityManager.RunningTaskInfo();
6813 ci.id = curTask.taskId;
6814 ci.baseActivity = r.intent.getComponent();
6815 ci.topActivity = top.intent.getComponent();
6816 ci.thumbnail = top.thumbnail;
6817 ci.description = topDescription;
6818 ci.numActivities = numActivities;
6819 ci.numRunning = numRunning;
6820 //System.out.println(
6821 // "#" + maxNum + ": " + " descr=" + ci.description);
6822 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006823 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006824 TAG, "State=" + top.state + "Idle=" + top.idle
6825 + " app=" + top.app
6826 + " thr=" + (top.app != null ? top.app.thread : null));
6827 if (top.state == ActivityState.RESUMED
6828 || top.state == ActivityState.PAUSING) {
6829 if (top.idle && top.app != null
6830 && top.app.thread != null) {
6831 topRecord = top;
6832 topThumbnail = top.app.thread;
6833 } else {
6834 top.thumbnailNeeded = true;
6835 }
6836 }
6837 if (pending == null) {
6838 pending = new PendingThumbnailsRecord(receiver);
6839 }
6840 pending.pendingRecords.add(top);
6841 }
6842 list.add(ci);
6843 maxNum--;
6844 top = null;
6845 }
6846 }
6847
6848 if (pending != null) {
6849 mPendingThumbnails.add(pending);
6850 }
6851 }
6852
Joe Onorato8a9b2202010-02-26 18:56:32 -08006853 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854
6855 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006856 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006857 try {
6858 topThumbnail.requestThumbnail(topRecord);
6859 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006860 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006861 sendPendingThumbnail(null, topRecord, null, null, true);
6862 }
6863 }
6864
6865 if (pending == null && receiver != null) {
6866 // In this case all thumbnails were available and the client
6867 // is being asked to be told when the remaining ones come in...
6868 // which is unusually, since the top-most currently running
6869 // activity should never have a canned thumbnail! Oh well.
6870 try {
6871 receiver.finished();
6872 } catch (RemoteException ex) {
6873 }
6874 }
6875
6876 return list;
6877 }
6878
6879 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6880 int flags) {
6881 synchronized (this) {
6882 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6883 "getRecentTasks()");
6884
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006885 IPackageManager pm = ActivityThread.getPackageManager();
6886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006887 final int N = mRecentTasks.size();
6888 ArrayList<ActivityManager.RecentTaskInfo> res
6889 = new ArrayList<ActivityManager.RecentTaskInfo>(
6890 maxNum < N ? maxNum : N);
6891 for (int i=0; i<N && maxNum > 0; i++) {
6892 TaskRecord tr = mRecentTasks.get(i);
6893 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6894 || (tr.intent == null)
6895 || ((tr.intent.getFlags()
6896 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6897 ActivityManager.RecentTaskInfo rti
6898 = new ActivityManager.RecentTaskInfo();
6899 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6900 rti.baseIntent = new Intent(
6901 tr.intent != null ? tr.intent : tr.affinityIntent);
6902 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006903
6904 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
6905 // Check whether this activity is currently available.
6906 try {
6907 if (rti.origActivity != null) {
6908 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
6909 continue;
6910 }
6911 } else if (rti.baseIntent != null) {
6912 if (pm.queryIntentActivities(rti.baseIntent,
6913 null, 0) == null) {
6914 continue;
6915 }
6916 }
6917 } catch (RemoteException e) {
6918 // Will never happen.
6919 }
6920 }
6921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006922 res.add(rti);
6923 maxNum--;
6924 }
6925 }
6926 return res;
6927 }
6928 }
6929
6930 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6931 int j;
6932 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6933 TaskRecord jt = startTask;
6934
6935 // First look backwards
6936 for (j=startIndex-1; j>=0; j--) {
6937 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6938 if (r.task != jt) {
6939 jt = r.task;
6940 if (affinity.equals(jt.affinity)) {
6941 return j;
6942 }
6943 }
6944 }
6945
6946 // Now look forwards
6947 final int N = mHistory.size();
6948 jt = startTask;
6949 for (j=startIndex+1; j<N; j++) {
6950 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6951 if (r.task != jt) {
6952 if (affinity.equals(jt.affinity)) {
6953 return j;
6954 }
6955 jt = r.task;
6956 }
6957 }
6958
6959 // Might it be at the top?
6960 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6961 return N-1;
6962 }
6963
6964 return -1;
6965 }
6966
6967 /**
6968 * Perform a reset of the given task, if needed as part of launching it.
6969 * Returns the new HistoryRecord at the top of the task.
6970 */
6971 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6972 HistoryRecord newActivity) {
6973 boolean forceReset = (newActivity.info.flags
6974 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6975 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6976 if ((newActivity.info.flags
6977 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6978 forceReset = true;
6979 }
6980 }
6981
6982 final TaskRecord task = taskTop.task;
6983
6984 // We are going to move through the history list so that we can look
6985 // at each activity 'target' with 'below' either the interesting
6986 // activity immediately below it in the stack or null.
6987 HistoryRecord target = null;
6988 int targetI = 0;
6989 int taskTopI = -1;
6990 int replyChainEnd = -1;
6991 int lastReparentPos = -1;
6992 for (int i=mHistory.size()-1; i>=-1; i--) {
6993 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6994
6995 if (below != null && below.finishing) {
6996 continue;
6997 }
6998 if (target == null) {
6999 target = below;
7000 targetI = i;
7001 // If we were in the middle of a reply chain before this
7002 // task, it doesn't appear like the root of the chain wants
7003 // anything interesting, so drop it.
7004 replyChainEnd = -1;
7005 continue;
7006 }
7007
7008 final int flags = target.info.flags;
7009
7010 final boolean finishOnTaskLaunch =
7011 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7012 final boolean allowTaskReparenting =
7013 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7014
7015 if (target.task == task) {
7016 // We are inside of the task being reset... we'll either
7017 // finish this activity, push it out for another task,
7018 // or leave it as-is. We only do this
7019 // for activities that are not the root of the task (since
7020 // if we finish the root, we may no longer have the task!).
7021 if (taskTopI < 0) {
7022 taskTopI = targetI;
7023 }
7024 if (below != null && below.task == task) {
7025 final boolean clearWhenTaskReset =
7026 (target.intent.getFlags()
7027 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007028 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007029 // If this activity is sending a reply to a previous
7030 // activity, we can't do anything with it now until
7031 // we reach the start of the reply chain.
7032 // XXX note that we are assuming the result is always
7033 // to the previous activity, which is almost always
7034 // the case but we really shouldn't count on.
7035 if (replyChainEnd < 0) {
7036 replyChainEnd = targetI;
7037 }
Ed Heyl73798232009-03-24 21:32:21 -07007038 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007039 && target.taskAffinity != null
7040 && !target.taskAffinity.equals(task.affinity)) {
7041 // If this activity has an affinity for another
7042 // task, then we need to move it out of here. We will
7043 // move it as far out of the way as possible, to the
7044 // bottom of the activity stack. This also keeps it
7045 // correctly ordered with any activities we previously
7046 // moved.
7047 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7048 if (target.taskAffinity != null
7049 && target.taskAffinity.equals(p.task.affinity)) {
7050 // If the activity currently at the bottom has the
7051 // same task affinity as the one we are moving,
7052 // then merge it into the same task.
7053 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007054 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007055 + " out to bottom task " + p.task);
7056 } else {
7057 mCurTask++;
7058 if (mCurTask <= 0) {
7059 mCurTask = 1;
7060 }
7061 target.task = new TaskRecord(mCurTask, target.info, null,
7062 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7063 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007064 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 + " out to new task " + target.task);
7066 }
7067 mWindowManager.setAppGroupId(target, task.taskId);
7068 if (replyChainEnd < 0) {
7069 replyChainEnd = targetI;
7070 }
7071 int dstPos = 0;
7072 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7073 p = (HistoryRecord)mHistory.get(srcPos);
7074 if (p.finishing) {
7075 continue;
7076 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007077 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007078 + " out to target's task " + target.task);
7079 task.numActivities--;
7080 p.task = target.task;
7081 target.task.numActivities++;
7082 mHistory.remove(srcPos);
7083 mHistory.add(dstPos, p);
7084 mWindowManager.moveAppToken(dstPos, p);
7085 mWindowManager.setAppGroupId(p, p.task.taskId);
7086 dstPos++;
7087 if (VALIDATE_TOKENS) {
7088 mWindowManager.validateAppTokens(mHistory);
7089 }
7090 i++;
7091 }
7092 if (taskTop == p) {
7093 taskTop = below;
7094 }
7095 if (taskTopI == replyChainEnd) {
7096 taskTopI = -1;
7097 }
7098 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007099 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007100 } else if (forceReset || finishOnTaskLaunch
7101 || clearWhenTaskReset) {
7102 // If the activity should just be removed -- either
7103 // because it asks for it, or the task should be
7104 // cleared -- then finish it and anything that is
7105 // part of its reply chain.
7106 if (clearWhenTaskReset) {
7107 // In this case, we want to finish this activity
7108 // and everything above it, so be sneaky and pretend
7109 // like these are all in the reply chain.
7110 replyChainEnd = targetI+1;
7111 while (replyChainEnd < mHistory.size() &&
7112 ((HistoryRecord)mHistory.get(
7113 replyChainEnd)).task == task) {
7114 replyChainEnd++;
7115 }
7116 replyChainEnd--;
7117 } else if (replyChainEnd < 0) {
7118 replyChainEnd = targetI;
7119 }
7120 HistoryRecord p = null;
7121 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7122 p = (HistoryRecord)mHistory.get(srcPos);
7123 if (p.finishing) {
7124 continue;
7125 }
7126 if (finishActivityLocked(p, srcPos,
7127 Activity.RESULT_CANCELED, null, "reset")) {
7128 replyChainEnd--;
7129 srcPos--;
7130 }
7131 }
7132 if (taskTop == p) {
7133 taskTop = below;
7134 }
7135 if (taskTopI == replyChainEnd) {
7136 taskTopI = -1;
7137 }
7138 replyChainEnd = -1;
7139 } else {
7140 // If we were in the middle of a chain, well the
7141 // activity that started it all doesn't want anything
7142 // special, so leave it all as-is.
7143 replyChainEnd = -1;
7144 }
7145 } else {
7146 // Reached the bottom of the task -- any reply chain
7147 // should be left as-is.
7148 replyChainEnd = -1;
7149 }
7150
7151 } else if (target.resultTo != null) {
7152 // If this activity is sending a reply to a previous
7153 // activity, we can't do anything with it now until
7154 // we reach the start of the reply chain.
7155 // XXX note that we are assuming the result is always
7156 // to the previous activity, which is almost always
7157 // the case but we really shouldn't count on.
7158 if (replyChainEnd < 0) {
7159 replyChainEnd = targetI;
7160 }
7161
7162 } else if (taskTopI >= 0 && allowTaskReparenting
7163 && task.affinity != null
7164 && task.affinity.equals(target.taskAffinity)) {
7165 // We are inside of another task... if this activity has
7166 // an affinity for our task, then either remove it if we are
7167 // clearing or move it over to our task. Note that
7168 // we currently punt on the case where we are resetting a
7169 // task that is not at the top but who has activities above
7170 // with an affinity to it... this is really not a normal
7171 // case, and we will need to later pull that task to the front
7172 // and usually at that point we will do the reset and pick
7173 // up those remaining activities. (This only happens if
7174 // someone starts an activity in a new task from an activity
7175 // in a task that is not currently on top.)
7176 if (forceReset || finishOnTaskLaunch) {
7177 if (replyChainEnd < 0) {
7178 replyChainEnd = targetI;
7179 }
7180 HistoryRecord p = null;
7181 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7182 p = (HistoryRecord)mHistory.get(srcPos);
7183 if (p.finishing) {
7184 continue;
7185 }
7186 if (finishActivityLocked(p, srcPos,
7187 Activity.RESULT_CANCELED, null, "reset")) {
7188 taskTopI--;
7189 lastReparentPos--;
7190 replyChainEnd--;
7191 srcPos--;
7192 }
7193 }
7194 replyChainEnd = -1;
7195 } else {
7196 if (replyChainEnd < 0) {
7197 replyChainEnd = targetI;
7198 }
7199 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7200 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7201 if (p.finishing) {
7202 continue;
7203 }
7204 if (lastReparentPos < 0) {
7205 lastReparentPos = taskTopI;
7206 taskTop = p;
7207 } else {
7208 lastReparentPos--;
7209 }
7210 mHistory.remove(srcPos);
7211 p.task.numActivities--;
7212 p.task = task;
7213 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007214 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007215 + " in to resetting task " + task);
7216 task.numActivities++;
7217 mWindowManager.moveAppToken(lastReparentPos, p);
7218 mWindowManager.setAppGroupId(p, p.task.taskId);
7219 if (VALIDATE_TOKENS) {
7220 mWindowManager.validateAppTokens(mHistory);
7221 }
7222 }
7223 replyChainEnd = -1;
7224
7225 // Now we've moved it in to place... but what if this is
7226 // a singleTop activity and we have put it on top of another
7227 // instance of the same activity? Then we drop the instance
7228 // below so it remains singleTop.
7229 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7230 for (int j=lastReparentPos-1; j>=0; j--) {
7231 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7232 if (p.finishing) {
7233 continue;
7234 }
7235 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7236 if (finishActivityLocked(p, j,
7237 Activity.RESULT_CANCELED, null, "replace")) {
7238 taskTopI--;
7239 lastReparentPos--;
7240 }
7241 }
7242 }
7243 }
7244 }
7245 }
7246
7247 target = below;
7248 targetI = i;
7249 }
7250
7251 return taskTop;
7252 }
7253
7254 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007255 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007256 */
7257 public void moveTaskToFront(int task) {
7258 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7259 "moveTaskToFront()");
7260
7261 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007262 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7263 Binder.getCallingUid(), "Task to front")) {
7264 return;
7265 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 final long origId = Binder.clearCallingIdentity();
7267 try {
7268 int N = mRecentTasks.size();
7269 for (int i=0; i<N; i++) {
7270 TaskRecord tr = mRecentTasks.get(i);
7271 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007272 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273 return;
7274 }
7275 }
7276 for (int i=mHistory.size()-1; i>=0; i--) {
7277 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7278 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007279 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007280 return;
7281 }
7282 }
7283 } finally {
7284 Binder.restoreCallingIdentity(origId);
7285 }
7286 }
7287 }
7288
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007289 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007290 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007291
7292 final int task = tr.taskId;
7293 int top = mHistory.size()-1;
7294
7295 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7296 // nothing to do!
7297 return;
7298 }
7299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007300 ArrayList moved = new ArrayList();
7301
7302 // Applying the affinities may have removed entries from the history,
7303 // so get the size again.
7304 top = mHistory.size()-1;
7305 int pos = top;
7306
7307 // Shift all activities with this task up to the top
7308 // of the stack, keeping them in the same internal order.
7309 while (pos >= 0) {
7310 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007311 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007312 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7313 boolean first = true;
7314 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007315 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 mHistory.remove(pos);
7317 mHistory.add(top, r);
7318 moved.add(0, r);
7319 top--;
7320 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007321 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007322 first = false;
7323 }
7324 }
7325 pos--;
7326 }
7327
Joe Onorato8a9b2202010-02-26 18:56:32 -08007328 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007329 "Prepare to front transition: task=" + tr);
7330 if (reason != null &&
7331 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7332 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7333 HistoryRecord r = topRunningActivityLocked(null);
7334 if (r != null) {
7335 mNoAnimActivities.add(r);
7336 }
7337 } else {
7338 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7339 }
7340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341 mWindowManager.moveAppTokensToTop(moved);
7342 if (VALIDATE_TOKENS) {
7343 mWindowManager.validateAppTokens(mHistory);
7344 }
7345
Josh Bartel7f208742010-02-25 11:01:44 -06007346 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007347 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007348 }
7349
Josh Bartel7f208742010-02-25 11:01:44 -06007350 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007351 resumeTopActivityLocked(null);
7352 }
7353
7354 public void moveTaskToBack(int task) {
7355 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7356 "moveTaskToBack()");
7357
7358 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007359 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7360 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7361 Binder.getCallingUid(), "Task to back")) {
7362 return;
7363 }
7364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007366 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007367 Binder.restoreCallingIdentity(origId);
7368 }
7369 }
7370
7371 /**
7372 * Moves an activity, and all of the other activities within the same task, to the bottom
7373 * of the history stack. The activity's order within the task is unchanged.
7374 *
7375 * @param token A reference to the activity we wish to move
7376 * @param nonRoot If false then this only works if the activity is the root
7377 * of a task; if true it will work for any activity in a task.
7378 * @return Returns true if the move completed, false if not.
7379 */
7380 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7381 synchronized(this) {
7382 final long origId = Binder.clearCallingIdentity();
7383 int taskId = getTaskForActivityLocked(token, !nonRoot);
7384 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007385 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386 }
7387 Binder.restoreCallingIdentity(origId);
7388 }
7389 return false;
7390 }
7391
7392 /**
7393 * Worker method for rearranging history stack. Implements the function of moving all
7394 * activities for a specific task (gathering them if disjoint) into a single group at the
7395 * bottom of the stack.
7396 *
7397 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7398 * to premeptively cancel the move.
7399 *
7400 * @param task The taskId to collect and move to the bottom.
7401 * @return Returns true if the move completed, false if not.
7402 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007403 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007404 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007405
7406 // If we have a watcher, preflight the move before committing to it. First check
7407 // for *other* available tasks, but if none are available, then try again allowing the
7408 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007409 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007410 HistoryRecord next = topRunningActivityLocked(null, task);
7411 if (next == null) {
7412 next = topRunningActivityLocked(null, 0);
7413 }
7414 if (next != null) {
7415 // ask watcher if this is allowed
7416 boolean moveOK = true;
7417 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007418 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007420 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007421 }
7422 if (!moveOK) {
7423 return false;
7424 }
7425 }
7426 }
7427
7428 ArrayList moved = new ArrayList();
7429
Joe Onorato8a9b2202010-02-26 18:56:32 -08007430 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007431 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432
7433 final int N = mHistory.size();
7434 int bottom = 0;
7435 int pos = 0;
7436
7437 // Shift all activities with this task down to the bottom
7438 // of the stack, keeping them in the same internal order.
7439 while (pos < N) {
7440 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007441 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007442 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7443 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007444 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007445 mHistory.remove(pos);
7446 mHistory.add(bottom, r);
7447 moved.add(r);
7448 bottom++;
7449 }
7450 pos++;
7451 }
7452
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007453 if (reason != null &&
7454 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7455 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7456 HistoryRecord r = topRunningActivityLocked(null);
7457 if (r != null) {
7458 mNoAnimActivities.add(r);
7459 }
7460 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007461 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007463 mWindowManager.moveAppTokensToBottom(moved);
7464 if (VALIDATE_TOKENS) {
7465 mWindowManager.validateAppTokens(mHistory);
7466 }
7467
Josh Bartel7f208742010-02-25 11:01:44 -06007468 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007469 return true;
7470 }
7471
7472 public void moveTaskBackwards(int task) {
7473 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7474 "moveTaskBackwards()");
7475
7476 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007477 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7478 Binder.getCallingUid(), "Task backwards")) {
7479 return;
7480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 final long origId = Binder.clearCallingIdentity();
7482 moveTaskBackwardsLocked(task);
7483 Binder.restoreCallingIdentity(origId);
7484 }
7485 }
7486
7487 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007488 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007489 }
7490
7491 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7492 synchronized(this) {
7493 return getTaskForActivityLocked(token, onlyRoot);
7494 }
7495 }
7496
7497 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7498 final int N = mHistory.size();
7499 TaskRecord lastTask = null;
7500 for (int i=0; i<N; i++) {
7501 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7502 if (r == token) {
7503 if (!onlyRoot || lastTask != r.task) {
7504 return r.task.taskId;
7505 }
7506 return -1;
7507 }
7508 lastTask = r.task;
7509 }
7510
7511 return -1;
7512 }
7513
7514 /**
7515 * Returns the top activity in any existing task matching the given
7516 * Intent. Returns null if no such task is found.
7517 */
7518 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7519 ComponentName cls = intent.getComponent();
7520 if (info.targetActivity != null) {
7521 cls = new ComponentName(info.packageName, info.targetActivity);
7522 }
7523
7524 TaskRecord cp = null;
7525
7526 final int N = mHistory.size();
7527 for (int i=(N-1); i>=0; i--) {
7528 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7529 if (!r.finishing && r.task != cp
7530 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7531 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007532 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007533 // + "/aff=" + r.task.affinity + " to new cls="
7534 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7535 if (r.task.affinity != null) {
7536 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007537 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007538 return r;
7539 }
7540 } else if (r.task.intent != null
7541 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007542 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007543 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007544 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 return r;
7546 } else if (r.task.affinityIntent != null
7547 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007548 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007550 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 return r;
7552 }
7553 }
7554 }
7555
7556 return null;
7557 }
7558
7559 /**
7560 * Returns the first activity (starting from the top of the stack) that
7561 * is the same as the given activity. Returns null if no such activity
7562 * is found.
7563 */
7564 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7565 ComponentName cls = intent.getComponent();
7566 if (info.targetActivity != null) {
7567 cls = new ComponentName(info.packageName, info.targetActivity);
7568 }
7569
7570 final int N = mHistory.size();
7571 for (int i=(N-1); i>=0; i--) {
7572 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7573 if (!r.finishing) {
7574 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007575 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007577 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007578 return r;
7579 }
7580 }
7581 }
7582
7583 return null;
7584 }
7585
7586 public void finishOtherInstances(IBinder token, ComponentName className) {
7587 synchronized(this) {
7588 final long origId = Binder.clearCallingIdentity();
7589
7590 int N = mHistory.size();
7591 TaskRecord lastTask = null;
7592 for (int i=0; i<N; i++) {
7593 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7594 if (r.realActivity.equals(className)
7595 && r != token && lastTask != r.task) {
7596 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7597 null, "others")) {
7598 i--;
7599 N--;
7600 }
7601 }
7602 lastTask = r.task;
7603 }
7604
7605 Binder.restoreCallingIdentity(origId);
7606 }
7607 }
7608
7609 // =========================================================
7610 // THUMBNAILS
7611 // =========================================================
7612
7613 public void reportThumbnail(IBinder token,
7614 Bitmap thumbnail, CharSequence description) {
7615 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7616 final long origId = Binder.clearCallingIdentity();
7617 sendPendingThumbnail(null, token, thumbnail, description, true);
7618 Binder.restoreCallingIdentity(origId);
7619 }
7620
7621 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7622 Bitmap thumbnail, CharSequence description, boolean always) {
7623 TaskRecord task = null;
7624 ArrayList receivers = null;
7625
7626 //System.out.println("Send pending thumbnail: " + r);
7627
7628 synchronized(this) {
7629 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007630 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 if (index < 0) {
7632 return;
7633 }
7634 r = (HistoryRecord)mHistory.get(index);
7635 }
7636 if (thumbnail == null) {
7637 thumbnail = r.thumbnail;
7638 description = r.description;
7639 }
7640 if (thumbnail == null && !always) {
7641 // If there is no thumbnail, and this entry is not actually
7642 // going away, then abort for now and pick up the next
7643 // thumbnail we get.
7644 return;
7645 }
7646 task = r.task;
7647
7648 int N = mPendingThumbnails.size();
7649 int i=0;
7650 while (i<N) {
7651 PendingThumbnailsRecord pr =
7652 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7653 //System.out.println("Looking in " + pr.pendingRecords);
7654 if (pr.pendingRecords.remove(r)) {
7655 if (receivers == null) {
7656 receivers = new ArrayList();
7657 }
7658 receivers.add(pr);
7659 if (pr.pendingRecords.size() == 0) {
7660 pr.finished = true;
7661 mPendingThumbnails.remove(i);
7662 N--;
7663 continue;
7664 }
7665 }
7666 i++;
7667 }
7668 }
7669
7670 if (receivers != null) {
7671 final int N = receivers.size();
7672 for (int i=0; i<N; i++) {
7673 try {
7674 PendingThumbnailsRecord pr =
7675 (PendingThumbnailsRecord)receivers.get(i);
7676 pr.receiver.newThumbnail(
7677 task != null ? task.taskId : -1, thumbnail, description);
7678 if (pr.finished) {
7679 pr.receiver.finished();
7680 }
7681 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007682 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683 }
7684 }
7685 }
7686 }
7687
7688 // =========================================================
7689 // CONTENT PROVIDERS
7690 // =========================================================
7691
7692 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7693 List providers = null;
7694 try {
7695 providers = ActivityThread.getPackageManager().
7696 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007697 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 } catch (RemoteException ex) {
7699 }
7700 if (providers != null) {
7701 final int N = providers.size();
7702 for (int i=0; i<N; i++) {
7703 ProviderInfo cpi =
7704 (ProviderInfo)providers.get(i);
7705 ContentProviderRecord cpr =
7706 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7707 if (cpr == null) {
7708 cpr = new ContentProviderRecord(cpi, app.info);
7709 mProvidersByClass.put(cpi.name, cpr);
7710 }
7711 app.pubProviders.put(cpi.name, cpr);
7712 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007713 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007714 }
7715 }
7716 return providers;
7717 }
7718
7719 private final String checkContentProviderPermissionLocked(
7720 ProviderInfo cpi, ProcessRecord r, int mode) {
7721 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7722 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7723 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7724 cpi.exported ? -1 : cpi.applicationInfo.uid)
7725 == PackageManager.PERMISSION_GRANTED
7726 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7727 return null;
7728 }
7729 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7730 cpi.exported ? -1 : cpi.applicationInfo.uid)
7731 == PackageManager.PERMISSION_GRANTED) {
7732 return null;
7733 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007734
7735 PathPermission[] pps = cpi.pathPermissions;
7736 if (pps != null) {
7737 int i = pps.length;
7738 while (i > 0) {
7739 i--;
7740 PathPermission pp = pps[i];
7741 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7742 cpi.exported ? -1 : cpi.applicationInfo.uid)
7743 == PackageManager.PERMISSION_GRANTED
7744 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7745 return null;
7746 }
7747 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7748 cpi.exported ? -1 : cpi.applicationInfo.uid)
7749 == PackageManager.PERMISSION_GRANTED) {
7750 return null;
7751 }
7752 }
7753 }
7754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007755 String msg = "Permission Denial: opening provider " + cpi.name
7756 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7757 + ", uid=" + callingUid + ") requires "
7758 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007759 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007760 return msg;
7761 }
7762
7763 private final ContentProviderHolder getContentProviderImpl(
7764 IApplicationThread caller, String name) {
7765 ContentProviderRecord cpr;
7766 ProviderInfo cpi = null;
7767
7768 synchronized(this) {
7769 ProcessRecord r = null;
7770 if (caller != null) {
7771 r = getRecordForAppLocked(caller);
7772 if (r == null) {
7773 throw new SecurityException(
7774 "Unable to find app for caller " + caller
7775 + " (pid=" + Binder.getCallingPid()
7776 + ") when getting content provider " + name);
7777 }
7778 }
7779
7780 // First check if this content provider has been published...
7781 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7782 if (cpr != null) {
7783 cpi = cpr.info;
7784 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7785 return new ContentProviderHolder(cpi,
7786 cpi.readPermission != null
7787 ? cpi.readPermission : cpi.writePermission);
7788 }
7789
7790 if (r != null && cpr.canRunHere(r)) {
7791 // This provider has been published or is in the process
7792 // of being published... but it is also allowed to run
7793 // in the caller's process, so don't make a connection
7794 // and just let the caller instantiate its own instance.
7795 if (cpr.provider != null) {
7796 // don't give caller the provider object, it needs
7797 // to make its own.
7798 cpr = new ContentProviderRecord(cpr);
7799 }
7800 return cpr;
7801 }
7802
7803 final long origId = Binder.clearCallingIdentity();
7804
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007805 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007806 // return it right away.
7807 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007808 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007809 "Adding provider requested by "
7810 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007811 + cpr.info.processName);
7812 Integer cnt = r.conProviders.get(cpr);
7813 if (cnt == null) {
7814 r.conProviders.put(cpr, new Integer(1));
7815 } else {
7816 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007818 cpr.clients.add(r);
7819 } else {
7820 cpr.externals++;
7821 }
7822
7823 if (cpr.app != null) {
7824 updateOomAdjLocked(cpr.app);
7825 }
7826
7827 Binder.restoreCallingIdentity(origId);
7828
7829 } else {
7830 try {
7831 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007832 resolveContentProvider(name,
7833 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007834 } catch (RemoteException ex) {
7835 }
7836 if (cpi == null) {
7837 return null;
7838 }
7839
7840 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7841 return new ContentProviderHolder(cpi,
7842 cpi.readPermission != null
7843 ? cpi.readPermission : cpi.writePermission);
7844 }
7845
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007846 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7847 && !cpi.processName.equals("system")) {
7848 // If this content provider does not run in the system
7849 // process, and the system is not yet ready to run other
7850 // processes, then fail fast instead of hanging.
7851 throw new IllegalArgumentException(
7852 "Attempt to launch content provider before system ready");
7853 }
7854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007855 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7856 final boolean firstClass = cpr == null;
7857 if (firstClass) {
7858 try {
7859 ApplicationInfo ai =
7860 ActivityThread.getPackageManager().
7861 getApplicationInfo(
7862 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007863 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007864 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007865 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007866 + cpi.name);
7867 return null;
7868 }
7869 cpr = new ContentProviderRecord(cpi, ai);
7870 } catch (RemoteException ex) {
7871 // pm is in same process, this will never happen.
7872 }
7873 }
7874
7875 if (r != null && cpr.canRunHere(r)) {
7876 // If this is a multiprocess provider, then just return its
7877 // info and allow the caller to instantiate it. Only do
7878 // this if the provider is the same user as the caller's
7879 // process, or can run as root (so can be in any process).
7880 return cpr;
7881 }
7882
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007883 if (DEBUG_PROVIDER) {
7884 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007885 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007886 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007887 }
7888
7889 // This is single process, and our app is now connecting to it.
7890 // See if we are already in the process of launching this
7891 // provider.
7892 final int N = mLaunchingProviders.size();
7893 int i;
7894 for (i=0; i<N; i++) {
7895 if (mLaunchingProviders.get(i) == cpr) {
7896 break;
7897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007898 }
7899
7900 // If the provider is not already being launched, then get it
7901 // started.
7902 if (i >= N) {
7903 final long origId = Binder.clearCallingIdentity();
7904 ProcessRecord proc = startProcessLocked(cpi.processName,
7905 cpr.appInfo, false, 0, "content provider",
7906 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007907 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007909 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007910 + cpi.applicationInfo.packageName + "/"
7911 + cpi.applicationInfo.uid + " for provider "
7912 + name + ": process is bad");
7913 return null;
7914 }
7915 cpr.launchingApp = proc;
7916 mLaunchingProviders.add(cpr);
7917 Binder.restoreCallingIdentity(origId);
7918 }
7919
7920 // Make sure the provider is published (the same provider class
7921 // may be published under multiple names).
7922 if (firstClass) {
7923 mProvidersByClass.put(cpi.name, cpr);
7924 }
7925 mProvidersByName.put(name, cpr);
7926
7927 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007928 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007929 "Adding provider requested by "
7930 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007931 + cpr.info.processName);
7932 Integer cnt = r.conProviders.get(cpr);
7933 if (cnt == null) {
7934 r.conProviders.put(cpr, new Integer(1));
7935 } else {
7936 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007938 cpr.clients.add(r);
7939 } else {
7940 cpr.externals++;
7941 }
7942 }
7943 }
7944
7945 // Wait for the provider to be published...
7946 synchronized (cpr) {
7947 while (cpr.provider == null) {
7948 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007949 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007950 + cpi.applicationInfo.packageName + "/"
7951 + cpi.applicationInfo.uid + " for provider "
7952 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007953 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007954 cpi.applicationInfo.packageName,
7955 cpi.applicationInfo.uid, name);
7956 return null;
7957 }
7958 try {
7959 cpr.wait();
7960 } catch (InterruptedException ex) {
7961 }
7962 }
7963 }
7964 return cpr;
7965 }
7966
7967 public final ContentProviderHolder getContentProvider(
7968 IApplicationThread caller, String name) {
7969 if (caller == null) {
7970 String msg = "null IApplicationThread when getting content provider "
7971 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007972 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007973 throw new SecurityException(msg);
7974 }
7975
7976 return getContentProviderImpl(caller, name);
7977 }
7978
7979 private ContentProviderHolder getContentProviderExternal(String name) {
7980 return getContentProviderImpl(null, name);
7981 }
7982
7983 /**
7984 * Drop a content provider from a ProcessRecord's bookkeeping
7985 * @param cpr
7986 */
7987 public void removeContentProvider(IApplicationThread caller, String name) {
7988 synchronized (this) {
7989 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7990 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007991 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007992 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007993 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007994 return;
7995 }
7996 final ProcessRecord r = getRecordForAppLocked(caller);
7997 if (r == null) {
7998 throw new SecurityException(
7999 "Unable to find app for caller " + caller +
8000 " when removing content provider " + name);
8001 }
8002 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008003 ContentProviderRecord localCpr = (ContentProviderRecord)
8004 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008005 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008006 + r.info.processName + " from process "
8007 + localCpr.appInfo.processName);
8008 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008009 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008010 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008011 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008012 return;
8013 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008014 Integer cnt = r.conProviders.get(localCpr);
8015 if (cnt == null || cnt.intValue() <= 1) {
8016 localCpr.clients.remove(r);
8017 r.conProviders.remove(localCpr);
8018 } else {
8019 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 }
8022 updateOomAdjLocked();
8023 }
8024 }
8025
8026 private void removeContentProviderExternal(String name) {
8027 synchronized (this) {
8028 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
8029 if(cpr == null) {
8030 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008031 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 return;
8033 }
8034
8035 //update content provider record entry info
8036 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
8037 localCpr.externals--;
8038 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008039 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008040 }
8041 updateOomAdjLocked();
8042 }
8043 }
8044
8045 public final void publishContentProviders(IApplicationThread caller,
8046 List<ContentProviderHolder> providers) {
8047 if (providers == null) {
8048 return;
8049 }
8050
8051 synchronized(this) {
8052 final ProcessRecord r = getRecordForAppLocked(caller);
8053 if (r == null) {
8054 throw new SecurityException(
8055 "Unable to find app for caller " + caller
8056 + " (pid=" + Binder.getCallingPid()
8057 + ") when publishing content providers");
8058 }
8059
8060 final long origId = Binder.clearCallingIdentity();
8061
8062 final int N = providers.size();
8063 for (int i=0; i<N; i++) {
8064 ContentProviderHolder src = providers.get(i);
8065 if (src == null || src.info == null || src.provider == null) {
8066 continue;
8067 }
8068 ContentProviderRecord dst =
8069 (ContentProviderRecord)r.pubProviders.get(src.info.name);
8070 if (dst != null) {
8071 mProvidersByClass.put(dst.info.name, dst);
8072 String names[] = dst.info.authority.split(";");
8073 for (int j = 0; j < names.length; j++) {
8074 mProvidersByName.put(names[j], dst);
8075 }
8076
8077 int NL = mLaunchingProviders.size();
8078 int j;
8079 for (j=0; j<NL; j++) {
8080 if (mLaunchingProviders.get(j) == dst) {
8081 mLaunchingProviders.remove(j);
8082 j--;
8083 NL--;
8084 }
8085 }
8086 synchronized (dst) {
8087 dst.provider = src.provider;
8088 dst.app = r;
8089 dst.notifyAll();
8090 }
8091 updateOomAdjLocked(r);
8092 }
8093 }
8094
8095 Binder.restoreCallingIdentity(origId);
8096 }
8097 }
8098
8099 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008100 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008101 synchronized (mSelf) {
8102 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8103 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008104 if (providers != null) {
8105 for (int i=providers.size()-1; i>=0; i--) {
8106 ProviderInfo pi = (ProviderInfo)providers.get(i);
8107 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8108 Slog.w(TAG, "Not installing system proc provider " + pi.name
8109 + ": not system .apk");
8110 providers.remove(i);
8111 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008112 }
8113 }
8114 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008115 if (providers != null) {
8116 mSystemThread.installSystemProviders(providers);
8117 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008118 }
8119
8120 // =========================================================
8121 // GLOBAL MANAGEMENT
8122 // =========================================================
8123
8124 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8125 ApplicationInfo info, String customProcess) {
8126 String proc = customProcess != null ? customProcess : info.processName;
8127 BatteryStatsImpl.Uid.Proc ps = null;
8128 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8129 synchronized (stats) {
8130 ps = stats.getProcessStatsLocked(info.uid, proc);
8131 }
8132 return new ProcessRecord(ps, thread, info, proc);
8133 }
8134
8135 final ProcessRecord addAppLocked(ApplicationInfo info) {
8136 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8137
8138 if (app == null) {
8139 app = newProcessRecordLocked(null, info, null);
8140 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008141 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008142 }
8143
8144 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8145 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8146 app.persistent = true;
8147 app.maxAdj = CORE_SERVER_ADJ;
8148 }
8149 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8150 mPersistentStartingProcesses.add(app);
8151 startProcessLocked(app, "added application", app.processName);
8152 }
8153
8154 return app;
8155 }
8156
8157 public void unhandledBack() {
8158 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8159 "unhandledBack()");
8160
8161 synchronized(this) {
8162 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008163 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008164 TAG, "Performing unhandledBack(): stack size = " + count);
8165 if (count > 1) {
8166 final long origId = Binder.clearCallingIdentity();
8167 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8168 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8169 Binder.restoreCallingIdentity(origId);
8170 }
8171 }
8172 }
8173
8174 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8175 String name = uri.getAuthority();
8176 ContentProviderHolder cph = getContentProviderExternal(name);
8177 ParcelFileDescriptor pfd = null;
8178 if (cph != null) {
8179 // We record the binder invoker's uid in thread-local storage before
8180 // going to the content provider to open the file. Later, in the code
8181 // that handles all permissions checks, we look for this uid and use
8182 // that rather than the Activity Manager's own uid. The effect is that
8183 // we do the check against the caller's permissions even though it looks
8184 // to the content provider like the Activity Manager itself is making
8185 // the request.
8186 sCallerIdentity.set(new Identity(
8187 Binder.getCallingPid(), Binder.getCallingUid()));
8188 try {
8189 pfd = cph.provider.openFile(uri, "r");
8190 } catch (FileNotFoundException e) {
8191 // do nothing; pfd will be returned null
8192 } finally {
8193 // Ensure that whatever happens, we clean up the identity state
8194 sCallerIdentity.remove();
8195 }
8196
8197 // We've got the fd now, so we're done with the provider.
8198 removeContentProviderExternal(name);
8199 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008200 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008201 }
8202 return pfd;
8203 }
8204
8205 public void goingToSleep() {
8206 synchronized(this) {
8207 mSleeping = true;
8208 mWindowManager.setEventDispatching(false);
8209
8210 if (mResumedActivity != null) {
8211 pauseIfSleepingLocked();
8212 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008213 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008214 }
8215 }
8216 }
8217
Dianne Hackborn55280a92009-05-07 15:53:46 -07008218 public boolean shutdown(int timeout) {
8219 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8220 != PackageManager.PERMISSION_GRANTED) {
8221 throw new SecurityException("Requires permission "
8222 + android.Manifest.permission.SHUTDOWN);
8223 }
8224
8225 boolean timedout = false;
8226
8227 synchronized(this) {
8228 mShuttingDown = true;
8229 mWindowManager.setEventDispatching(false);
8230
8231 if (mResumedActivity != null) {
8232 pauseIfSleepingLocked();
8233 final long endTime = System.currentTimeMillis() + timeout;
8234 while (mResumedActivity != null || mPausingActivity != null) {
8235 long delay = endTime - System.currentTimeMillis();
8236 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008237 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008238 timedout = true;
8239 break;
8240 }
8241 try {
8242 this.wait();
8243 } catch (InterruptedException e) {
8244 }
8245 }
8246 }
8247 }
8248
8249 mUsageStatsService.shutdown();
8250 mBatteryStatsService.shutdown();
8251
8252 return timedout;
8253 }
8254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008255 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008256 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008257 if (!mGoingToSleep.isHeld()) {
8258 mGoingToSleep.acquire();
8259 if (mLaunchingActivity.isHeld()) {
8260 mLaunchingActivity.release();
8261 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8262 }
8263 }
8264
8265 // If we are not currently pausing an activity, get the current
8266 // one to pause. If we are pausing one, we will just let that stuff
8267 // run and release the wake lock when all done.
8268 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008269 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8270 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008271 startPausingLocked(false, true);
8272 }
8273 }
8274 }
8275
8276 public void wakingUp() {
8277 synchronized(this) {
8278 if (mGoingToSleep.isHeld()) {
8279 mGoingToSleep.release();
8280 }
8281 mWindowManager.setEventDispatching(true);
8282 mSleeping = false;
8283 resumeTopActivityLocked(null);
8284 }
8285 }
8286
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008287 public void stopAppSwitches() {
8288 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8289 != PackageManager.PERMISSION_GRANTED) {
8290 throw new SecurityException("Requires permission "
8291 + android.Manifest.permission.STOP_APP_SWITCHES);
8292 }
8293
8294 synchronized(this) {
8295 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8296 + APP_SWITCH_DELAY_TIME;
8297 mDidAppSwitch = false;
8298 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8299 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8300 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8301 }
8302 }
8303
8304 public void resumeAppSwitches() {
8305 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8306 != PackageManager.PERMISSION_GRANTED) {
8307 throw new SecurityException("Requires permission "
8308 + android.Manifest.permission.STOP_APP_SWITCHES);
8309 }
8310
8311 synchronized(this) {
8312 // Note that we don't execute any pending app switches... we will
8313 // let those wait until either the timeout, or the next start
8314 // activity request.
8315 mAppSwitchesAllowedTime = 0;
8316 }
8317 }
8318
8319 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8320 String name) {
8321 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8322 return true;
8323 }
8324
8325 final int perm = checkComponentPermission(
8326 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8327 callingUid, -1);
8328 if (perm == PackageManager.PERMISSION_GRANTED) {
8329 return true;
8330 }
8331
Joe Onorato8a9b2202010-02-26 18:56:32 -08008332 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008333 return false;
8334 }
8335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008336 public void setDebugApp(String packageName, boolean waitForDebugger,
8337 boolean persistent) {
8338 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8339 "setDebugApp()");
8340
8341 // Note that this is not really thread safe if there are multiple
8342 // callers into it at the same time, but that's not a situation we
8343 // care about.
8344 if (persistent) {
8345 final ContentResolver resolver = mContext.getContentResolver();
8346 Settings.System.putString(
8347 resolver, Settings.System.DEBUG_APP,
8348 packageName);
8349 Settings.System.putInt(
8350 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8351 waitForDebugger ? 1 : 0);
8352 }
8353
8354 synchronized (this) {
8355 if (!persistent) {
8356 mOrigDebugApp = mDebugApp;
8357 mOrigWaitForDebugger = mWaitForDebugger;
8358 }
8359 mDebugApp = packageName;
8360 mWaitForDebugger = waitForDebugger;
8361 mDebugTransient = !persistent;
8362 if (packageName != null) {
8363 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008364 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008365 Binder.restoreCallingIdentity(origId);
8366 }
8367 }
8368 }
8369
8370 public void setAlwaysFinish(boolean enabled) {
8371 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8372 "setAlwaysFinish()");
8373
8374 Settings.System.putInt(
8375 mContext.getContentResolver(),
8376 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8377
8378 synchronized (this) {
8379 mAlwaysFinishActivities = enabled;
8380 }
8381 }
8382
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008383 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008385 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008386 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008387 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008388 }
8389 }
8390
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008391 public boolean isUserAMonkey() {
8392 // For now the fact that there is a controller implies
8393 // we have a monkey.
8394 synchronized (this) {
8395 return mController != null;
8396 }
8397 }
8398
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008399 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008400 synchronized (this) {
8401 mWatchers.register(watcher);
8402 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008403 }
8404
8405 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008406 synchronized (this) {
8407 mWatchers.unregister(watcher);
8408 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008409 }
8410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008411 public final void enterSafeMode() {
8412 synchronized(this) {
8413 // It only makes sense to do this before the system is ready
8414 // and started launching other packages.
8415 if (!mSystemReady) {
8416 try {
8417 ActivityThread.getPackageManager().enterSafeMode();
8418 } catch (RemoteException e) {
8419 }
8420
8421 View v = LayoutInflater.from(mContext).inflate(
8422 com.android.internal.R.layout.safe_mode, null);
8423 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8424 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8425 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8426 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8427 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8428 lp.format = v.getBackground().getOpacity();
8429 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8430 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8431 ((WindowManager)mContext.getSystemService(
8432 Context.WINDOW_SERVICE)).addView(v, lp);
8433 }
8434 }
8435 }
8436
8437 public void noteWakeupAlarm(IIntentSender sender) {
8438 if (!(sender instanceof PendingIntentRecord)) {
8439 return;
8440 }
8441 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8442 synchronized (stats) {
8443 if (mBatteryStatsService.isOnBattery()) {
8444 mBatteryStatsService.enforceCallingPermission();
8445 PendingIntentRecord rec = (PendingIntentRecord)sender;
8446 int MY_UID = Binder.getCallingUid();
8447 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8448 BatteryStatsImpl.Uid.Pkg pkg =
8449 stats.getPackageStatsLocked(uid, rec.key.packageName);
8450 pkg.incWakeupsLocked();
8451 }
8452 }
8453 }
8454
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008455 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008456 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008457 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008458 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008459 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008460 // XXX Note: don't acquire main activity lock here, because the window
8461 // manager calls in with its locks held.
8462
8463 boolean killed = false;
8464 synchronized (mPidsSelfLocked) {
8465 int[] types = new int[pids.length];
8466 int worstType = 0;
8467 for (int i=0; i<pids.length; i++) {
8468 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8469 if (proc != null) {
8470 int type = proc.setAdj;
8471 types[i] = type;
8472 if (type > worstType) {
8473 worstType = type;
8474 }
8475 }
8476 }
8477
8478 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8479 // then constrain it so we will kill all hidden procs.
8480 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8481 worstType = HIDDEN_APP_MIN_ADJ;
8482 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008483 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008484 for (int i=0; i<pids.length; i++) {
8485 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8486 if (proc == null) {
8487 continue;
8488 }
8489 int adj = proc.setAdj;
8490 if (adj >= worstType) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008491 Slog.w(TAG, "Killing " + reason + " : " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008492 + adj + ")");
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008493 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8494 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008495 killed = true;
8496 Process.killProcess(pids[i]);
8497 }
8498 }
8499 }
8500 return killed;
8501 }
8502
8503 public void reportPss(IApplicationThread caller, int pss) {
8504 Watchdog.PssRequestor req;
8505 String name;
8506 ProcessRecord callerApp;
8507 synchronized (this) {
8508 if (caller == null) {
8509 return;
8510 }
8511 callerApp = getRecordForAppLocked(caller);
8512 if (callerApp == null) {
8513 return;
8514 }
8515 callerApp.lastPss = pss;
8516 req = callerApp;
8517 name = callerApp.processName;
8518 }
8519 Watchdog.getInstance().reportPss(req, name, pss);
8520 if (!callerApp.persistent) {
8521 removeRequestedPss(callerApp);
8522 }
8523 }
8524
8525 public void requestPss(Runnable completeCallback) {
8526 ArrayList<ProcessRecord> procs;
8527 synchronized (this) {
8528 mRequestPssCallback = completeCallback;
8529 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008530 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8531 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 if (!proc.persistent) {
8533 mRequestPssList.add(proc);
8534 }
8535 }
8536 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8537 }
8538
8539 int oldPri = Process.getThreadPriority(Process.myTid());
8540 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8541 for (int i=procs.size()-1; i>=0; i--) {
8542 ProcessRecord proc = procs.get(i);
8543 proc.lastPss = 0;
8544 proc.requestPss();
8545 }
8546 Process.setThreadPriority(oldPri);
8547 }
8548
8549 void removeRequestedPss(ProcessRecord proc) {
8550 Runnable callback = null;
8551 synchronized (this) {
8552 if (mRequestPssList.remove(proc)) {
8553 if (mRequestPssList.size() == 0) {
8554 callback = mRequestPssCallback;
8555 mRequestPssCallback = null;
8556 }
8557 }
8558 }
8559
8560 if (callback != null) {
8561 callback.run();
8562 }
8563 }
8564
8565 public void collectPss(Watchdog.PssStats stats) {
8566 stats.mEmptyPss = 0;
8567 stats.mEmptyCount = 0;
8568 stats.mBackgroundPss = 0;
8569 stats.mBackgroundCount = 0;
8570 stats.mServicePss = 0;
8571 stats.mServiceCount = 0;
8572 stats.mVisiblePss = 0;
8573 stats.mVisibleCount = 0;
8574 stats.mForegroundPss = 0;
8575 stats.mForegroundCount = 0;
8576 stats.mNoPssCount = 0;
8577 synchronized (this) {
8578 int i;
8579 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8580 ? mProcDeaths.length : stats.mProcDeaths.length;
8581 int aggr = 0;
8582 for (i=0; i<NPD; i++) {
8583 aggr += mProcDeaths[i];
8584 stats.mProcDeaths[i] = aggr;
8585 }
8586 while (i<stats.mProcDeaths.length) {
8587 stats.mProcDeaths[i] = 0;
8588 i++;
8589 }
8590
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008591 for (i=mLruProcesses.size()-1; i>=0; i--) {
8592 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008593 if (proc.persistent) {
8594 continue;
8595 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008596 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008597 if (proc.lastPss == 0) {
8598 stats.mNoPssCount++;
8599 continue;
8600 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008601 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8602 if (proc.empty) {
8603 stats.mEmptyPss += proc.lastPss;
8604 stats.mEmptyCount++;
8605 } else {
8606 stats.mBackgroundPss += proc.lastPss;
8607 stats.mBackgroundCount++;
8608 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008609 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8610 stats.mVisiblePss += proc.lastPss;
8611 stats.mVisibleCount++;
8612 } else {
8613 stats.mForegroundPss += proc.lastPss;
8614 stats.mForegroundCount++;
8615 }
8616 }
8617 }
8618 }
8619
8620 public final void startRunning(String pkg, String cls, String action,
8621 String data) {
8622 synchronized(this) {
8623 if (mStartRunning) {
8624 return;
8625 }
8626 mStartRunning = true;
8627 mTopComponent = pkg != null && cls != null
8628 ? new ComponentName(pkg, cls) : null;
8629 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8630 mTopData = data;
8631 if (!mSystemReady) {
8632 return;
8633 }
8634 }
8635
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008636 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008637 }
8638
8639 private void retrieveSettings() {
8640 final ContentResolver resolver = mContext.getContentResolver();
8641 String debugApp = Settings.System.getString(
8642 resolver, Settings.System.DEBUG_APP);
8643 boolean waitForDebugger = Settings.System.getInt(
8644 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8645 boolean alwaysFinishActivities = Settings.System.getInt(
8646 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8647
8648 Configuration configuration = new Configuration();
8649 Settings.System.getConfiguration(resolver, configuration);
8650
8651 synchronized (this) {
8652 mDebugApp = mOrigDebugApp = debugApp;
8653 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8654 mAlwaysFinishActivities = alwaysFinishActivities;
8655 // This happens before any activities are started, so we can
8656 // change mConfiguration in-place.
8657 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008658 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008659 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660 }
8661 }
8662
8663 public boolean testIsSystemReady() {
8664 // no need to synchronize(this) just to read & return the value
8665 return mSystemReady;
8666 }
8667
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008668 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 // In the simulator, startRunning will never have been called, which
8670 // normally sets a few crucial variables. Do it here instead.
8671 if (!Process.supportsProcesses()) {
8672 mStartRunning = true;
8673 mTopAction = Intent.ACTION_MAIN;
8674 }
8675
8676 synchronized(this) {
8677 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008678 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008679 return;
8680 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008681
8682 // Check to see if there are any update receivers to run.
8683 if (!mDidUpdate) {
8684 if (mWaitingUpdate) {
8685 return;
8686 }
8687 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8688 List<ResolveInfo> ris = null;
8689 try {
8690 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8691 intent, null, 0);
8692 } catch (RemoteException e) {
8693 }
8694 if (ris != null) {
8695 for (int i=ris.size()-1; i>=0; i--) {
8696 if ((ris.get(i).activityInfo.applicationInfo.flags
8697 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8698 ris.remove(i);
8699 }
8700 }
8701 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8702 for (int i=0; i<ris.size(); i++) {
8703 ActivityInfo ai = ris.get(i).activityInfo;
8704 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8705 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008706 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008707 finisher = new IIntentReceiver.Stub() {
8708 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008709 String data, Bundle extras, boolean ordered,
8710 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008711 throws RemoteException {
8712 synchronized (ActivityManagerService.this) {
8713 mDidUpdate = true;
8714 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008715 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008716 }
8717 };
8718 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008719 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008720 broadcastIntentLocked(null, null, intent, null, finisher,
8721 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008722 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008723 mWaitingUpdate = true;
8724 }
8725 }
8726 }
8727 if (mWaitingUpdate) {
8728 return;
8729 }
8730 mDidUpdate = true;
8731 }
8732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008733 mSystemReady = true;
8734 if (!mStartRunning) {
8735 return;
8736 }
8737 }
8738
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008739 ArrayList<ProcessRecord> procsToKill = null;
8740 synchronized(mPidsSelfLocked) {
8741 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8742 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8743 if (!isAllowedWhileBooting(proc.info)){
8744 if (procsToKill == null) {
8745 procsToKill = new ArrayList<ProcessRecord>();
8746 }
8747 procsToKill.add(proc);
8748 }
8749 }
8750 }
8751
8752 if (procsToKill != null) {
8753 synchronized(this) {
8754 for (int i=procsToKill.size()-1; i>=0; i--) {
8755 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008756 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008757 removeProcessLocked(proc, true);
8758 }
8759 }
8760 }
8761
Joe Onorato8a9b2202010-02-26 18:56:32 -08008762 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008763 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008764 SystemClock.uptimeMillis());
8765
8766 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008767 // Make sure we have no pre-ready processes sitting around.
8768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008769 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8770 ResolveInfo ri = mContext.getPackageManager()
8771 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008772 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008773 CharSequence errorMsg = null;
8774 if (ri != null) {
8775 ActivityInfo ai = ri.activityInfo;
8776 ApplicationInfo app = ai.applicationInfo;
8777 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8778 mTopAction = Intent.ACTION_FACTORY_TEST;
8779 mTopData = null;
8780 mTopComponent = new ComponentName(app.packageName,
8781 ai.name);
8782 } else {
8783 errorMsg = mContext.getResources().getText(
8784 com.android.internal.R.string.factorytest_not_system);
8785 }
8786 } else {
8787 errorMsg = mContext.getResources().getText(
8788 com.android.internal.R.string.factorytest_no_action);
8789 }
8790 if (errorMsg != null) {
8791 mTopAction = null;
8792 mTopData = null;
8793 mTopComponent = null;
8794 Message msg = Message.obtain();
8795 msg.what = SHOW_FACTORY_ERROR_MSG;
8796 msg.getData().putCharSequence("msg", errorMsg);
8797 mHandler.sendMessage(msg);
8798 }
8799 }
8800 }
8801
8802 retrieveSettings();
8803
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008804 if (goingCallback != null) goingCallback.run();
8805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008806 synchronized (this) {
8807 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8808 try {
8809 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008810 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008811 if (apps != null) {
8812 int N = apps.size();
8813 int i;
8814 for (i=0; i<N; i++) {
8815 ApplicationInfo info
8816 = (ApplicationInfo)apps.get(i);
8817 if (info != null &&
8818 !info.packageName.equals("android")) {
8819 addAppLocked(info);
8820 }
8821 }
8822 }
8823 } catch (RemoteException ex) {
8824 // pm is in same process, this will never happen.
8825 }
8826 }
8827
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008828 // Start up initial activity.
8829 mBooting = true;
8830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008831 try {
8832 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8833 Message msg = Message.obtain();
8834 msg.what = SHOW_UID_ERROR_MSG;
8835 mHandler.sendMessage(msg);
8836 }
8837 } catch (RemoteException e) {
8838 }
8839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008840 resumeTopActivityLocked(null);
8841 }
8842 }
8843
Dan Egnorb7f03672009-12-09 16:22:32 -08008844 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008845 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008846 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008847 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008848 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008849 startAppProblemLocked(app);
8850 app.stopFreezingAllLocked();
8851 return handleAppCrashLocked(app);
8852 }
8853
Dan Egnorb7f03672009-12-09 16:22:32 -08008854 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008855 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008856 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008857 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008858 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8859 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008860 startAppProblemLocked(app);
8861 app.stopFreezingAllLocked();
8862 }
8863
8864 /**
8865 * Generate a process error record, suitable for attachment to a ProcessRecord.
8866 *
8867 * @param app The ProcessRecord in which the error occurred.
8868 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8869 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008870 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008871 * @param shortMsg Short message describing the crash.
8872 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008873 * @param stackTrace Full crash stack trace, may be null.
8874 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008875 * @return Returns a fully-formed AppErrorStateInfo record.
8876 */
8877 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008878 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008879 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008881 report.condition = condition;
8882 report.processName = app.processName;
8883 report.pid = app.pid;
8884 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008885 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008886 report.shortMsg = shortMsg;
8887 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008888 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008889
8890 return report;
8891 }
8892
Dan Egnor42471dd2010-01-07 17:25:22 -08008893 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008894 synchronized (this) {
8895 app.crashing = false;
8896 app.crashingReport = null;
8897 app.notResponding = false;
8898 app.notRespondingReport = null;
8899 if (app.anrDialog == fromDialog) {
8900 app.anrDialog = null;
8901 }
8902 if (app.waitDialog == fromDialog) {
8903 app.waitDialog = null;
8904 }
8905 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008906 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008907 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008908 + app.processName
8909 + " (pid=" + app.pid + ") at user's request");
8910 Process.killProcess(app.pid);
8911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008912 }
8913 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008914
Dan Egnorb7f03672009-12-09 16:22:32 -08008915 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008916 long now = SystemClock.uptimeMillis();
8917
8918 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8919 app.info.uid);
8920 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8921 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008922 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008923 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008924 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008925 app.info.processName, app.info.uid);
8926 killServicesLocked(app, false);
8927 for (int i=mHistory.size()-1; i>=0; i--) {
8928 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8929 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008930 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008931 + r.intent.getComponent().flattenToShortString());
8932 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8933 }
8934 }
8935 if (!app.persistent) {
8936 // We don't want to start this process again until the user
8937 // explicitly does so... but for persistent process, we really
8938 // need to keep it running. If a persistent process is actually
8939 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008940 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008941 app.info.processName);
8942 mBadProcesses.put(app.info.processName, app.info.uid, now);
8943 app.bad = true;
8944 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8945 app.removed = true;
8946 removeProcessLocked(app, false);
8947 return false;
8948 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008949 } else {
8950 HistoryRecord r = topRunningActivityLocked(null);
8951 if (r.app == app) {
8952 // If the top running activity is from this crashing
8953 // process, then terminate it to avoid getting in a loop.
8954 Slog.w(TAG, " Force finishing activity "
8955 + r.intent.getComponent().flattenToShortString());
8956 int index = indexOfTokenLocked(r);
8957 finishActivityLocked(r, index,
8958 Activity.RESULT_CANCELED, null, "crashed");
8959 // Also terminate an activities below it that aren't yet
8960 // stopped, to avoid a situation where one will get
8961 // re-start our crashing activity once it gets resumed again.
8962 index--;
8963 if (index >= 0) {
8964 r = (HistoryRecord)mHistory.get(index);
8965 if (r.state == ActivityState.RESUMED
8966 || r.state == ActivityState.PAUSING
8967 || r.state == ActivityState.PAUSED) {
8968 if (!r.isHomeActivity) {
8969 Slog.w(TAG, " Force finishing activity "
8970 + r.intent.getComponent().flattenToShortString());
8971 finishActivityLocked(r, index,
8972 Activity.RESULT_CANCELED, null, "crashed");
8973 }
8974 }
8975 }
8976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008977 }
8978
8979 // Bump up the crash count of any services currently running in the proc.
8980 if (app.services.size() != 0) {
8981 // Any services running in the application need to be placed
8982 // back in the pending list.
8983 Iterator it = app.services.iterator();
8984 while (it.hasNext()) {
8985 ServiceRecord sr = (ServiceRecord)it.next();
8986 sr.crashCount++;
8987 }
8988 }
8989
8990 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8991 return true;
8992 }
8993
8994 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008995 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8996 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008997 skipCurrentReceiverLocked(app);
8998 }
8999
9000 void skipCurrentReceiverLocked(ProcessRecord app) {
9001 boolean reschedule = false;
9002 BroadcastRecord r = app.curReceiver;
9003 if (r != null) {
9004 // The current broadcast is waiting for this app's receiver
9005 // to be finished. Looks like that's not going to happen, so
9006 // let the broadcast continue.
9007 logBroadcastReceiverDiscard(r);
9008 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9009 r.resultExtras, r.resultAbort, true);
9010 reschedule = true;
9011 }
9012 r = mPendingBroadcast;
9013 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009014 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009015 "skip & discard pending app " + r);
9016 logBroadcastReceiverDiscard(r);
9017 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9018 r.resultExtras, r.resultAbort, true);
9019 reschedule = true;
9020 }
9021 if (reschedule) {
9022 scheduleBroadcastsLocked();
9023 }
9024 }
9025
Dan Egnor60d87622009-12-16 16:32:58 -08009026 /**
9027 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9028 * The application process will exit immediately after this call returns.
9029 * @param app object of the crashing app, null for the system server
9030 * @param crashInfo describing the exception
9031 */
9032 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9033 ProcessRecord r = findAppProcess(app);
9034
9035 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9036 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009037 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009038 crashInfo.exceptionClassName,
9039 crashInfo.exceptionMessage,
9040 crashInfo.throwFileName,
9041 crashInfo.throwLineNumber);
9042
Dan Egnor42471dd2010-01-07 17:25:22 -08009043 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009044
9045 crashApplication(r, crashInfo);
9046 }
9047
9048 /**
9049 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9050 * @param app object of the crashing app, null for the system server
9051 * @param tag reported by the caller
9052 * @param crashInfo describing the context of the error
9053 * @return true if the process should exit immediately (WTF is fatal)
9054 */
9055 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009056 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009057 ProcessRecord r = findAppProcess(app);
9058
9059 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9060 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009061 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009062 tag, crashInfo.exceptionMessage);
9063
Dan Egnor42471dd2010-01-07 17:25:22 -08009064 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009065
Doug Zongker43866e02010-01-07 12:09:54 -08009066 if (Settings.Secure.getInt(mContext.getContentResolver(),
9067 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009068 crashApplication(r, crashInfo);
9069 return true;
9070 } else {
9071 return false;
9072 }
9073 }
9074
9075 /**
9076 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9077 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9078 */
9079 private ProcessRecord findAppProcess(IBinder app) {
9080 if (app == null) {
9081 return null;
9082 }
9083
9084 synchronized (this) {
9085 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9086 final int NA = apps.size();
9087 for (int ia=0; ia<NA; ia++) {
9088 ProcessRecord p = apps.valueAt(ia);
9089 if (p.thread != null && p.thread.asBinder() == app) {
9090 return p;
9091 }
9092 }
9093 }
9094
Joe Onorato8a9b2202010-02-26 18:56:32 -08009095 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009096 return null;
9097 }
9098 }
9099
9100 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009101 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009102 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009103 * @param process which caused the error, null means the system server
9104 * @param activity which triggered the error, null if unknown
9105 * @param parent activity related to the error, null if unknown
9106 * @param subject line related to the error, null if absent
9107 * @param report in long form describing the error, null if absent
9108 * @param logFile to include in the report, null if none
9109 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009110 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009111 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009112 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9113 final String report, final File logFile,
9114 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009115 // NOTE -- this must never acquire the ActivityManagerService lock,
9116 // otherwise the watchdog may be prevented from resetting the system.
9117
Dan Egnora455d192010-03-12 08:52:28 -08009118 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009119 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009120 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009121 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009122 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009123 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009124 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009125 }
9126
Dan Egnora455d192010-03-12 08:52:28 -08009127 final String dropboxTag = prefix + eventType;
9128 final DropBoxManager dbox = (DropBoxManager)
9129 mContext.getSystemService(Context.DROPBOX_SERVICE);
9130
9131 // Exit early if the dropbox isn't configured to accept this report type.
9132 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9133
9134 final StringBuilder sb = new StringBuilder(1024);
9135 if (process == null || process.pid == MY_PID) {
9136 sb.append("Process: system_server\n");
9137 } else {
9138 sb.append("Process: ").append(process.processName).append("\n");
9139 }
9140 if (process != null) {
9141 int flags = process.info.flags;
9142 IPackageManager pm = ActivityThread.getPackageManager();
9143 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9144 for (String pkg : process.pkgList) {
9145 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009146 try {
Dan Egnora455d192010-03-12 08:52:28 -08009147 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9148 if (pi != null) {
9149 sb.append(" v").append(pi.versionCode);
9150 if (pi.versionName != null) {
9151 sb.append(" (").append(pi.versionName).append(")");
9152 }
9153 }
9154 } catch (RemoteException e) {
9155 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009156 }
Dan Egnora455d192010-03-12 08:52:28 -08009157 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009158 }
Dan Egnora455d192010-03-12 08:52:28 -08009159 }
9160 if (activity != null) {
9161 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9162 }
9163 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9164 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9165 }
9166 if (parent != null && parent != activity) {
9167 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9168 }
9169 if (subject != null) {
9170 sb.append("Subject: ").append(subject).append("\n");
9171 }
9172 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9173 sb.append("\n");
9174
9175 // Do the rest in a worker thread to avoid blocking the caller on I/O
9176 // (After this point, we shouldn't access AMS internal data structures.)
9177 Thread worker = new Thread("Error dump: " + dropboxTag) {
9178 @Override
9179 public void run() {
9180 if (report != null) {
9181 sb.append(report);
9182 }
9183 if (logFile != null) {
9184 try {
9185 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9186 } catch (IOException e) {
9187 Slog.e(TAG, "Error reading " + logFile, e);
9188 }
9189 }
9190 if (crashInfo != null && crashInfo.stackTrace != null) {
9191 sb.append(crashInfo.stackTrace);
9192 }
9193
9194 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9195 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9196 if (lines > 0) {
9197 sb.append("\n");
9198
9199 // Merge several logcat streams, and take the last N lines
9200 InputStreamReader input = null;
9201 try {
9202 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9203 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9204 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9205
9206 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9207 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9208 input = new InputStreamReader(logcat.getInputStream());
9209
9210 int num;
9211 char[] buf = new char[8192];
9212 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9213 } catch (IOException e) {
9214 Slog.e(TAG, "Error running logcat", e);
9215 } finally {
9216 if (input != null) try { input.close(); } catch (IOException e) {}
9217 }
9218 }
9219
9220 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009221 }
Dan Egnora455d192010-03-12 08:52:28 -08009222 };
9223
9224 if (process == null || process.pid == MY_PID) {
9225 worker.run(); // We may be about to die -- need to run this synchronously
9226 } else {
9227 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009228 }
9229 }
9230
9231 /**
9232 * Bring up the "unexpected error" dialog box for a crashing app.
9233 * Deal with edge cases (intercepts from instrumented applications,
9234 * ActivityController, error intent receivers, that sort of thing).
9235 * @param r the application crashing
9236 * @param crashInfo describing the failure
9237 */
9238 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009239 long timeMillis = System.currentTimeMillis();
9240 String shortMsg = crashInfo.exceptionClassName;
9241 String longMsg = crashInfo.exceptionMessage;
9242 String stackTrace = crashInfo.stackTrace;
9243 if (shortMsg != null && longMsg != null) {
9244 longMsg = shortMsg + ": " + longMsg;
9245 } else if (shortMsg != null) {
9246 longMsg = shortMsg;
9247 }
9248
Dan Egnor60d87622009-12-16 16:32:58 -08009249 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009251 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009252 try {
9253 String name = r != null ? r.processName : null;
9254 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009255 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009256 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009257 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009258 + " at watcher's request");
9259 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009260 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009261 }
9262 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009263 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009264 }
9265 }
9266
9267 final long origId = Binder.clearCallingIdentity();
9268
9269 // If this process is running instrumentation, finish it.
9270 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009271 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009272 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009273 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9274 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009275 Bundle info = new Bundle();
9276 info.putString("shortMsg", shortMsg);
9277 info.putString("longMsg", longMsg);
9278 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9279 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009280 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009281 }
9282
Dan Egnor60d87622009-12-16 16:32:58 -08009283 // If we can't identify the process or it's already exceeded its crash quota,
9284 // quit right away without showing a crash dialog.
9285 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009287 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009288 }
9289
9290 Message msg = Message.obtain();
9291 msg.what = SHOW_ERROR_MSG;
9292 HashMap data = new HashMap();
9293 data.put("result", result);
9294 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 msg.obj = data;
9296 mHandler.sendMessage(msg);
9297
9298 Binder.restoreCallingIdentity(origId);
9299 }
9300
9301 int res = result.get();
9302
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009303 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009304 synchronized (this) {
9305 if (r != null) {
9306 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9307 SystemClock.uptimeMillis());
9308 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009309 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009310 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009311 }
9312 }
9313
9314 if (appErrorIntent != null) {
9315 try {
9316 mContext.startActivity(appErrorIntent);
9317 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009318 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009321 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009322
9323 Intent createAppErrorIntentLocked(ProcessRecord r,
9324 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9325 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009326 if (report == null) {
9327 return null;
9328 }
9329 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9330 result.setComponent(r.errorReportReceiver);
9331 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9332 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9333 return result;
9334 }
9335
Dan Egnorb7f03672009-12-09 16:22:32 -08009336 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9337 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009338 if (r.errorReportReceiver == null) {
9339 return null;
9340 }
9341
9342 if (!r.crashing && !r.notResponding) {
9343 return null;
9344 }
9345
Dan Egnorb7f03672009-12-09 16:22:32 -08009346 ApplicationErrorReport report = new ApplicationErrorReport();
9347 report.packageName = r.info.packageName;
9348 report.installerPackageName = r.errorReportReceiver.getPackageName();
9349 report.processName = r.processName;
9350 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009351 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009352
Dan Egnorb7f03672009-12-09 16:22:32 -08009353 if (r.crashing) {
9354 report.type = ApplicationErrorReport.TYPE_CRASH;
9355 report.crashInfo = crashInfo;
9356 } else if (r.notResponding) {
9357 report.type = ApplicationErrorReport.TYPE_ANR;
9358 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009359
Dan Egnorb7f03672009-12-09 16:22:32 -08009360 report.anrInfo.activity = r.notRespondingReport.tag;
9361 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9362 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009363 }
9364
Dan Egnorb7f03672009-12-09 16:22:32 -08009365 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009366 }
9367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009368 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9369 // assume our apps are happy - lazy create the list
9370 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9371
9372 synchronized (this) {
9373
9374 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009375 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9376 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009377 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9378 // This one's in trouble, so we'll generate a report for it
9379 // crashes are higher priority (in case there's a crash *and* an anr)
9380 ActivityManager.ProcessErrorStateInfo report = null;
9381 if (app.crashing) {
9382 report = app.crashingReport;
9383 } else if (app.notResponding) {
9384 report = app.notRespondingReport;
9385 }
9386
9387 if (report != null) {
9388 if (errList == null) {
9389 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9390 }
9391 errList.add(report);
9392 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009393 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009394 " crashing = " + app.crashing +
9395 " notResponding = " + app.notResponding);
9396 }
9397 }
9398 }
9399 }
9400
9401 return errList;
9402 }
9403
9404 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9405 // Lazy instantiation of list
9406 List<ActivityManager.RunningAppProcessInfo> runList = null;
9407 synchronized (this) {
9408 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009409 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9410 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009411 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9412 // Generate process state info for running application
9413 ActivityManager.RunningAppProcessInfo currApp =
9414 new ActivityManager.RunningAppProcessInfo(app.processName,
9415 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009416 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009417 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009418 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009419 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9420 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9421 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009422 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9423 } else if (adj >= HOME_APP_ADJ) {
9424 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9425 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009426 } else if (adj >= SECONDARY_SERVER_ADJ) {
9427 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9428 } else if (adj >= VISIBLE_APP_ADJ) {
9429 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9430 } else {
9431 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9432 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009433 currApp.importanceReasonCode = app.adjTypeCode;
9434 if (app.adjSource instanceof ProcessRecord) {
9435 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9436 } else if (app.adjSource instanceof HistoryRecord) {
9437 HistoryRecord r = (HistoryRecord)app.adjSource;
9438 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9439 }
9440 if (app.adjTarget instanceof ComponentName) {
9441 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9442 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009443 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009444 // + " lru=" + currApp.lru);
9445 if (runList == null) {
9446 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9447 }
9448 runList.add(currApp);
9449 }
9450 }
9451 }
9452 return runList;
9453 }
9454
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009455 public List<ApplicationInfo> getRunningExternalApplications() {
9456 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9457 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9458 if (runningApps != null && runningApps.size() > 0) {
9459 Set<String> extList = new HashSet<String>();
9460 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9461 if (app.pkgList != null) {
9462 for (String pkg : app.pkgList) {
9463 extList.add(pkg);
9464 }
9465 }
9466 }
9467 IPackageManager pm = ActivityThread.getPackageManager();
9468 for (String pkg : extList) {
9469 try {
9470 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9471 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9472 retList.add(info);
9473 }
9474 } catch (RemoteException e) {
9475 }
9476 }
9477 }
9478 return retList;
9479 }
9480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009481 @Override
9482 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009483 if (checkCallingPermission(android.Manifest.permission.DUMP)
9484 != PackageManager.PERMISSION_GRANTED) {
9485 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9486 + Binder.getCallingPid()
9487 + ", uid=" + Binder.getCallingUid()
9488 + " without permission "
9489 + android.Manifest.permission.DUMP);
9490 return;
9491 }
9492
9493 boolean dumpAll = false;
9494
9495 int opti = 0;
9496 while (opti < args.length) {
9497 String opt = args[opti];
9498 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9499 break;
9500 }
9501 opti++;
9502 if ("-a".equals(opt)) {
9503 dumpAll = true;
9504 } else if ("-h".equals(opt)) {
9505 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009506 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009507 pw.println(" cmd may be one of:");
9508 pw.println(" activities: activity stack state");
9509 pw.println(" broadcasts: broadcast state");
9510 pw.println(" intents: pending intent state");
9511 pw.println(" processes: process state");
9512 pw.println(" providers: content provider state");
9513 pw.println(" services: service state");
9514 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009515 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009516 } else {
9517 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009518 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009519 }
9520
9521 // Is the caller requesting to dump a particular piece of data?
9522 if (opti < args.length) {
9523 String cmd = args[opti];
9524 opti++;
9525 if ("activities".equals(cmd) || "a".equals(cmd)) {
9526 synchronized (this) {
9527 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009528 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009529 return;
9530 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9531 synchronized (this) {
9532 dumpBroadcastsLocked(fd, pw, args, opti, true);
9533 }
9534 return;
9535 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9536 synchronized (this) {
9537 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9538 }
9539 return;
9540 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9541 synchronized (this) {
9542 dumpProcessesLocked(fd, pw, args, opti, true);
9543 }
9544 return;
9545 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9546 synchronized (this) {
9547 dumpProvidersLocked(fd, pw, args, opti, true);
9548 }
9549 return;
9550 } else if ("service".equals(cmd)) {
9551 dumpService(fd, pw, args, opti, true);
9552 return;
9553 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9554 synchronized (this) {
9555 dumpServicesLocked(fd, pw, args, opti, true);
9556 }
9557 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009558 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009559 }
9560
9561 // No piece of data specified, dump everything.
9562 synchronized (this) {
9563 boolean needSep;
9564 if (dumpAll) {
9565 pw.println("Providers in Current Activity Manager State:");
9566 }
9567 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9568 if (needSep) {
9569 pw.println(" ");
9570 }
9571 if (dumpAll) {
9572 pw.println("-------------------------------------------------------------------------------");
9573 pw.println("Broadcasts in Current Activity Manager State:");
9574 }
9575 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9576 if (needSep) {
9577 pw.println(" ");
9578 }
9579 if (dumpAll) {
9580 pw.println("-------------------------------------------------------------------------------");
9581 pw.println("Services in Current Activity Manager State:");
9582 }
9583 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9584 if (needSep) {
9585 pw.println(" ");
9586 }
9587 if (dumpAll) {
9588 pw.println("-------------------------------------------------------------------------------");
9589 pw.println("PendingIntents in Current Activity Manager State:");
9590 }
9591 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9592 if (needSep) {
9593 pw.println(" ");
9594 }
9595 if (dumpAll) {
9596 pw.println("-------------------------------------------------------------------------------");
9597 pw.println("Activities in Current Activity Manager State:");
9598 }
9599 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9600 if (needSep) {
9601 pw.println(" ");
9602 }
9603 if (dumpAll) {
9604 pw.println("-------------------------------------------------------------------------------");
9605 pw.println("Processes in Current Activity Manager State:");
9606 }
9607 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9608 }
9609 }
9610
9611 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9612 int opti, boolean dumpAll, boolean needHeader) {
9613 if (needHeader) {
9614 pw.println(" Activity stack:");
9615 }
9616 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9617 pw.println(" ");
9618 pw.println(" Running activities (most recent first):");
9619 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9620 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009622 pw.println(" Activities waiting for another to become visible:");
9623 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9624 }
9625 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009627 pw.println(" Activities waiting to stop:");
9628 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9629 }
9630 if (mFinishingActivities.size() > 0) {
9631 pw.println(" ");
9632 pw.println(" Activities waiting to finish:");
9633 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009636 pw.println(" ");
9637 pw.println(" mPausingActivity: " + mPausingActivity);
9638 pw.println(" mResumedActivity: " + mResumedActivity);
9639 pw.println(" mFocusedActivity: " + mFocusedActivity);
9640 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009641
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009642 if (dumpAll && mRecentTasks.size() > 0) {
9643 pw.println(" ");
9644 pw.println("Recent tasks in Current Activity Manager State:");
9645
9646 final int N = mRecentTasks.size();
9647 for (int i=0; i<N; i++) {
9648 TaskRecord tr = mRecentTasks.get(i);
9649 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9650 pw.println(tr);
9651 mRecentTasks.get(i).dump(pw, " ");
9652 }
9653 }
9654
9655 pw.println(" ");
9656 pw.println(" mCurTask: " + mCurTask);
9657
9658 return true;
9659 }
9660
9661 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9662 int opti, boolean dumpAll) {
9663 boolean needSep = false;
9664 int numPers = 0;
9665
9666 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9668 final int NA = procs.size();
9669 for (int ia=0; ia<NA; ia++) {
9670 if (!needSep) {
9671 pw.println(" All known processes:");
9672 needSep = true;
9673 }
9674 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009675 pw.print(r.persistent ? " *PERS*" : " *APP*");
9676 pw.print(" UID "); pw.print(procs.keyAt(ia));
9677 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009678 r.dump(pw, " ");
9679 if (r.persistent) {
9680 numPers++;
9681 }
9682 }
9683 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009684 }
9685
9686 if (mLruProcesses.size() > 0) {
9687 if (needSep) pw.println(" ");
9688 needSep = true;
9689 pw.println(" Running processes (most recent first):");
9690 dumpProcessList(pw, this, mLruProcesses, " ",
9691 "App ", "PERS", true);
9692 needSep = true;
9693 }
9694
9695 synchronized (mPidsSelfLocked) {
9696 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009697 if (needSep) pw.println(" ");
9698 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009699 pw.println(" PID mappings:");
9700 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9701 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9702 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009703 }
9704 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009705 }
9706
9707 if (mForegroundProcesses.size() > 0) {
9708 if (needSep) pw.println(" ");
9709 needSep = true;
9710 pw.println(" Foreground Processes:");
9711 for (int i=0; i<mForegroundProcesses.size(); i++) {
9712 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9713 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009714 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009715 }
9716
9717 if (mPersistentStartingProcesses.size() > 0) {
9718 if (needSep) pw.println(" ");
9719 needSep = true;
9720 pw.println(" Persisent processes that are starting:");
9721 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9722 "Starting Norm", "Restarting PERS", false);
9723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009724
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009725 if (mStartingProcesses.size() > 0) {
9726 if (needSep) pw.println(" ");
9727 needSep = true;
9728 pw.println(" Processes that are starting:");
9729 dumpProcessList(pw, this, mStartingProcesses, " ",
9730 "Starting Norm", "Starting PERS", false);
9731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009732
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009733 if (mRemovedProcesses.size() > 0) {
9734 if (needSep) pw.println(" ");
9735 needSep = true;
9736 pw.println(" Processes that are being removed:");
9737 dumpProcessList(pw, this, mRemovedProcesses, " ",
9738 "Removed Norm", "Removed PERS", false);
9739 }
9740
9741 if (mProcessesOnHold.size() > 0) {
9742 if (needSep) pw.println(" ");
9743 needSep = true;
9744 pw.println(" Processes that are on old until the system is ready:");
9745 dumpProcessList(pw, this, mProcessesOnHold, " ",
9746 "OnHold Norm", "OnHold PERS", false);
9747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009748
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009749 if (mProcessesToGc.size() > 0) {
9750 if (needSep) pw.println(" ");
9751 needSep = true;
9752 pw.println(" Processes that are waiting to GC:");
9753 long now = SystemClock.uptimeMillis();
9754 for (int i=0; i<mProcessesToGc.size(); i++) {
9755 ProcessRecord proc = mProcessesToGc.get(i);
9756 pw.print(" Process "); pw.println(proc);
9757 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9758 pw.print(", last gced=");
9759 pw.print(now-proc.lastRequestedGc);
9760 pw.print(" ms ago, last lowMem=");
9761 pw.print(now-proc.lastLowMemory);
9762 pw.println(" ms ago");
9763
9764 }
9765 }
9766
9767 if (mProcessCrashTimes.getMap().size() > 0) {
9768 if (needSep) pw.println(" ");
9769 needSep = true;
9770 pw.println(" Time since processes crashed:");
9771 long now = SystemClock.uptimeMillis();
9772 for (Map.Entry<String, SparseArray<Long>> procs
9773 : mProcessCrashTimes.getMap().entrySet()) {
9774 SparseArray<Long> uids = procs.getValue();
9775 final int N = uids.size();
9776 for (int i=0; i<N; i++) {
9777 pw.print(" Process "); pw.print(procs.getKey());
9778 pw.print(" uid "); pw.print(uids.keyAt(i));
9779 pw.print(": last crashed ");
9780 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009781 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009782 }
9783 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009784 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009785
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009786 if (mBadProcesses.getMap().size() > 0) {
9787 if (needSep) pw.println(" ");
9788 needSep = true;
9789 pw.println(" Bad processes:");
9790 for (Map.Entry<String, SparseArray<Long>> procs
9791 : mBadProcesses.getMap().entrySet()) {
9792 SparseArray<Long> uids = procs.getValue();
9793 final int N = uids.size();
9794 for (int i=0; i<N; i++) {
9795 pw.print(" Bad process "); pw.print(procs.getKey());
9796 pw.print(" uid "); pw.print(uids.keyAt(i));
9797 pw.print(": crashed at time ");
9798 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009799 }
9800 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009802
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009803 pw.println(" ");
9804 pw.println(" mHomeProcess: " + mHomeProcess);
9805 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07009806 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009807 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9808 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9809 || mOrigWaitForDebugger) {
9810 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9811 + " mDebugTransient=" + mDebugTransient
9812 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9813 }
9814 if (mAlwaysFinishActivities || mController != null) {
9815 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9816 + " mController=" + mController);
9817 }
9818 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009820 pw.println(" mStartRunning=" + mStartRunning
9821 + " mSystemReady=" + mSystemReady
9822 + " mBooting=" + mBooting
9823 + " mBooted=" + mBooted
9824 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 pw.println(" mGoingToSleep=" + mGoingToSleep);
9826 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009827 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009828
9829 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 }
9831
9832 /**
9833 * There are three ways to call this:
9834 * - no service specified: dump all the services
9835 * - a flattened component name that matched an existing service was specified as the
9836 * first arg: dump that one service
9837 * - the first arg isn't the flattened component name of an existing service:
9838 * dump all services whose component contains the first arg as a substring
9839 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009840 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9841 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009842 String[] newArgs;
9843 String componentNameString;
9844 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009845 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009846 componentNameString = null;
9847 newArgs = EMPTY_STRING_ARRAY;
9848 r = null;
9849 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009850 componentNameString = args[opti];
9851 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009852 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9853 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009854 newArgs = new String[args.length - opti];
9855 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009856 }
9857
9858 if (r != null) {
9859 dumpService(fd, pw, r, newArgs);
9860 } else {
9861 for (ServiceRecord r1 : mServices.values()) {
9862 if (componentNameString == null
9863 || r1.name.flattenToString().contains(componentNameString)) {
9864 dumpService(fd, pw, r1, newArgs);
9865 }
9866 }
9867 }
9868 }
9869
9870 /**
9871 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9872 * there is a thread associated with the service.
9873 */
9874 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9875 pw.println(" Service " + r.name.flattenToString());
9876 if (r.app != null && r.app.thread != null) {
9877 try {
9878 // flush anything that is already in the PrintWriter since the thread is going
9879 // to write to the file descriptor directly
9880 pw.flush();
9881 r.app.thread.dumpService(fd, r, args);
9882 pw.print("\n");
9883 } catch (RemoteException e) {
9884 pw.println("got a RemoteException while dumping the service");
9885 }
9886 }
9887 }
9888
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009889 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9890 int opti, boolean dumpAll) {
9891 boolean needSep = false;
9892
9893 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009894 if (mRegisteredReceivers.size() > 0) {
9895 pw.println(" ");
9896 pw.println(" Registered Receivers:");
9897 Iterator it = mRegisteredReceivers.values().iterator();
9898 while (it.hasNext()) {
9899 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009900 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901 r.dump(pw, " ");
9902 }
9903 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 pw.println(" ");
9906 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009907 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009908 needSep = true;
9909 }
9910
9911 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9912 || mPendingBroadcast != null) {
9913 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009914 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009915 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009916 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009917 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9918 pw.println(" Broadcast #" + i + ":");
9919 mParallelBroadcasts.get(i).dump(pw, " ");
9920 }
9921 if (mOrderedBroadcasts.size() > 0) {
9922 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07009923 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009924 }
9925 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9926 pw.println(" Serialized Broadcast #" + i + ":");
9927 mOrderedBroadcasts.get(i).dump(pw, " ");
9928 }
9929 pw.println(" ");
9930 pw.println(" Pending broadcast:");
9931 if (mPendingBroadcast != null) {
9932 mPendingBroadcast.dump(pw, " ");
9933 } else {
9934 pw.println(" (null)");
9935 }
9936 needSep = true;
9937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009938
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009939 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009940 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009941 pw.println(" Historical broadcasts:");
9942 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9943 BroadcastRecord r = mBroadcastHistory[i];
9944 if (r == null) {
9945 break;
9946 }
9947 pw.println(" Historical Broadcast #" + i + ":");
9948 r.dump(pw, " ");
9949 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009950 needSep = true;
9951 }
9952
9953 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009954 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009955 pw.println(" Sticky broadcasts:");
9956 StringBuilder sb = new StringBuilder(128);
9957 for (Map.Entry<String, ArrayList<Intent>> ent
9958 : mStickyBroadcasts.entrySet()) {
9959 pw.print(" * Sticky action "); pw.print(ent.getKey());
9960 pw.println(":");
9961 ArrayList<Intent> intents = ent.getValue();
9962 final int N = intents.size();
9963 for (int i=0; i<N; i++) {
9964 sb.setLength(0);
9965 sb.append(" Intent: ");
9966 intents.get(i).toShortString(sb, true, false);
9967 pw.println(sb.toString());
9968 Bundle bundle = intents.get(i).getExtras();
9969 if (bundle != null) {
9970 pw.print(" ");
9971 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009972 }
9973 }
9974 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009975 needSep = true;
9976 }
9977
9978 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009979 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009980 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009981 pw.println(" mHandler:");
9982 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009983 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009984 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009985
9986 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009987 }
9988
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009989 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9990 int opti, boolean dumpAll) {
9991 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009993 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009994 if (mServices.size() > 0) {
9995 pw.println(" Active services:");
9996 Iterator<ServiceRecord> it = mServices.values().iterator();
9997 while (it.hasNext()) {
9998 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009999 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 r.dump(pw, " ");
10001 }
10002 needSep = true;
10003 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010005
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010006 if (mPendingServices.size() > 0) {
10007 if (needSep) pw.println(" ");
10008 pw.println(" Pending services:");
10009 for (int i=0; i<mPendingServices.size(); i++) {
10010 ServiceRecord r = mPendingServices.get(i);
10011 pw.print(" * Pending "); pw.println(r);
10012 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010013 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010014 needSep = true;
10015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010016
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010017 if (mRestartingServices.size() > 0) {
10018 if (needSep) pw.println(" ");
10019 pw.println(" Restarting services:");
10020 for (int i=0; i<mRestartingServices.size(); i++) {
10021 ServiceRecord r = mRestartingServices.get(i);
10022 pw.print(" * Restarting "); pw.println(r);
10023 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010024 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010025 needSep = true;
10026 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010027
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010028 if (mStoppingServices.size() > 0) {
10029 if (needSep) pw.println(" ");
10030 pw.println(" Stopping services:");
10031 for (int i=0; i<mStoppingServices.size(); i++) {
10032 ServiceRecord r = mStoppingServices.get(i);
10033 pw.print(" * Stopping "); pw.println(r);
10034 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010035 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010036 needSep = true;
10037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010039 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010040 if (mServiceConnections.size() > 0) {
10041 if (needSep) pw.println(" ");
10042 pw.println(" Connection bindings to services:");
10043 Iterator<ConnectionRecord> it
10044 = mServiceConnections.values().iterator();
10045 while (it.hasNext()) {
10046 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010047 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010048 r.dump(pw, " ");
10049 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010050 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010051 }
10052 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010053
10054 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 }
10056
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010057 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10058 int opti, boolean dumpAll) {
10059 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010060
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010061 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010062 if (mProvidersByClass.size() > 0) {
10063 if (needSep) pw.println(" ");
10064 pw.println(" Published content providers (by class):");
10065 Iterator it = mProvidersByClass.entrySet().iterator();
10066 while (it.hasNext()) {
10067 Map.Entry e = (Map.Entry)it.next();
10068 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010069 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010070 r.dump(pw, " ");
10071 }
10072 needSep = true;
10073 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010074
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010075 if (mProvidersByName.size() > 0) {
10076 pw.println(" ");
10077 pw.println(" Authority to provider mappings:");
10078 Iterator it = mProvidersByName.entrySet().iterator();
10079 while (it.hasNext()) {
10080 Map.Entry e = (Map.Entry)it.next();
10081 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
10082 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10083 pw.println(r);
10084 }
10085 needSep = true;
10086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010087 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010088
10089 if (mLaunchingProviders.size() > 0) {
10090 if (needSep) pw.println(" ");
10091 pw.println(" Launching content providers:");
10092 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10093 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10094 pw.println(mLaunchingProviders.get(i));
10095 }
10096 needSep = true;
10097 }
10098
10099 if (mGrantedUriPermissions.size() > 0) {
10100 pw.println();
10101 pw.println("Granted Uri Permissions:");
10102 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10103 int uid = mGrantedUriPermissions.keyAt(i);
10104 HashMap<Uri, UriPermission> perms
10105 = mGrantedUriPermissions.valueAt(i);
10106 pw.print(" * UID "); pw.print(uid);
10107 pw.println(" holds:");
10108 for (UriPermission perm : perms.values()) {
10109 pw.print(" "); pw.println(perm);
10110 perm.dump(pw, " ");
10111 }
10112 }
10113 needSep = true;
10114 }
10115
10116 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010117 }
10118
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010119 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10120 int opti, boolean dumpAll) {
10121 boolean needSep = false;
10122
10123 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010124 if (this.mIntentSenderRecords.size() > 0) {
10125 Iterator<WeakReference<PendingIntentRecord>> it
10126 = mIntentSenderRecords.values().iterator();
10127 while (it.hasNext()) {
10128 WeakReference<PendingIntentRecord> ref = it.next();
10129 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010130 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010131 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010132 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010133 rec.dump(pw, " ");
10134 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010135 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010136 }
10137 }
10138 }
10139 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010140
10141 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010142 }
10143
10144 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010145 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010146 TaskRecord lastTask = null;
10147 for (int i=list.size()-1; i>=0; i--) {
10148 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010149 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010150 if (lastTask != r.task) {
10151 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010152 pw.print(prefix);
10153 pw.print(full ? "* " : " ");
10154 pw.println(lastTask);
10155 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010156 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010158 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010159 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10160 pw.print(" #"); pw.print(i); pw.print(": ");
10161 pw.println(r);
10162 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010163 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010165 }
10166 }
10167
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010168 private static String buildOomTag(String prefix, String space, int val, int base) {
10169 if (val == base) {
10170 if (space == null) return prefix;
10171 return prefix + " ";
10172 }
10173 return prefix + "+" + Integer.toString(val-base);
10174 }
10175
10176 private static final int dumpProcessList(PrintWriter pw,
10177 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010178 String prefix, String normalLabel, String persistentLabel,
10179 boolean inclOomAdj) {
10180 int numPers = 0;
10181 for (int i=list.size()-1; i>=0; i--) {
10182 ProcessRecord r = (ProcessRecord)list.get(i);
10183 if (false) {
10184 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10185 + " #" + i + ":");
10186 r.dump(pw, prefix + " ");
10187 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010188 String oomAdj;
10189 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010190 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010191 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010192 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10193 } else if (r.setAdj >= HOME_APP_ADJ) {
10194 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10195 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10196 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10197 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10198 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10199 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10200 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10201 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10202 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010203 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010204 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010205 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010206 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010207 } else {
10208 oomAdj = Integer.toString(r.setAdj);
10209 }
10210 String schedGroup;
10211 switch (r.setSchedGroup) {
10212 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10213 schedGroup = "B";
10214 break;
10215 case Process.THREAD_GROUP_DEFAULT:
10216 schedGroup = "F";
10217 break;
10218 default:
10219 schedGroup = Integer.toString(r.setSchedGroup);
10220 break;
10221 }
10222 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010223 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010224 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010225 if (r.adjSource != null || r.adjTarget != null) {
10226 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010227 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010229 } else {
10230 pw.println(String.format("%s%s #%2d: %s",
10231 prefix, (r.persistent ? persistentLabel : normalLabel),
10232 i, r.toString()));
10233 }
10234 if (r.persistent) {
10235 numPers++;
10236 }
10237 }
10238 return numPers;
10239 }
10240
Dianne Hackborn472ad872010-04-07 17:31:48 -070010241 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010243 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010244 long uptime = SystemClock.uptimeMillis();
10245 long realtime = SystemClock.elapsedRealtime();
10246
10247 if (isCheckinRequest) {
10248 // short checkin version
10249 pw.println(uptime + "," + realtime);
10250 pw.flush();
10251 } else {
10252 pw.println("Applications Memory Usage (kB):");
10253 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10254 }
10255 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10256 ProcessRecord r = (ProcessRecord)list.get(i);
10257 if (r.thread != null) {
10258 if (!isCheckinRequest) {
10259 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10260 pw.flush();
10261 }
10262 try {
10263 r.thread.asBinder().dump(fd, args);
10264 } catch (RemoteException e) {
10265 if (!isCheckinRequest) {
10266 pw.println("Got RemoteException!");
10267 pw.flush();
10268 }
10269 }
10270 }
10271 }
10272 }
10273
10274 /**
10275 * Searches array of arguments for the specified string
10276 * @param args array of argument strings
10277 * @param value value to search for
10278 * @return true if the value is contained in the array
10279 */
10280 private static boolean scanArgs(String[] args, String value) {
10281 if (args != null) {
10282 for (String arg : args) {
10283 if (value.equals(arg)) {
10284 return true;
10285 }
10286 }
10287 }
10288 return false;
10289 }
10290
Dianne Hackborn75b03852009-06-12 15:43:26 -070010291 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292 int count = mHistory.size();
10293
10294 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010295 int index = -1;
10296 for (int i=count-1; i>=0; i--) {
10297 Object o = mHistory.get(i);
10298 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 index = i;
10300 break;
10301 }
10302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010303
10304 return index;
10305 }
10306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010307 private final void killServicesLocked(ProcessRecord app,
10308 boolean allowRestart) {
10309 // Report disconnected services.
10310 if (false) {
10311 // XXX we are letting the client link to the service for
10312 // death notifications.
10313 if (app.services.size() > 0) {
10314 Iterator it = app.services.iterator();
10315 while (it.hasNext()) {
10316 ServiceRecord r = (ServiceRecord)it.next();
10317 if (r.connections.size() > 0) {
10318 Iterator<ConnectionRecord> jt
10319 = r.connections.values().iterator();
10320 while (jt.hasNext()) {
10321 ConnectionRecord c = jt.next();
10322 if (c.binding.client != app) {
10323 try {
10324 //c.conn.connected(r.className, null);
10325 } catch (Exception e) {
10326 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010327 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 + r.shortName
10329 + " from app " + app.processName, e);
10330 }
10331 }
10332 }
10333 }
10334 }
10335 }
10336 }
10337
10338 // Clean up any connections this application has to other services.
10339 if (app.connections.size() > 0) {
10340 Iterator<ConnectionRecord> it = app.connections.iterator();
10341 while (it.hasNext()) {
10342 ConnectionRecord r = it.next();
10343 removeConnectionLocked(r, app, null);
10344 }
10345 }
10346 app.connections.clear();
10347
10348 if (app.services.size() != 0) {
10349 // Any services running in the application need to be placed
10350 // back in the pending list.
10351 Iterator it = app.services.iterator();
10352 while (it.hasNext()) {
10353 ServiceRecord sr = (ServiceRecord)it.next();
10354 synchronized (sr.stats.getBatteryStats()) {
10355 sr.stats.stopLaunchedLocked();
10356 }
10357 sr.app = null;
10358 sr.executeNesting = 0;
10359 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010360
10361 boolean hasClients = sr.bindings.size() > 0;
10362 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010363 Iterator<IntentBindRecord> bindings
10364 = sr.bindings.values().iterator();
10365 while (bindings.hasNext()) {
10366 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010367 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010368 + ": shouldUnbind=" + b.hasBound);
10369 b.binder = null;
10370 b.requested = b.received = b.hasBound = false;
10371 }
10372 }
10373
10374 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010375 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010376 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010377 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378 sr.crashCount, sr.shortName, app.pid);
10379 bringDownServiceLocked(sr, true);
10380 } else if (!allowRestart) {
10381 bringDownServiceLocked(sr, true);
10382 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010383 boolean canceled = scheduleServiceRestartLocked(sr, true);
10384
10385 // Should the service remain running? Note that in the
10386 // extreme case of so many attempts to deliver a command
10387 // that it failed, that we also will stop it here.
10388 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10389 if (sr.pendingStarts.size() == 0) {
10390 sr.startRequested = false;
10391 if (!hasClients) {
10392 // Whoops, no reason to restart!
10393 bringDownServiceLocked(sr, true);
10394 }
10395 }
10396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010397 }
10398 }
10399
10400 if (!allowRestart) {
10401 app.services.clear();
10402 }
10403 }
10404
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010405 // Make sure we have no more records on the stopping list.
10406 int i = mStoppingServices.size();
10407 while (i > 0) {
10408 i--;
10409 ServiceRecord sr = mStoppingServices.get(i);
10410 if (sr.app == app) {
10411 mStoppingServices.remove(i);
10412 }
10413 }
10414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010415 app.executingServices.clear();
10416 }
10417
10418 private final void removeDyingProviderLocked(ProcessRecord proc,
10419 ContentProviderRecord cpr) {
10420 synchronized (cpr) {
10421 cpr.launchingApp = null;
10422 cpr.notifyAll();
10423 }
10424
10425 mProvidersByClass.remove(cpr.info.name);
10426 String names[] = cpr.info.authority.split(";");
10427 for (int j = 0; j < names.length; j++) {
10428 mProvidersByName.remove(names[j]);
10429 }
10430
10431 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10432 while (cit.hasNext()) {
10433 ProcessRecord capp = cit.next();
10434 if (!capp.persistent && capp.thread != null
10435 && capp.pid != 0
10436 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010437 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010438 + " (pid " + capp.pid
10439 + ") because provider " + cpr.info.name
10440 + " is in dying process " + proc.processName);
10441 Process.killProcess(capp.pid);
10442 }
10443 }
10444
10445 mLaunchingProviders.remove(cpr);
10446 }
10447
10448 /**
10449 * Main code for cleaning up a process when it has gone away. This is
10450 * called both as a result of the process dying, or directly when stopping
10451 * a process when running in single process mode.
10452 */
10453 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10454 boolean restarting, int index) {
10455 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010456 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010457 }
10458
Dianne Hackborn36124872009-10-08 16:22:03 -070010459 mProcessesToGc.remove(app);
10460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010461 // Dismiss any open dialogs.
10462 if (app.crashDialog != null) {
10463 app.crashDialog.dismiss();
10464 app.crashDialog = null;
10465 }
10466 if (app.anrDialog != null) {
10467 app.anrDialog.dismiss();
10468 app.anrDialog = null;
10469 }
10470 if (app.waitDialog != null) {
10471 app.waitDialog.dismiss();
10472 app.waitDialog = null;
10473 }
10474
10475 app.crashing = false;
10476 app.notResponding = false;
10477
10478 app.resetPackageList();
10479 app.thread = null;
10480 app.forcingToForeground = null;
10481 app.foregroundServices = false;
10482
10483 killServicesLocked(app, true);
10484
10485 boolean restart = false;
10486
10487 int NL = mLaunchingProviders.size();
10488
10489 // Remove published content providers.
10490 if (!app.pubProviders.isEmpty()) {
10491 Iterator it = app.pubProviders.values().iterator();
10492 while (it.hasNext()) {
10493 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10494 cpr.provider = null;
10495 cpr.app = null;
10496
10497 // See if someone is waiting for this provider... in which
10498 // case we don't remove it, but just let it restart.
10499 int i = 0;
10500 if (!app.bad) {
10501 for (; i<NL; i++) {
10502 if (mLaunchingProviders.get(i) == cpr) {
10503 restart = true;
10504 break;
10505 }
10506 }
10507 } else {
10508 i = NL;
10509 }
10510
10511 if (i >= NL) {
10512 removeDyingProviderLocked(app, cpr);
10513 NL = mLaunchingProviders.size();
10514 }
10515 }
10516 app.pubProviders.clear();
10517 }
10518
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010519 // Take care of any launching providers waiting for this process.
10520 if (checkAppInLaunchingProvidersLocked(app, false)) {
10521 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010522 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010524 // Unregister from connected content providers.
10525 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010526 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010527 while (it.hasNext()) {
10528 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10529 cpr.clients.remove(app);
10530 }
10531 app.conProviders.clear();
10532 }
10533
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010534 // At this point there may be remaining entries in mLaunchingProviders
10535 // where we were the only one waiting, so they are no longer of use.
10536 // Look for these and clean up if found.
10537 // XXX Commented out for now. Trying to figure out a way to reproduce
10538 // the actual situation to identify what is actually going on.
10539 if (false) {
10540 for (int i=0; i<NL; i++) {
10541 ContentProviderRecord cpr = (ContentProviderRecord)
10542 mLaunchingProviders.get(i);
10543 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10544 synchronized (cpr) {
10545 cpr.launchingApp = null;
10546 cpr.notifyAll();
10547 }
10548 }
10549 }
10550 }
10551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010552 skipCurrentReceiverLocked(app);
10553
10554 // Unregister any receivers.
10555 if (app.receivers.size() > 0) {
10556 Iterator<ReceiverList> it = app.receivers.iterator();
10557 while (it.hasNext()) {
10558 removeReceiverLocked(it.next());
10559 }
10560 app.receivers.clear();
10561 }
10562
Christopher Tate181fafa2009-05-14 11:12:14 -070010563 // If the app is undergoing backup, tell the backup manager about it
10564 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010565 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010566 try {
10567 IBackupManager bm = IBackupManager.Stub.asInterface(
10568 ServiceManager.getService(Context.BACKUP_SERVICE));
10569 bm.agentDisconnected(app.info.packageName);
10570 } catch (RemoteException e) {
10571 // can't happen; backup manager is local
10572 }
10573 }
10574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010575 // If the caller is restarting this app, then leave it in its
10576 // current lists and let the caller take care of it.
10577 if (restarting) {
10578 return;
10579 }
10580
10581 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010582 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 "Removing non-persistent process during cleanup: " + app);
10584 mProcessNames.remove(app.processName, app.info.uid);
10585 } else if (!app.removed) {
10586 // This app is persistent, so we need to keep its record around.
10587 // If it is not already on the pending app list, add it there
10588 // and start a new process for it.
10589 app.thread = null;
10590 app.forcingToForeground = null;
10591 app.foregroundServices = false;
10592 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10593 mPersistentStartingProcesses.add(app);
10594 restart = true;
10595 }
10596 }
10597 mProcessesOnHold.remove(app);
10598
The Android Open Source Project4df24232009-03-05 14:34:35 -080010599 if (app == mHomeProcess) {
10600 mHomeProcess = null;
10601 }
10602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010603 if (restart) {
10604 // We have components that still need to be running in the
10605 // process, so re-launch it.
10606 mProcessNames.put(app.processName, app.info.uid, app);
10607 startProcessLocked(app, "restart", app.processName);
10608 } else if (app.pid > 0 && app.pid != MY_PID) {
10609 // Goodbye!
10610 synchronized (mPidsSelfLocked) {
10611 mPidsSelfLocked.remove(app.pid);
10612 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10613 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010614 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 }
10616 }
10617
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010618 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10619 // Look through the content providers we are waiting to have launched,
10620 // and if any run in this process then either schedule a restart of
10621 // the process or kill the client waiting for it if this process has
10622 // gone bad.
10623 int NL = mLaunchingProviders.size();
10624 boolean restart = false;
10625 for (int i=0; i<NL; i++) {
10626 ContentProviderRecord cpr = (ContentProviderRecord)
10627 mLaunchingProviders.get(i);
10628 if (cpr.launchingApp == app) {
10629 if (!alwaysBad && !app.bad) {
10630 restart = true;
10631 } else {
10632 removeDyingProviderLocked(app, cpr);
10633 NL = mLaunchingProviders.size();
10634 }
10635 }
10636 }
10637 return restart;
10638 }
10639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 // =========================================================
10641 // SERVICES
10642 // =========================================================
10643
10644 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10645 ActivityManager.RunningServiceInfo info =
10646 new ActivityManager.RunningServiceInfo();
10647 info.service = r.name;
10648 if (r.app != null) {
10649 info.pid = r.app.pid;
10650 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010651 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 info.process = r.processName;
10653 info.foreground = r.isForeground;
10654 info.activeSince = r.createTime;
10655 info.started = r.startRequested;
10656 info.clientCount = r.connections.size();
10657 info.crashCount = r.crashCount;
10658 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010659 if (r.isForeground) {
10660 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10661 }
10662 if (r.startRequested) {
10663 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10664 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010665 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010666 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10667 }
10668 if (r.app != null && r.app.persistent) {
10669 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10670 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010671 for (ConnectionRecord conn : r.connections.values()) {
10672 if (conn.clientLabel != 0) {
10673 info.clientPackage = conn.binding.client.info.packageName;
10674 info.clientLabel = conn.clientLabel;
10675 break;
10676 }
10677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010678 return info;
10679 }
10680
10681 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10682 int flags) {
10683 synchronized (this) {
10684 ArrayList<ActivityManager.RunningServiceInfo> res
10685 = new ArrayList<ActivityManager.RunningServiceInfo>();
10686
10687 if (mServices.size() > 0) {
10688 Iterator<ServiceRecord> it = mServices.values().iterator();
10689 while (it.hasNext() && res.size() < maxNum) {
10690 res.add(makeRunningServiceInfoLocked(it.next()));
10691 }
10692 }
10693
10694 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10695 ServiceRecord r = mRestartingServices.get(i);
10696 ActivityManager.RunningServiceInfo info =
10697 makeRunningServiceInfoLocked(r);
10698 info.restarting = r.nextRestartTime;
10699 res.add(info);
10700 }
10701
10702 return res;
10703 }
10704 }
10705
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010706 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10707 synchronized (this) {
10708 ServiceRecord r = mServices.get(name);
10709 if (r != null) {
10710 for (ConnectionRecord conn : r.connections.values()) {
10711 if (conn.clientIntent != null) {
10712 return conn.clientIntent;
10713 }
10714 }
10715 }
10716 }
10717 return null;
10718 }
10719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010720 private final ServiceRecord findServiceLocked(ComponentName name,
10721 IBinder token) {
10722 ServiceRecord r = mServices.get(name);
10723 return r == token ? r : null;
10724 }
10725
10726 private final class ServiceLookupResult {
10727 final ServiceRecord record;
10728 final String permission;
10729
10730 ServiceLookupResult(ServiceRecord _record, String _permission) {
10731 record = _record;
10732 permission = _permission;
10733 }
10734 };
10735
10736 private ServiceLookupResult findServiceLocked(Intent service,
10737 String resolvedType) {
10738 ServiceRecord r = null;
10739 if (service.getComponent() != null) {
10740 r = mServices.get(service.getComponent());
10741 }
10742 if (r == null) {
10743 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10744 r = mServicesByIntent.get(filter);
10745 }
10746
10747 if (r == null) {
10748 try {
10749 ResolveInfo rInfo =
10750 ActivityThread.getPackageManager().resolveService(
10751 service, resolvedType, 0);
10752 ServiceInfo sInfo =
10753 rInfo != null ? rInfo.serviceInfo : null;
10754 if (sInfo == null) {
10755 return null;
10756 }
10757
10758 ComponentName name = new ComponentName(
10759 sInfo.applicationInfo.packageName, sInfo.name);
10760 r = mServices.get(name);
10761 } catch (RemoteException ex) {
10762 // pm is in same process, this will never happen.
10763 }
10764 }
10765 if (r != null) {
10766 int callingPid = Binder.getCallingPid();
10767 int callingUid = Binder.getCallingUid();
10768 if (checkComponentPermission(r.permission,
10769 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10770 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010771 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772 + " from pid=" + callingPid
10773 + ", uid=" + callingUid
10774 + " requires " + r.permission);
10775 return new ServiceLookupResult(null, r.permission);
10776 }
10777 return new ServiceLookupResult(r, null);
10778 }
10779 return null;
10780 }
10781
10782 private class ServiceRestarter implements Runnable {
10783 private ServiceRecord mService;
10784
10785 void setService(ServiceRecord service) {
10786 mService = service;
10787 }
10788
10789 public void run() {
10790 synchronized(ActivityManagerService.this) {
10791 performServiceRestartLocked(mService);
10792 }
10793 }
10794 }
10795
10796 private ServiceLookupResult retrieveServiceLocked(Intent service,
10797 String resolvedType, int callingPid, int callingUid) {
10798 ServiceRecord r = null;
10799 if (service.getComponent() != null) {
10800 r = mServices.get(service.getComponent());
10801 }
10802 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10803 r = mServicesByIntent.get(filter);
10804 if (r == null) {
10805 try {
10806 ResolveInfo rInfo =
10807 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010808 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010809 ServiceInfo sInfo =
10810 rInfo != null ? rInfo.serviceInfo : null;
10811 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010812 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010813 ": not found");
10814 return null;
10815 }
10816
10817 ComponentName name = new ComponentName(
10818 sInfo.applicationInfo.packageName, sInfo.name);
10819 r = mServices.get(name);
10820 if (r == null) {
10821 filter = new Intent.FilterComparison(service.cloneFilter());
10822 ServiceRestarter res = new ServiceRestarter();
10823 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10824 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10825 synchronized (stats) {
10826 ss = stats.getServiceStatsLocked(
10827 sInfo.applicationInfo.uid, sInfo.packageName,
10828 sInfo.name);
10829 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010830 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010831 res.setService(r);
10832 mServices.put(name, r);
10833 mServicesByIntent.put(filter, r);
10834
10835 // Make sure this component isn't in the pending list.
10836 int N = mPendingServices.size();
10837 for (int i=0; i<N; i++) {
10838 ServiceRecord pr = mPendingServices.get(i);
10839 if (pr.name.equals(name)) {
10840 mPendingServices.remove(i);
10841 i--;
10842 N--;
10843 }
10844 }
10845 }
10846 } catch (RemoteException ex) {
10847 // pm is in same process, this will never happen.
10848 }
10849 }
10850 if (r != null) {
10851 if (checkComponentPermission(r.permission,
10852 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10853 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010854 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010855 + " from pid=" + Binder.getCallingPid()
10856 + ", uid=" + Binder.getCallingUid()
10857 + " requires " + r.permission);
10858 return new ServiceLookupResult(null, r.permission);
10859 }
10860 return new ServiceLookupResult(r, null);
10861 }
10862 return null;
10863 }
10864
10865 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10866 long now = SystemClock.uptimeMillis();
10867 if (r.executeNesting == 0 && r.app != null) {
10868 if (r.app.executingServices.size() == 0) {
10869 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10870 msg.obj = r.app;
10871 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10872 }
10873 r.app.executingServices.add(r);
10874 }
10875 r.executeNesting++;
10876 r.executingStart = now;
10877 }
10878
10879 private final void sendServiceArgsLocked(ServiceRecord r,
10880 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010881 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882 if (N == 0) {
10883 return;
10884 }
10885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010886 int i = 0;
10887 while (i < N) {
10888 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010889 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010890 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010891 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010892 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010893 // If somehow we got a dummy start at the front, then
10894 // just drop it here.
10895 i++;
10896 continue;
10897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 bumpServiceExecutingLocked(r);
10899 if (!oomAdjusted) {
10900 oomAdjusted = true;
10901 updateOomAdjLocked(r.app);
10902 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010903 int flags = 0;
10904 if (si.deliveryCount > 0) {
10905 flags |= Service.START_FLAG_RETRY;
10906 }
10907 if (si.doneExecutingCount > 0) {
10908 flags |= Service.START_FLAG_REDELIVERY;
10909 }
10910 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10911 si.deliveredTime = SystemClock.uptimeMillis();
10912 r.deliveredStarts.add(si);
10913 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010914 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010915 } catch (RemoteException e) {
10916 // Remote process gone... we'll let the normal cleanup take
10917 // care of this.
10918 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010919 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010920 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 break;
10922 }
10923 }
10924 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010925 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010926 } else {
10927 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010928 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010929 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010930 }
10931 }
10932 }
10933
10934 private final boolean requestServiceBindingLocked(ServiceRecord r,
10935 IntentBindRecord i, boolean rebind) {
10936 if (r.app == null || r.app.thread == null) {
10937 // If service is not currently running, can't yet bind.
10938 return false;
10939 }
10940 if ((!i.requested || rebind) && i.apps.size() > 0) {
10941 try {
10942 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010943 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010944 + ": shouldUnbind=" + i.hasBound);
10945 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10946 if (!rebind) {
10947 i.requested = true;
10948 }
10949 i.hasBound = true;
10950 i.doRebind = false;
10951 } catch (RemoteException e) {
10952 return false;
10953 }
10954 }
10955 return true;
10956 }
10957
10958 private final void requestServiceBindingsLocked(ServiceRecord r) {
10959 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10960 while (bindings.hasNext()) {
10961 IntentBindRecord i = bindings.next();
10962 if (!requestServiceBindingLocked(r, i, false)) {
10963 break;
10964 }
10965 }
10966 }
10967
10968 private final void realStartServiceLocked(ServiceRecord r,
10969 ProcessRecord app) throws RemoteException {
10970 if (app.thread == null) {
10971 throw new RemoteException();
10972 }
10973
10974 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010975 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010976
10977 app.services.add(r);
10978 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010979 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980
10981 boolean created = false;
10982 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010983 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010984 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010985 mStringBuilder.setLength(0);
10986 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010987 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010988 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010989 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010990 synchronized (r.stats.getBatteryStats()) {
10991 r.stats.startLaunchedLocked();
10992 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010993 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010994 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010995 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 created = true;
10997 } finally {
10998 if (!created) {
10999 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011000 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 }
11002 }
11003
11004 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011005
11006 // If the service is in the started state, and there are no
11007 // pending arguments, then fake up one so its onStartCommand() will
11008 // be called.
11009 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11010 r.lastStartId++;
11011 if (r.lastStartId < 1) {
11012 r.lastStartId = 1;
11013 }
11014 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11015 }
11016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017 sendServiceArgsLocked(r, true);
11018 }
11019
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011020 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11021 boolean allowCancel) {
11022 boolean canceled = false;
11023
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011024 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011025 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011026 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011027
11028 // Any delivered but not yet finished starts should be put back
11029 // on the pending list.
11030 final int N = r.deliveredStarts.size();
11031 if (N > 0) {
11032 for (int i=N-1; i>=0; i--) {
11033 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11034 if (si.intent == null) {
11035 // We'll generate this again if needed.
11036 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11037 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11038 r.pendingStarts.add(0, si);
11039 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11040 dur *= 2;
11041 if (minDuration < dur) minDuration = dur;
11042 if (resetTime < dur) resetTime = dur;
11043 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011044 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011045 + r.name);
11046 canceled = true;
11047 }
11048 }
11049 r.deliveredStarts.clear();
11050 }
11051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 r.totalRestartCount++;
11053 if (r.restartDelay == 0) {
11054 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011055 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 } else {
11057 // If it has been a "reasonably long time" since the service
11058 // was started, then reset our restart duration back to
11059 // the beginning, so we don't infinitely increase the duration
11060 // on a service that just occasionally gets killed (which is
11061 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011062 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011063 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011064 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011066 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011067 if (r.restartDelay < minDuration) {
11068 r.restartDelay = minDuration;
11069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 }
11071 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011072
11073 r.nextRestartTime = now + r.restartDelay;
11074
11075 // Make sure that we don't end up restarting a bunch of services
11076 // all at the same time.
11077 boolean repeat;
11078 do {
11079 repeat = false;
11080 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11081 ServiceRecord r2 = mRestartingServices.get(i);
11082 if (r2 != r && r.nextRestartTime
11083 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11084 && r.nextRestartTime
11085 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11086 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11087 r.restartDelay = r.nextRestartTime - now;
11088 repeat = true;
11089 break;
11090 }
11091 }
11092 } while (repeat);
11093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011094 if (!mRestartingServices.contains(r)) {
11095 mRestartingServices.add(r);
11096 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011097
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011098 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011100 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011101 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011102 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011103 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011105 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 r.shortName, r.restartDelay);
11107
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011108 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 }
11110
11111 final void performServiceRestartLocked(ServiceRecord r) {
11112 if (!mRestartingServices.contains(r)) {
11113 return;
11114 }
11115 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11116 }
11117
11118 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11119 if (r.restartDelay == 0) {
11120 return false;
11121 }
11122 r.resetRestartCounter();
11123 mRestartingServices.remove(r);
11124 mHandler.removeCallbacks(r.restarter);
11125 return true;
11126 }
11127
11128 private final boolean bringUpServiceLocked(ServiceRecord r,
11129 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011130 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011131 //r.dump(" ");
11132
Dianne Hackborn36124872009-10-08 16:22:03 -070011133 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011134 sendServiceArgsLocked(r, false);
11135 return true;
11136 }
11137
11138 if (!whileRestarting && r.restartDelay > 0) {
11139 // If waiting for a restart, then do nothing.
11140 return true;
11141 }
11142
Joe Onorato8a9b2202010-02-26 18:56:32 -080011143 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011144 + " " + r.intent);
11145
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011146 // We are now bringing the service up, so no longer in the
11147 // restarting state.
11148 mRestartingServices.remove(r);
11149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011150 final String appName = r.processName;
11151 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11152 if (app != null && app.thread != null) {
11153 try {
11154 realStartServiceLocked(r, app);
11155 return true;
11156 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011157 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011158 }
11159
11160 // If a dead object exception was thrown -- fall through to
11161 // restart the application.
11162 }
11163
Dianne Hackborn36124872009-10-08 16:22:03 -070011164 // Not running -- get it started, and enqueue this service record
11165 // to be executed when the app comes up.
11166 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11167 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011168 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011169 + r.appInfo.packageName + "/"
11170 + r.appInfo.uid + " for service "
11171 + r.intent.getIntent() + ": process is bad");
11172 bringDownServiceLocked(r, true);
11173 return false;
11174 }
11175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011176 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011177 mPendingServices.add(r);
11178 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011180 return true;
11181 }
11182
11183 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011184 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 //r.dump(" ");
11186
11187 // Does it still need to run?
11188 if (!force && r.startRequested) {
11189 return;
11190 }
11191 if (r.connections.size() > 0) {
11192 if (!force) {
11193 // XXX should probably keep a count of the number of auto-create
11194 // connections directly in the service.
11195 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11196 while (it.hasNext()) {
11197 ConnectionRecord cr = it.next();
11198 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11199 return;
11200 }
11201 }
11202 }
11203
11204 // Report to all of the connections that the service is no longer
11205 // available.
11206 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11207 while (it.hasNext()) {
11208 ConnectionRecord c = it.next();
11209 try {
11210 // todo: shouldn't be a synchronous call!
11211 c.conn.connected(r.name, null);
11212 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011213 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 " to connection " + c.conn.asBinder() +
11215 " (in " + c.binding.client.processName + ")", e);
11216 }
11217 }
11218 }
11219
11220 // Tell the service that it has been unbound.
11221 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11222 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11223 while (it.hasNext()) {
11224 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011225 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011226 + ": hasBound=" + ibr.hasBound);
11227 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11228 try {
11229 bumpServiceExecutingLocked(r);
11230 updateOomAdjLocked(r.app);
11231 ibr.hasBound = false;
11232 r.app.thread.scheduleUnbindService(r,
11233 ibr.intent.getIntent());
11234 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011235 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011236 + r.shortName, e);
11237 serviceDoneExecutingLocked(r, true);
11238 }
11239 }
11240 }
11241 }
11242
Joe Onorato8a9b2202010-02-26 18:56:32 -080011243 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011244 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011245 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011246 System.identityHashCode(r), r.shortName,
11247 (r.app != null) ? r.app.pid : -1);
11248
11249 mServices.remove(r.name);
11250 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011251 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011252 r.totalRestartCount = 0;
11253 unscheduleServiceRestartLocked(r);
11254
11255 // Also make sure it is not on the pending list.
11256 int N = mPendingServices.size();
11257 for (int i=0; i<N; i++) {
11258 if (mPendingServices.get(i) == r) {
11259 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011260 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011261 TAG, "Removed pending service: " + r.shortName);
11262 i--;
11263 N--;
11264 }
11265 }
11266
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011267 r.cancelNotification();
11268 r.isForeground = false;
11269 r.foregroundId = 0;
11270 r.foregroundNoti = null;
11271
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011272 // Clear start entries.
11273 r.deliveredStarts.clear();
11274 r.pendingStarts.clear();
11275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011276 if (r.app != null) {
11277 synchronized (r.stats.getBatteryStats()) {
11278 r.stats.stopLaunchedLocked();
11279 }
11280 r.app.services.remove(r);
11281 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011283 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011284 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 bumpServiceExecutingLocked(r);
11286 mStoppingServices.add(r);
11287 updateOomAdjLocked(r.app);
11288 r.app.thread.scheduleStopService(r);
11289 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011290 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 + r.shortName, e);
11292 serviceDoneExecutingLocked(r, true);
11293 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011294 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011296 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011297 TAG, "Removed service that has no process: " + r.shortName);
11298 }
11299 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011300 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011301 TAG, "Removed service that is not running: " + r.shortName);
11302 }
11303 }
11304
11305 ComponentName startServiceLocked(IApplicationThread caller,
11306 Intent service, String resolvedType,
11307 int callingPid, int callingUid) {
11308 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011309 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011310 + " type=" + resolvedType + " args=" + service.getExtras());
11311
11312 if (caller != null) {
11313 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11314 if (callerApp == null) {
11315 throw new SecurityException(
11316 "Unable to find app for caller " + caller
11317 + " (pid=" + Binder.getCallingPid()
11318 + ") when starting service " + service);
11319 }
11320 }
11321
11322 ServiceLookupResult res =
11323 retrieveServiceLocked(service, resolvedType,
11324 callingPid, callingUid);
11325 if (res == null) {
11326 return null;
11327 }
11328 if (res.record == null) {
11329 return new ComponentName("!", res.permission != null
11330 ? res.permission : "private to package");
11331 }
11332 ServiceRecord r = res.record;
11333 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011334 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011335 + r.shortName);
11336 }
11337 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011338 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 r.lastStartId++;
11340 if (r.lastStartId < 1) {
11341 r.lastStartId = 1;
11342 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011343 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011344 r.lastActivity = SystemClock.uptimeMillis();
11345 synchronized (r.stats.getBatteryStats()) {
11346 r.stats.startRunningLocked();
11347 }
11348 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11349 return new ComponentName("!", "Service process is bad");
11350 }
11351 return r.name;
11352 }
11353 }
11354
11355 public ComponentName startService(IApplicationThread caller, Intent service,
11356 String resolvedType) {
11357 // Refuse possible leaked file descriptors
11358 if (service != null && service.hasFileDescriptors() == true) {
11359 throw new IllegalArgumentException("File descriptors passed in Intent");
11360 }
11361
11362 synchronized(this) {
11363 final int callingPid = Binder.getCallingPid();
11364 final int callingUid = Binder.getCallingUid();
11365 final long origId = Binder.clearCallingIdentity();
11366 ComponentName res = startServiceLocked(caller, service,
11367 resolvedType, callingPid, callingUid);
11368 Binder.restoreCallingIdentity(origId);
11369 return res;
11370 }
11371 }
11372
11373 ComponentName startServiceInPackage(int uid,
11374 Intent service, String resolvedType) {
11375 synchronized(this) {
11376 final long origId = Binder.clearCallingIdentity();
11377 ComponentName res = startServiceLocked(null, service,
11378 resolvedType, -1, uid);
11379 Binder.restoreCallingIdentity(origId);
11380 return res;
11381 }
11382 }
11383
11384 public int stopService(IApplicationThread caller, Intent service,
11385 String resolvedType) {
11386 // Refuse possible leaked file descriptors
11387 if (service != null && service.hasFileDescriptors() == true) {
11388 throw new IllegalArgumentException("File descriptors passed in Intent");
11389 }
11390
11391 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011392 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011393 + " type=" + resolvedType);
11394
11395 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11396 if (caller != null && callerApp == null) {
11397 throw new SecurityException(
11398 "Unable to find app for caller " + caller
11399 + " (pid=" + Binder.getCallingPid()
11400 + ") when stopping service " + service);
11401 }
11402
11403 // If this service is active, make sure it is stopped.
11404 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11405 if (r != null) {
11406 if (r.record != null) {
11407 synchronized (r.record.stats.getBatteryStats()) {
11408 r.record.stats.stopRunningLocked();
11409 }
11410 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011411 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011412 final long origId = Binder.clearCallingIdentity();
11413 bringDownServiceLocked(r.record, false);
11414 Binder.restoreCallingIdentity(origId);
11415 return 1;
11416 }
11417 return -1;
11418 }
11419 }
11420
11421 return 0;
11422 }
11423
11424 public IBinder peekService(Intent service, String resolvedType) {
11425 // Refuse possible leaked file descriptors
11426 if (service != null && service.hasFileDescriptors() == true) {
11427 throw new IllegalArgumentException("File descriptors passed in Intent");
11428 }
11429
11430 IBinder ret = null;
11431
11432 synchronized(this) {
11433 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11434
11435 if (r != null) {
11436 // r.record is null if findServiceLocked() failed the caller permission check
11437 if (r.record == null) {
11438 throw new SecurityException(
11439 "Permission Denial: Accessing service " + r.record.name
11440 + " from pid=" + Binder.getCallingPid()
11441 + ", uid=" + Binder.getCallingUid()
11442 + " requires " + r.permission);
11443 }
11444 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11445 if (ib != null) {
11446 ret = ib.binder;
11447 }
11448 }
11449 }
11450
11451 return ret;
11452 }
11453
11454 public boolean stopServiceToken(ComponentName className, IBinder token,
11455 int startId) {
11456 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011457 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011458 + " " + token + " startId=" + startId);
11459 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011460 if (r != null) {
11461 if (startId >= 0) {
11462 // Asked to only stop if done with all work. Note that
11463 // to avoid leaks, we will take this as dropping all
11464 // start items up to and including this one.
11465 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11466 if (si != null) {
11467 while (r.deliveredStarts.size() > 0) {
11468 if (r.deliveredStarts.remove(0) == si) {
11469 break;
11470 }
11471 }
11472 }
11473
11474 if (r.lastStartId != startId) {
11475 return false;
11476 }
11477
11478 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011479 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011480 + " is last, but have " + r.deliveredStarts.size()
11481 + " remaining args");
11482 }
11483 }
11484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 synchronized (r.stats.getBatteryStats()) {
11486 r.stats.stopRunningLocked();
11487 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011488 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011489 }
11490 final long origId = Binder.clearCallingIdentity();
11491 bringDownServiceLocked(r, false);
11492 Binder.restoreCallingIdentity(origId);
11493 return true;
11494 }
11495 }
11496 return false;
11497 }
11498
11499 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011500 int id, Notification notification, boolean removeNotification) {
11501 final long origId = Binder.clearCallingIdentity();
11502 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 synchronized(this) {
11504 ServiceRecord r = findServiceLocked(className, token);
11505 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011506 if (id != 0) {
11507 if (notification == null) {
11508 throw new IllegalArgumentException("null notification");
11509 }
11510 if (r.foregroundId != id) {
11511 r.cancelNotification();
11512 r.foregroundId = id;
11513 }
11514 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11515 r.foregroundNoti = notification;
11516 r.isForeground = true;
11517 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518 if (r.app != null) {
11519 updateServiceForegroundLocked(r.app, true);
11520 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011521 } else {
11522 if (r.isForeground) {
11523 r.isForeground = false;
11524 if (r.app != null) {
11525 updateServiceForegroundLocked(r.app, true);
11526 }
11527 }
11528 if (removeNotification) {
11529 r.cancelNotification();
11530 r.foregroundId = 0;
11531 r.foregroundNoti = null;
11532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011533 }
11534 }
11535 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011536 } finally {
11537 Binder.restoreCallingIdentity(origId);
11538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011539 }
11540
11541 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11542 boolean anyForeground = false;
11543 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11544 if (sr.isForeground) {
11545 anyForeground = true;
11546 break;
11547 }
11548 }
11549 if (anyForeground != proc.foregroundServices) {
11550 proc.foregroundServices = anyForeground;
11551 if (oomAdj) {
11552 updateOomAdjLocked();
11553 }
11554 }
11555 }
11556
11557 public int bindService(IApplicationThread caller, IBinder token,
11558 Intent service, String resolvedType,
11559 IServiceConnection connection, int flags) {
11560 // Refuse possible leaked file descriptors
11561 if (service != null && service.hasFileDescriptors() == true) {
11562 throw new IllegalArgumentException("File descriptors passed in Intent");
11563 }
11564
11565 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011566 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011567 + " type=" + resolvedType + " conn=" + connection.asBinder()
11568 + " flags=0x" + Integer.toHexString(flags));
11569 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11570 if (callerApp == null) {
11571 throw new SecurityException(
11572 "Unable to find app for caller " + caller
11573 + " (pid=" + Binder.getCallingPid()
11574 + ") when binding service " + service);
11575 }
11576
11577 HistoryRecord activity = null;
11578 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011579 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011580 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011581 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011582 return 0;
11583 }
11584 activity = (HistoryRecord)mHistory.get(aindex);
11585 }
11586
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011587 int clientLabel = 0;
11588 PendingIntent clientIntent = null;
11589
11590 if (callerApp.info.uid == Process.SYSTEM_UID) {
11591 // Hacky kind of thing -- allow system stuff to tell us
11592 // what they are, so we can report this elsewhere for
11593 // others to know why certain services are running.
11594 try {
11595 clientIntent = (PendingIntent)service.getParcelableExtra(
11596 Intent.EXTRA_CLIENT_INTENT);
11597 } catch (RuntimeException e) {
11598 }
11599 if (clientIntent != null) {
11600 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11601 if (clientLabel != 0) {
11602 // There are no useful extras in the intent, trash them.
11603 // System code calling with this stuff just needs to know
11604 // this will happen.
11605 service = service.cloneFilter();
11606 }
11607 }
11608 }
11609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011610 ServiceLookupResult res =
11611 retrieveServiceLocked(service, resolvedType,
11612 Binder.getCallingPid(), Binder.getCallingUid());
11613 if (res == null) {
11614 return 0;
11615 }
11616 if (res.record == null) {
11617 return -1;
11618 }
11619 ServiceRecord s = res.record;
11620
11621 final long origId = Binder.clearCallingIdentity();
11622
11623 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011624 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011625 + s.shortName);
11626 }
11627
11628 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11629 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011630 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011631
11632 IBinder binder = connection.asBinder();
11633 s.connections.put(binder, c);
11634 b.connections.add(c);
11635 if (activity != null) {
11636 if (activity.connections == null) {
11637 activity.connections = new HashSet<ConnectionRecord>();
11638 }
11639 activity.connections.add(c);
11640 }
11641 b.client.connections.add(c);
11642 mServiceConnections.put(binder, c);
11643
11644 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11645 s.lastActivity = SystemClock.uptimeMillis();
11646 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11647 return 0;
11648 }
11649 }
11650
11651 if (s.app != null) {
11652 // This could have made the service more important.
11653 updateOomAdjLocked(s.app);
11654 }
11655
Joe Onorato8a9b2202010-02-26 18:56:32 -080011656 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011657 + ": received=" + b.intent.received
11658 + " apps=" + b.intent.apps.size()
11659 + " doRebind=" + b.intent.doRebind);
11660
11661 if (s.app != null && b.intent.received) {
11662 // Service is already running, so we can immediately
11663 // publish the connection.
11664 try {
11665 c.conn.connected(s.name, b.intent.binder);
11666 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011667 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011668 + " to connection " + c.conn.asBinder()
11669 + " (in " + c.binding.client.processName + ")", e);
11670 }
11671
11672 // If this is the first app connected back to this binding,
11673 // and the service had previously asked to be told when
11674 // rebound, then do so.
11675 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11676 requestServiceBindingLocked(s, b.intent, true);
11677 }
11678 } else if (!b.intent.requested) {
11679 requestServiceBindingLocked(s, b.intent, false);
11680 }
11681
11682 Binder.restoreCallingIdentity(origId);
11683 }
11684
11685 return 1;
11686 }
11687
11688 private void removeConnectionLocked(
11689 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11690 IBinder binder = c.conn.asBinder();
11691 AppBindRecord b = c.binding;
11692 ServiceRecord s = b.service;
11693 s.connections.remove(binder);
11694 b.connections.remove(c);
11695 if (c.activity != null && c.activity != skipAct) {
11696 if (c.activity.connections != null) {
11697 c.activity.connections.remove(c);
11698 }
11699 }
11700 if (b.client != skipApp) {
11701 b.client.connections.remove(c);
11702 }
11703 mServiceConnections.remove(binder);
11704
11705 if (b.connections.size() == 0) {
11706 b.intent.apps.remove(b.client);
11707 }
11708
Joe Onorato8a9b2202010-02-26 18:56:32 -080011709 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011710 + ": shouldUnbind=" + b.intent.hasBound);
11711 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11712 && b.intent.hasBound) {
11713 try {
11714 bumpServiceExecutingLocked(s);
11715 updateOomAdjLocked(s.app);
11716 b.intent.hasBound = false;
11717 // Assume the client doesn't want to know about a rebind;
11718 // we will deal with that later if it asks for one.
11719 b.intent.doRebind = false;
11720 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11721 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011722 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011723 serviceDoneExecutingLocked(s, true);
11724 }
11725 }
11726
11727 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11728 bringDownServiceLocked(s, false);
11729 }
11730 }
11731
11732 public boolean unbindService(IServiceConnection connection) {
11733 synchronized (this) {
11734 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011735 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011736 ConnectionRecord r = mServiceConnections.get(binder);
11737 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011738 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011739 + connection.asBinder());
11740 return false;
11741 }
11742
11743 final long origId = Binder.clearCallingIdentity();
11744
11745 removeConnectionLocked(r, null, null);
11746
11747 if (r.binding.service.app != null) {
11748 // This could have made the service less important.
11749 updateOomAdjLocked(r.binding.service.app);
11750 }
11751
11752 Binder.restoreCallingIdentity(origId);
11753 }
11754
11755 return true;
11756 }
11757
11758 public void publishService(IBinder token, Intent intent, IBinder service) {
11759 // Refuse possible leaked file descriptors
11760 if (intent != null && intent.hasFileDescriptors() == true) {
11761 throw new IllegalArgumentException("File descriptors passed in Intent");
11762 }
11763
11764 synchronized(this) {
11765 if (!(token instanceof ServiceRecord)) {
11766 throw new IllegalArgumentException("Invalid service token");
11767 }
11768 ServiceRecord r = (ServiceRecord)token;
11769
11770 final long origId = Binder.clearCallingIdentity();
11771
Joe Onorato8a9b2202010-02-26 18:56:32 -080011772 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011773 + " " + intent + ": " + service);
11774 if (r != null) {
11775 Intent.FilterComparison filter
11776 = new Intent.FilterComparison(intent);
11777 IntentBindRecord b = r.bindings.get(filter);
11778 if (b != null && !b.received) {
11779 b.binder = service;
11780 b.requested = true;
11781 b.received = true;
11782 if (r.connections.size() > 0) {
11783 Iterator<ConnectionRecord> it
11784 = r.connections.values().iterator();
11785 while (it.hasNext()) {
11786 ConnectionRecord c = it.next();
11787 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011788 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011789 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011790 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011791 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011792 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011793 TAG, "Published intent: " + intent);
11794 continue;
11795 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011796 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 try {
11798 c.conn.connected(r.name, service);
11799 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011800 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011801 " to connection " + c.conn.asBinder() +
11802 " (in " + c.binding.client.processName + ")", e);
11803 }
11804 }
11805 }
11806 }
11807
11808 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11809
11810 Binder.restoreCallingIdentity(origId);
11811 }
11812 }
11813 }
11814
11815 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11816 // Refuse possible leaked file descriptors
11817 if (intent != null && intent.hasFileDescriptors() == true) {
11818 throw new IllegalArgumentException("File descriptors passed in Intent");
11819 }
11820
11821 synchronized(this) {
11822 if (!(token instanceof ServiceRecord)) {
11823 throw new IllegalArgumentException("Invalid service token");
11824 }
11825 ServiceRecord r = (ServiceRecord)token;
11826
11827 final long origId = Binder.clearCallingIdentity();
11828
11829 if (r != null) {
11830 Intent.FilterComparison filter
11831 = new Intent.FilterComparison(intent);
11832 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011833 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011834 + " at " + b + ": apps="
11835 + (b != null ? b.apps.size() : 0));
11836 if (b != null) {
11837 if (b.apps.size() > 0) {
11838 // Applications have already bound since the last
11839 // unbind, so just rebind right here.
11840 requestServiceBindingLocked(r, b, true);
11841 } else {
11842 // Note to tell the service the next time there is
11843 // a new client.
11844 b.doRebind = true;
11845 }
11846 }
11847
11848 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11849
11850 Binder.restoreCallingIdentity(origId);
11851 }
11852 }
11853 }
11854
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011855 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856 synchronized(this) {
11857 if (!(token instanceof ServiceRecord)) {
11858 throw new IllegalArgumentException("Invalid service token");
11859 }
11860 ServiceRecord r = (ServiceRecord)token;
11861 boolean inStopping = mStoppingServices.contains(token);
11862 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011863 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011864 + ": nesting=" + r.executeNesting
11865 + ", inStopping=" + inStopping);
11866 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011867 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011868 + " with incorrect token: given " + token
11869 + ", expected " + r);
11870 return;
11871 }
11872
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011873 if (type == 1) {
11874 // This is a call from a service start... take care of
11875 // book-keeping.
11876 r.callStart = true;
11877 switch (res) {
11878 case Service.START_STICKY_COMPATIBILITY:
11879 case Service.START_STICKY: {
11880 // We are done with the associated start arguments.
11881 r.findDeliveredStart(startId, true);
11882 // Don't stop if killed.
11883 r.stopIfKilled = false;
11884 break;
11885 }
11886 case Service.START_NOT_STICKY: {
11887 // We are done with the associated start arguments.
11888 r.findDeliveredStart(startId, true);
11889 if (r.lastStartId == startId) {
11890 // There is no more work, and this service
11891 // doesn't want to hang around if killed.
11892 r.stopIfKilled = true;
11893 }
11894 break;
11895 }
11896 case Service.START_REDELIVER_INTENT: {
11897 // We'll keep this item until they explicitly
11898 // call stop for it, but keep track of the fact
11899 // that it was delivered.
11900 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11901 if (si != null) {
11902 si.deliveryCount = 0;
11903 si.doneExecutingCount++;
11904 // Don't stop if killed.
11905 r.stopIfKilled = true;
11906 }
11907 break;
11908 }
11909 default:
11910 throw new IllegalArgumentException(
11911 "Unknown service start result: " + res);
11912 }
11913 if (res == Service.START_STICKY_COMPATIBILITY) {
11914 r.callStart = false;
11915 }
11916 }
11917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011918 final long origId = Binder.clearCallingIdentity();
11919 serviceDoneExecutingLocked(r, inStopping);
11920 Binder.restoreCallingIdentity(origId);
11921 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011922 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011923 + " with token " + token);
11924 }
11925 }
11926 }
11927
11928 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11929 r.executeNesting--;
11930 if (r.executeNesting <= 0 && r.app != null) {
11931 r.app.executingServices.remove(r);
11932 if (r.app.executingServices.size() == 0) {
11933 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11934 }
11935 if (inStopping) {
11936 mStoppingServices.remove(r);
11937 }
11938 updateOomAdjLocked(r.app);
11939 }
11940 }
11941
11942 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011943 String anrMessage = null;
11944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011945 synchronized(this) {
11946 if (proc.executingServices.size() == 0 || proc.thread == null) {
11947 return;
11948 }
11949 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11950 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11951 ServiceRecord timeout = null;
11952 long nextTime = 0;
11953 while (it.hasNext()) {
11954 ServiceRecord sr = it.next();
11955 if (sr.executingStart < maxTime) {
11956 timeout = sr;
11957 break;
11958 }
11959 if (sr.executingStart > nextTime) {
11960 nextTime = sr.executingStart;
11961 }
11962 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011963 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011964 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011965 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011966 } else {
11967 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11968 msg.obj = proc;
11969 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11970 }
11971 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011972
11973 if (anrMessage != null) {
11974 appNotResponding(proc, null, null, anrMessage);
11975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011976 }
11977
11978 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011979 // BACKUP AND RESTORE
11980 // =========================================================
11981
11982 // Cause the target app to be launched if necessary and its backup agent
11983 // instantiated. The backup agent will invoke backupAgentCreated() on the
11984 // activity manager to announce its creation.
11985 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011986 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011987 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11988
11989 synchronized(this) {
11990 // !!! TODO: currently no check here that we're already bound
11991 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11992 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11993 synchronized (stats) {
11994 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11995 }
11996
11997 BackupRecord r = new BackupRecord(ss, app, backupMode);
11998 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11999 // startProcessLocked() returns existing proc's record if it's already running
12000 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012001 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012002 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012003 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012004 return false;
12005 }
12006
12007 r.app = proc;
12008 mBackupTarget = r;
12009 mBackupAppName = app.packageName;
12010
Christopher Tate6fa95972009-06-05 18:43:55 -070012011 // Try not to kill the process during backup
12012 updateOomAdjLocked(proc);
12013
Christopher Tate181fafa2009-05-14 11:12:14 -070012014 // If the process is already attached, schedule the creation of the backup agent now.
12015 // If it is not yet live, this will be done when it attaches to the framework.
12016 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012017 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012018 try {
12019 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12020 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012021 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012022 }
12023 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012024 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012025 }
12026 // Invariants: at this point, the target app process exists and the application
12027 // is either already running or in the process of coming up. mBackupTarget and
12028 // mBackupAppName describe the app, so that when it binds back to the AM we
12029 // know that it's scheduled for a backup-agent operation.
12030 }
12031
12032 return true;
12033 }
12034
12035 // A backup agent has just come up
12036 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012037 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012038 + " = " + agent);
12039
12040 synchronized(this) {
12041 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012042 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012043 return;
12044 }
12045
Christopher Tate043dadc2009-06-02 16:11:00 -070012046 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012047 try {
12048 IBackupManager bm = IBackupManager.Stub.asInterface(
12049 ServiceManager.getService(Context.BACKUP_SERVICE));
12050 bm.agentConnected(agentPackageName, agent);
12051 } catch (RemoteException e) {
12052 // can't happen; the backup manager service is local
12053 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012054 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012055 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012056 } finally {
12057 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012058 }
12059 }
12060 }
12061
12062 // done with this agent
12063 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012064 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012065 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012066 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012067 return;
12068 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012069
12070 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012071 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012072 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012073 return;
12074 }
12075
Christopher Tate181fafa2009-05-14 11:12:14 -070012076 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012077 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012078 return;
12079 }
12080
Christopher Tate6fa95972009-06-05 18:43:55 -070012081 ProcessRecord proc = mBackupTarget.app;
12082 mBackupTarget = null;
12083 mBackupAppName = null;
12084
12085 // Not backing this app up any more; reset its OOM adjustment
12086 updateOomAdjLocked(proc);
12087
Christopher Tatec7b31e32009-06-10 15:49:30 -070012088 // If the app crashed during backup, 'thread' will be null here
12089 if (proc.thread != null) {
12090 try {
12091 proc.thread.scheduleDestroyBackupAgent(appInfo);
12092 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012093 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012094 e.printStackTrace();
12095 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012096 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012097 }
12098 }
12099 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012100 // BROADCASTS
12101 // =========================================================
12102
Josh Bartel7f208742010-02-25 11:01:44 -060012103 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012104 List cur) {
12105 final ContentResolver resolver = mContext.getContentResolver();
12106 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12107 if (list == null) {
12108 return cur;
12109 }
12110 int N = list.size();
12111 for (int i=0; i<N; i++) {
12112 Intent intent = list.get(i);
12113 if (filter.match(resolver, intent, true, TAG) >= 0) {
12114 if (cur == null) {
12115 cur = new ArrayList<Intent>();
12116 }
12117 cur.add(intent);
12118 }
12119 }
12120 return cur;
12121 }
12122
12123 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012124 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012125 + mBroadcastsScheduled);
12126
12127 if (mBroadcastsScheduled) {
12128 return;
12129 }
12130 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12131 mBroadcastsScheduled = true;
12132 }
12133
12134 public Intent registerReceiver(IApplicationThread caller,
12135 IIntentReceiver receiver, IntentFilter filter, String permission) {
12136 synchronized(this) {
12137 ProcessRecord callerApp = null;
12138 if (caller != null) {
12139 callerApp = getRecordForAppLocked(caller);
12140 if (callerApp == null) {
12141 throw new SecurityException(
12142 "Unable to find app for caller " + caller
12143 + " (pid=" + Binder.getCallingPid()
12144 + ") when registering receiver " + receiver);
12145 }
12146 }
12147
12148 List allSticky = null;
12149
12150 // Look for any matching sticky broadcasts...
12151 Iterator actions = filter.actionsIterator();
12152 if (actions != null) {
12153 while (actions.hasNext()) {
12154 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012155 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012156 }
12157 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012158 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012159 }
12160
12161 // The first sticky in the list is returned directly back to
12162 // the client.
12163 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12164
Joe Onorato8a9b2202010-02-26 18:56:32 -080012165 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012166 + ": " + sticky);
12167
12168 if (receiver == null) {
12169 return sticky;
12170 }
12171
12172 ReceiverList rl
12173 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12174 if (rl == null) {
12175 rl = new ReceiverList(this, callerApp,
12176 Binder.getCallingPid(),
12177 Binder.getCallingUid(), receiver);
12178 if (rl.app != null) {
12179 rl.app.receivers.add(rl);
12180 } else {
12181 try {
12182 receiver.asBinder().linkToDeath(rl, 0);
12183 } catch (RemoteException e) {
12184 return sticky;
12185 }
12186 rl.linkedToDeath = true;
12187 }
12188 mRegisteredReceivers.put(receiver.asBinder(), rl);
12189 }
12190 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12191 rl.add(bf);
12192 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012193 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012194 }
12195 mReceiverResolver.addFilter(bf);
12196
12197 // Enqueue broadcasts for all existing stickies that match
12198 // this filter.
12199 if (allSticky != null) {
12200 ArrayList receivers = new ArrayList();
12201 receivers.add(bf);
12202
12203 int N = allSticky.size();
12204 for (int i=0; i<N; i++) {
12205 Intent intent = (Intent)allSticky.get(i);
12206 BroadcastRecord r = new BroadcastRecord(intent, null,
12207 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012208 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012209 if (mParallelBroadcasts.size() == 0) {
12210 scheduleBroadcastsLocked();
12211 }
12212 mParallelBroadcasts.add(r);
12213 }
12214 }
12215
12216 return sticky;
12217 }
12218 }
12219
12220 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012221 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012222
12223 boolean doNext = false;
12224
12225 synchronized(this) {
12226 ReceiverList rl
12227 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12228 if (rl != null) {
12229 if (rl.curBroadcast != null) {
12230 BroadcastRecord r = rl.curBroadcast;
12231 doNext = finishReceiverLocked(
12232 receiver.asBinder(), r.resultCode, r.resultData,
12233 r.resultExtras, r.resultAbort, true);
12234 }
12235
12236 if (rl.app != null) {
12237 rl.app.receivers.remove(rl);
12238 }
12239 removeReceiverLocked(rl);
12240 if (rl.linkedToDeath) {
12241 rl.linkedToDeath = false;
12242 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12243 }
12244 }
12245 }
12246
12247 if (!doNext) {
12248 return;
12249 }
12250
12251 final long origId = Binder.clearCallingIdentity();
12252 processNextBroadcast(false);
12253 trimApplications();
12254 Binder.restoreCallingIdentity(origId);
12255 }
12256
12257 void removeReceiverLocked(ReceiverList rl) {
12258 mRegisteredReceivers.remove(rl.receiver.asBinder());
12259 int N = rl.size();
12260 for (int i=0; i<N; i++) {
12261 mReceiverResolver.removeFilter(rl.get(i));
12262 }
12263 }
12264
12265 private final int broadcastIntentLocked(ProcessRecord callerApp,
12266 String callerPackage, Intent intent, String resolvedType,
12267 IIntentReceiver resultTo, int resultCode, String resultData,
12268 Bundle map, String requiredPermission,
12269 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12270 intent = new Intent(intent);
12271
Joe Onorato8a9b2202010-02-26 18:56:32 -080012272 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012273 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12274 + " ordered=" + ordered);
12275 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012276 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012277 }
12278
12279 // Handle special intents: if this broadcast is from the package
12280 // manager about a package being removed, we need to remove all of
12281 // its activities from the history stack.
12282 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12283 intent.getAction());
12284 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12285 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012286 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012287 || uidRemoved) {
12288 if (checkComponentPermission(
12289 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12290 callingPid, callingUid, -1)
12291 == PackageManager.PERMISSION_GRANTED) {
12292 if (uidRemoved) {
12293 final Bundle intentExtras = intent.getExtras();
12294 final int uid = intentExtras != null
12295 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12296 if (uid >= 0) {
12297 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12298 synchronized (bs) {
12299 bs.removeUidStatsLocked(uid);
12300 }
12301 }
12302 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012303 // If resources are unvailble just force stop all
12304 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012305 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012306 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12307 if (list != null && (list.length > 0)) {
12308 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012309 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012310 }
12311 }
12312 } else {
12313 Uri data = intent.getData();
12314 String ssp;
12315 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12316 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12317 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012318 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012320 }
12321 }
12322 }
12323 } else {
12324 String msg = "Permission Denial: " + intent.getAction()
12325 + " broadcast from " + callerPackage + " (pid=" + callingPid
12326 + ", uid=" + callingUid + ")"
12327 + " requires "
12328 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012329 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012330 throw new SecurityException(msg);
12331 }
12332 }
12333
12334 /*
12335 * If this is the time zone changed action, queue up a message that will reset the timezone
12336 * of all currently running processes. This message will get queued up before the broadcast
12337 * happens.
12338 */
12339 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12340 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12341 }
12342
Dianne Hackborn854060af2009-07-09 18:14:31 -070012343 /*
12344 * Prevent non-system code (defined here to be non-persistent
12345 * processes) from sending protected broadcasts.
12346 */
12347 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12348 || callingUid == Process.SHELL_UID || callingUid == 0) {
12349 // Always okay.
12350 } else if (callerApp == null || !callerApp.persistent) {
12351 try {
12352 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12353 intent.getAction())) {
12354 String msg = "Permission Denial: not allowed to send broadcast "
12355 + intent.getAction() + " from pid="
12356 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012357 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012358 throw new SecurityException(msg);
12359 }
12360 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012361 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012362 return BROADCAST_SUCCESS;
12363 }
12364 }
12365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012366 // Add to the sticky list if requested.
12367 if (sticky) {
12368 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12369 callingPid, callingUid)
12370 != PackageManager.PERMISSION_GRANTED) {
12371 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12372 + callingPid + ", uid=" + callingUid
12373 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012374 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012375 throw new SecurityException(msg);
12376 }
12377 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012378 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012379 + " and enforce permission " + requiredPermission);
12380 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12381 }
12382 if (intent.getComponent() != null) {
12383 throw new SecurityException(
12384 "Sticky broadcasts can't target a specific component");
12385 }
12386 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12387 if (list == null) {
12388 list = new ArrayList<Intent>();
12389 mStickyBroadcasts.put(intent.getAction(), list);
12390 }
12391 int N = list.size();
12392 int i;
12393 for (i=0; i<N; i++) {
12394 if (intent.filterEquals(list.get(i))) {
12395 // This sticky already exists, replace it.
12396 list.set(i, new Intent(intent));
12397 break;
12398 }
12399 }
12400 if (i >= N) {
12401 list.add(new Intent(intent));
12402 }
12403 }
12404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012405 // Figure out who all will receive this broadcast.
12406 List receivers = null;
12407 List<BroadcastFilter> registeredReceivers = null;
12408 try {
12409 if (intent.getComponent() != null) {
12410 // Broadcast is going to one specific receiver class...
12411 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012412 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012413 if (ai != null) {
12414 receivers = new ArrayList();
12415 ResolveInfo ri = new ResolveInfo();
12416 ri.activityInfo = ai;
12417 receivers.add(ri);
12418 }
12419 } else {
12420 // Need to resolve the intent to interested receivers...
12421 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12422 == 0) {
12423 receivers =
12424 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012425 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012426 }
Mihai Preda074edef2009-05-18 17:13:31 +020012427 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012428 }
12429 } catch (RemoteException ex) {
12430 // pm is in same process, this will never happen.
12431 }
12432
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012433 final boolean replacePending =
12434 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12435
Joe Onorato8a9b2202010-02-26 18:56:32 -080012436 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012437 + " replacePending=" + replacePending);
12438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012439 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12440 if (!ordered && NR > 0) {
12441 // If we are not serializing this broadcast, then send the
12442 // registered receivers separately so they don't wait for the
12443 // components to be launched.
12444 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12445 callerPackage, callingPid, callingUid, requiredPermission,
12446 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012447 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012448 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012449 TAG, "Enqueueing parallel broadcast " + r
12450 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012451 boolean replaced = false;
12452 if (replacePending) {
12453 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12454 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012455 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012456 "***** DROPPING PARALLEL: " + intent);
12457 mParallelBroadcasts.set(i, r);
12458 replaced = true;
12459 break;
12460 }
12461 }
12462 }
12463 if (!replaced) {
12464 mParallelBroadcasts.add(r);
12465 scheduleBroadcastsLocked();
12466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012467 registeredReceivers = null;
12468 NR = 0;
12469 }
12470
12471 // Merge into one list.
12472 int ir = 0;
12473 if (receivers != null) {
12474 // A special case for PACKAGE_ADDED: do not allow the package
12475 // being added to see this broadcast. This prevents them from
12476 // using this as a back door to get run as soon as they are
12477 // installed. Maybe in the future we want to have a special install
12478 // broadcast or such for apps, but we'd like to deliberately make
12479 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012480 String skipPackages[] = null;
12481 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12482 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12483 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12484 Uri data = intent.getData();
12485 if (data != null) {
12486 String pkgName = data.getSchemeSpecificPart();
12487 if (pkgName != null) {
12488 skipPackages = new String[] { pkgName };
12489 }
12490 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012491 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012492 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012493 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012494 if (skipPackages != null && (skipPackages.length > 0)) {
12495 for (String skipPackage : skipPackages) {
12496 if (skipPackage != null) {
12497 int NT = receivers.size();
12498 for (int it=0; it<NT; it++) {
12499 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12500 if (curt.activityInfo.packageName.equals(skipPackage)) {
12501 receivers.remove(it);
12502 it--;
12503 NT--;
12504 }
12505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012506 }
12507 }
12508 }
12509
12510 int NT = receivers != null ? receivers.size() : 0;
12511 int it = 0;
12512 ResolveInfo curt = null;
12513 BroadcastFilter curr = null;
12514 while (it < NT && ir < NR) {
12515 if (curt == null) {
12516 curt = (ResolveInfo)receivers.get(it);
12517 }
12518 if (curr == null) {
12519 curr = registeredReceivers.get(ir);
12520 }
12521 if (curr.getPriority() >= curt.priority) {
12522 // Insert this broadcast record into the final list.
12523 receivers.add(it, curr);
12524 ir++;
12525 curr = null;
12526 it++;
12527 NT++;
12528 } else {
12529 // Skip to the next ResolveInfo in the final list.
12530 it++;
12531 curt = null;
12532 }
12533 }
12534 }
12535 while (ir < NR) {
12536 if (receivers == null) {
12537 receivers = new ArrayList();
12538 }
12539 receivers.add(registeredReceivers.get(ir));
12540 ir++;
12541 }
12542
12543 if ((receivers != null && receivers.size() > 0)
12544 || resultTo != null) {
12545 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12546 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012547 receivers, resultTo, resultCode, resultData, map, ordered,
12548 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012549 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012550 TAG, "Enqueueing ordered broadcast " + r
12551 + ": prev had " + mOrderedBroadcasts.size());
12552 if (DEBUG_BROADCAST) {
12553 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012554 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012555 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012556 boolean replaced = false;
12557 if (replacePending) {
12558 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12559 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012560 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012561 "***** DROPPING ORDERED: " + intent);
12562 mOrderedBroadcasts.set(i, r);
12563 replaced = true;
12564 break;
12565 }
12566 }
12567 }
12568 if (!replaced) {
12569 mOrderedBroadcasts.add(r);
12570 scheduleBroadcastsLocked();
12571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012572 }
12573
12574 return BROADCAST_SUCCESS;
12575 }
12576
12577 public final int broadcastIntent(IApplicationThread caller,
12578 Intent intent, String resolvedType, IIntentReceiver resultTo,
12579 int resultCode, String resultData, Bundle map,
12580 String requiredPermission, boolean serialized, boolean sticky) {
12581 // Refuse possible leaked file descriptors
12582 if (intent != null && intent.hasFileDescriptors() == true) {
12583 throw new IllegalArgumentException("File descriptors passed in Intent");
12584 }
12585
12586 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012587 int flags = intent.getFlags();
12588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012589 if (!mSystemReady) {
12590 // if the caller really truly claims to know what they're doing, go
12591 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012592 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12593 intent = new Intent(intent);
12594 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12595 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012596 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012597 + " before boot completion");
12598 throw new IllegalStateException("Cannot broadcast before boot completed");
12599 }
12600 }
12601
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012602 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12603 throw new IllegalArgumentException(
12604 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12605 }
12606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012607 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12608 final int callingPid = Binder.getCallingPid();
12609 final int callingUid = Binder.getCallingUid();
12610 final long origId = Binder.clearCallingIdentity();
12611 int res = broadcastIntentLocked(callerApp,
12612 callerApp != null ? callerApp.info.packageName : null,
12613 intent, resolvedType, resultTo,
12614 resultCode, resultData, map, requiredPermission, serialized,
12615 sticky, callingPid, callingUid);
12616 Binder.restoreCallingIdentity(origId);
12617 return res;
12618 }
12619 }
12620
12621 int broadcastIntentInPackage(String packageName, int uid,
12622 Intent intent, String resolvedType, IIntentReceiver resultTo,
12623 int resultCode, String resultData, Bundle map,
12624 String requiredPermission, boolean serialized, boolean sticky) {
12625 synchronized(this) {
12626 final long origId = Binder.clearCallingIdentity();
12627 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12628 resultTo, resultCode, resultData, map, requiredPermission,
12629 serialized, sticky, -1, uid);
12630 Binder.restoreCallingIdentity(origId);
12631 return res;
12632 }
12633 }
12634
12635 public final void unbroadcastIntent(IApplicationThread caller,
12636 Intent intent) {
12637 // Refuse possible leaked file descriptors
12638 if (intent != null && intent.hasFileDescriptors() == true) {
12639 throw new IllegalArgumentException("File descriptors passed in Intent");
12640 }
12641
12642 synchronized(this) {
12643 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12644 != PackageManager.PERMISSION_GRANTED) {
12645 String msg = "Permission Denial: unbroadcastIntent() from pid="
12646 + Binder.getCallingPid()
12647 + ", uid=" + Binder.getCallingUid()
12648 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012649 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012650 throw new SecurityException(msg);
12651 }
12652 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12653 if (list != null) {
12654 int N = list.size();
12655 int i;
12656 for (i=0; i<N; i++) {
12657 if (intent.filterEquals(list.get(i))) {
12658 list.remove(i);
12659 break;
12660 }
12661 }
12662 }
12663 }
12664 }
12665
12666 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12667 String resultData, Bundle resultExtras, boolean resultAbort,
12668 boolean explicit) {
12669 if (mOrderedBroadcasts.size() == 0) {
12670 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012671 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012672 }
12673 return false;
12674 }
12675 BroadcastRecord r = mOrderedBroadcasts.get(0);
12676 if (r.receiver == null) {
12677 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012678 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012679 }
12680 return false;
12681 }
12682 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012683 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012684 return false;
12685 }
12686 int state = r.state;
12687 r.state = r.IDLE;
12688 if (state == r.IDLE) {
12689 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012690 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012691 }
12692 }
12693 r.receiver = null;
12694 r.intent.setComponent(null);
12695 if (r.curApp != null) {
12696 r.curApp.curReceiver = null;
12697 }
12698 if (r.curFilter != null) {
12699 r.curFilter.receiverList.curBroadcast = null;
12700 }
12701 r.curFilter = null;
12702 r.curApp = null;
12703 r.curComponent = null;
12704 r.curReceiver = null;
12705 mPendingBroadcast = null;
12706
12707 r.resultCode = resultCode;
12708 r.resultData = resultData;
12709 r.resultExtras = resultExtras;
12710 r.resultAbort = resultAbort;
12711
12712 // We will process the next receiver right now if this is finishing
12713 // an app receiver (which is always asynchronous) or after we have
12714 // come back from calling a receiver.
12715 return state == BroadcastRecord.APP_RECEIVE
12716 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12717 }
12718
12719 public void finishReceiver(IBinder who, int resultCode, String resultData,
12720 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012721 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012722
12723 // Refuse possible leaked file descriptors
12724 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12725 throw new IllegalArgumentException("File descriptors passed in Bundle");
12726 }
12727
12728 boolean doNext;
12729
12730 final long origId = Binder.clearCallingIdentity();
12731
12732 synchronized(this) {
12733 doNext = finishReceiverLocked(
12734 who, resultCode, resultData, resultExtras, resultAbort, true);
12735 }
12736
12737 if (doNext) {
12738 processNextBroadcast(false);
12739 }
12740 trimApplications();
12741
12742 Binder.restoreCallingIdentity(origId);
12743 }
12744
12745 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12746 if (r.nextReceiver > 0) {
12747 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12748 if (curReceiver instanceof BroadcastFilter) {
12749 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012750 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012751 System.identityHashCode(r),
12752 r.intent.getAction(),
12753 r.nextReceiver - 1,
12754 System.identityHashCode(bf));
12755 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012756 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012757 System.identityHashCode(r),
12758 r.intent.getAction(),
12759 r.nextReceiver - 1,
12760 ((ResolveInfo)curReceiver).toString());
12761 }
12762 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012763 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012764 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012765 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012766 System.identityHashCode(r),
12767 r.intent.getAction(),
12768 r.nextReceiver,
12769 "NONE");
12770 }
12771 }
12772
12773 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012774 ProcessRecord app = null;
12775 String anrMessage = null;
12776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012777 synchronized (this) {
12778 if (mOrderedBroadcasts.size() == 0) {
12779 return;
12780 }
12781 long now = SystemClock.uptimeMillis();
12782 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012783 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012784 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012785 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012786 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012787 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012788 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012789 return;
12790 }
12791
Joe Onorato8a9b2202010-02-26 18:56:32 -080012792 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012793 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012794 r.anrCount++;
12795
12796 // Current receiver has passed its expiration date.
12797 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012798 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012799 return;
12800 }
12801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012802 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012803 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012804 logBroadcastReceiverDiscard(r);
12805 if (curReceiver instanceof BroadcastFilter) {
12806 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12807 if (bf.receiverList.pid != 0
12808 && bf.receiverList.pid != MY_PID) {
12809 synchronized (this.mPidsSelfLocked) {
12810 app = this.mPidsSelfLocked.get(
12811 bf.receiverList.pid);
12812 }
12813 }
12814 } else {
12815 app = r.curApp;
12816 }
12817
12818 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012819 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012820 }
12821
12822 if (mPendingBroadcast == r) {
12823 mPendingBroadcast = null;
12824 }
12825
12826 // Move on to the next receiver.
12827 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12828 r.resultExtras, r.resultAbort, true);
12829 scheduleBroadcastsLocked();
12830 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012831
12832 if (anrMessage != null) {
12833 appNotResponding(app, null, null, anrMessage);
12834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012835 }
12836
12837 private final void processCurBroadcastLocked(BroadcastRecord r,
12838 ProcessRecord app) throws RemoteException {
12839 if (app.thread == null) {
12840 throw new RemoteException();
12841 }
12842 r.receiver = app.thread.asBinder();
12843 r.curApp = app;
12844 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012845 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012846
12847 // Tell the application to launch this receiver.
12848 r.intent.setComponent(r.curComponent);
12849
12850 boolean started = false;
12851 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012852 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012853 "Delivering to component " + r.curComponent
12854 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012855 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012856 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12857 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12858 started = true;
12859 } finally {
12860 if (!started) {
12861 r.receiver = null;
12862 r.curApp = null;
12863 app.curReceiver = null;
12864 }
12865 }
12866
12867 }
12868
12869 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012870 Intent intent, int resultCode, String data, Bundle extras,
12871 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012872 if (app != null && app.thread != null) {
12873 // If we have an app thread, do the call through that so it is
12874 // correctly ordered with other one-way calls.
12875 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012876 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012877 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012878 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012879 }
12880 }
12881
12882 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12883 BroadcastFilter filter, boolean ordered) {
12884 boolean skip = false;
12885 if (filter.requiredPermission != null) {
12886 int perm = checkComponentPermission(filter.requiredPermission,
12887 r.callingPid, r.callingUid, -1);
12888 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012889 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012890 + r.intent.toString()
12891 + " from " + r.callerPackage + " (pid="
12892 + r.callingPid + ", uid=" + r.callingUid + ")"
12893 + " requires " + filter.requiredPermission
12894 + " due to registered receiver " + filter);
12895 skip = true;
12896 }
12897 }
12898 if (r.requiredPermission != null) {
12899 int perm = checkComponentPermission(r.requiredPermission,
12900 filter.receiverList.pid, filter.receiverList.uid, -1);
12901 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012902 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012903 + r.intent.toString()
12904 + " to " + filter.receiverList.app
12905 + " (pid=" + filter.receiverList.pid
12906 + ", uid=" + filter.receiverList.uid + ")"
12907 + " requires " + r.requiredPermission
12908 + " due to sender " + r.callerPackage
12909 + " (uid " + r.callingUid + ")");
12910 skip = true;
12911 }
12912 }
12913
12914 if (!skip) {
12915 // If this is not being sent as an ordered broadcast, then we
12916 // don't want to touch the fields that keep track of the current
12917 // state of ordered broadcasts.
12918 if (ordered) {
12919 r.receiver = filter.receiverList.receiver.asBinder();
12920 r.curFilter = filter;
12921 filter.receiverList.curBroadcast = r;
12922 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012923 if (filter.receiverList.app != null) {
12924 // Bump hosting application to no longer be in background
12925 // scheduling class. Note that we can't do that if there
12926 // isn't an app... but we can only be in that case for
12927 // things that directly call the IActivityManager API, which
12928 // are already core system stuff so don't matter for this.
12929 r.curApp = filter.receiverList.app;
12930 filter.receiverList.app.curReceiver = r;
12931 updateOomAdjLocked();
12932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012933 }
12934 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012935 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012936 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012937 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012938 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012939 }
12940 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12941 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012942 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012943 if (ordered) {
12944 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12945 }
12946 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012947 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012948 if (ordered) {
12949 r.receiver = null;
12950 r.curFilter = null;
12951 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012952 if (filter.receiverList.app != null) {
12953 filter.receiverList.app.curReceiver = null;
12954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012955 }
12956 }
12957 }
12958 }
12959
Dianne Hackborn12527f92009-11-11 17:39:50 -080012960 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12961 if (r.callingUid < 0) {
12962 // This was from a registerReceiver() call; ignore it.
12963 return;
12964 }
12965 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12966 MAX_BROADCAST_HISTORY-1);
12967 r.finishTime = SystemClock.uptimeMillis();
12968 mBroadcastHistory[0] = r;
12969 }
12970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012971 private final void processNextBroadcast(boolean fromMsg) {
12972 synchronized(this) {
12973 BroadcastRecord r;
12974
Joe Onorato8a9b2202010-02-26 18:56:32 -080012975 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012976 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012977 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012978
12979 updateCpuStats();
12980
12981 if (fromMsg) {
12982 mBroadcastsScheduled = false;
12983 }
12984
12985 // First, deliver any non-serialized broadcasts right away.
12986 while (mParallelBroadcasts.size() > 0) {
12987 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012988 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012989 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012990 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012991 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012992 for (int i=0; i<N; i++) {
12993 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012994 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012995 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012996 + target + ": " + r);
12997 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12998 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012999 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013000 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013001 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013002 }
13003
13004 // Now take care of the next serialized one...
13005
13006 // If we are waiting for a process to come up to handle the next
13007 // broadcast, then do nothing at this point. Just in case, we
13008 // check that the process we're waiting for still exists.
13009 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013010 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013011 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013012 + mPendingBroadcast.curApp);
13013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013014
13015 boolean isDead;
13016 synchronized (mPidsSelfLocked) {
13017 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13018 }
13019 if (!isDead) {
13020 // It's still alive, so keep waiting
13021 return;
13022 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013023 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013024 + " died before responding to broadcast");
13025 mPendingBroadcast = null;
13026 }
13027 }
13028
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013029 boolean looped = false;
13030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013031 do {
13032 if (mOrderedBroadcasts.size() == 0) {
13033 // No more broadcasts pending, so all done!
13034 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013035 if (looped) {
13036 // If we had finished the last ordered broadcast, then
13037 // make sure all processes have correct oom and sched
13038 // adjustments.
13039 updateOomAdjLocked();
13040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013041 return;
13042 }
13043 r = mOrderedBroadcasts.get(0);
13044 boolean forceReceive = false;
13045
13046 // Ensure that even if something goes awry with the timeout
13047 // detection, we catch "hung" broadcasts here, discard them,
13048 // and continue to make progress.
13049 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
13050 long now = SystemClock.uptimeMillis();
13051 if (r.dispatchTime > 0) {
13052 if ((numReceivers > 0) &&
13053 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013054 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013055 + " now=" + now
13056 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013057 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013058 + " intent=" + r.intent
13059 + " numReceivers=" + numReceivers
13060 + " nextReceiver=" + r.nextReceiver
13061 + " state=" + r.state);
13062 broadcastTimeout(); // forcibly finish this broadcast
13063 forceReceive = true;
13064 r.state = BroadcastRecord.IDLE;
13065 }
13066 }
13067
13068 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013069 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013070 "processNextBroadcast() called when not idle (state="
13071 + r.state + ")");
13072 return;
13073 }
13074
13075 if (r.receivers == null || r.nextReceiver >= numReceivers
13076 || r.resultAbort || forceReceive) {
13077 // No more receivers for this broadcast! Send the final
13078 // result if requested...
13079 if (r.resultTo != null) {
13080 try {
13081 if (DEBUG_BROADCAST) {
13082 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013083 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013084 + " seq=" + seq + " app=" + r.callerApp);
13085 }
13086 performReceive(r.callerApp, r.resultTo,
13087 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013088 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013089 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013090 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013091 }
13092 }
13093
Joe Onorato8a9b2202010-02-26 18:56:32 -080013094 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013095 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13096
Joe Onorato8a9b2202010-02-26 18:56:32 -080013097 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013098 + r);
13099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013100 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013101 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013102 mOrderedBroadcasts.remove(0);
13103 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013104 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013105 continue;
13106 }
13107 } while (r == null);
13108
13109 // Get the next receiver...
13110 int recIdx = r.nextReceiver++;
13111
13112 // Keep track of when this receiver started, and make sure there
13113 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013114 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013115 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013116 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013117
Joe Onorato8a9b2202010-02-26 18:56:32 -080013118 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013119 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013120 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013121 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013122 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013123 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013124 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013125 }
13126
13127 Object nextReceiver = r.receivers.get(recIdx);
13128 if (nextReceiver instanceof BroadcastFilter) {
13129 // Simple case: this is a registered receiver who gets
13130 // a direct call.
13131 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013132 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013133 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013134 + filter + ": " + r);
13135 deliverToRegisteredReceiver(r, filter, r.ordered);
13136 if (r.receiver == null || !r.ordered) {
13137 // The receiver has already finished, so schedule to
13138 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013139 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13140 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013141 r.state = BroadcastRecord.IDLE;
13142 scheduleBroadcastsLocked();
13143 }
13144 return;
13145 }
13146
13147 // Hard case: need to instantiate the receiver, possibly
13148 // starting its application process to host it.
13149
13150 ResolveInfo info =
13151 (ResolveInfo)nextReceiver;
13152
13153 boolean skip = false;
13154 int perm = checkComponentPermission(info.activityInfo.permission,
13155 r.callingPid, r.callingUid,
13156 info.activityInfo.exported
13157 ? -1 : info.activityInfo.applicationInfo.uid);
13158 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013159 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013160 + r.intent.toString()
13161 + " from " + r.callerPackage + " (pid=" + r.callingPid
13162 + ", uid=" + r.callingUid + ")"
13163 + " requires " + info.activityInfo.permission
13164 + " due to receiver " + info.activityInfo.packageName
13165 + "/" + info.activityInfo.name);
13166 skip = true;
13167 }
13168 if (r.callingUid != Process.SYSTEM_UID &&
13169 r.requiredPermission != null) {
13170 try {
13171 perm = ActivityThread.getPackageManager().
13172 checkPermission(r.requiredPermission,
13173 info.activityInfo.applicationInfo.packageName);
13174 } catch (RemoteException e) {
13175 perm = PackageManager.PERMISSION_DENIED;
13176 }
13177 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013178 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013179 + r.intent + " to "
13180 + info.activityInfo.applicationInfo.packageName
13181 + " requires " + r.requiredPermission
13182 + " due to sender " + r.callerPackage
13183 + " (uid " + r.callingUid + ")");
13184 skip = true;
13185 }
13186 }
13187 if (r.curApp != null && r.curApp.crashing) {
13188 // If the target process is crashing, just skip it.
13189 skip = true;
13190 }
13191
13192 if (skip) {
13193 r.receiver = null;
13194 r.curFilter = null;
13195 r.state = BroadcastRecord.IDLE;
13196 scheduleBroadcastsLocked();
13197 return;
13198 }
13199
13200 r.state = BroadcastRecord.APP_RECEIVE;
13201 String targetProcess = info.activityInfo.processName;
13202 r.curComponent = new ComponentName(
13203 info.activityInfo.applicationInfo.packageName,
13204 info.activityInfo.name);
13205 r.curReceiver = info.activityInfo;
13206
13207 // Is this receiver's application already running?
13208 ProcessRecord app = getProcessRecordLocked(targetProcess,
13209 info.activityInfo.applicationInfo.uid);
13210 if (app != null && app.thread != null) {
13211 try {
13212 processCurBroadcastLocked(r, app);
13213 return;
13214 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013215 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013216 + r.curComponent, e);
13217 }
13218
13219 // If a dead object exception was thrown -- fall through to
13220 // restart the application.
13221 }
13222
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013223 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013224 if ((r.curApp=startProcessLocked(targetProcess,
13225 info.activityInfo.applicationInfo, true,
13226 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013227 "broadcast", r.curComponent,
13228 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13229 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013230 // Ah, this recipient is unavailable. Finish it if necessary,
13231 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013232 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013233 + info.activityInfo.applicationInfo.packageName + "/"
13234 + info.activityInfo.applicationInfo.uid + " for broadcast "
13235 + r.intent + ": process is bad");
13236 logBroadcastReceiverDiscard(r);
13237 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13238 r.resultExtras, r.resultAbort, true);
13239 scheduleBroadcastsLocked();
13240 r.state = BroadcastRecord.IDLE;
13241 return;
13242 }
13243
13244 mPendingBroadcast = r;
13245 }
13246 }
13247
13248 // =========================================================
13249 // INSTRUMENTATION
13250 // =========================================================
13251
13252 public boolean startInstrumentation(ComponentName className,
13253 String profileFile, int flags, Bundle arguments,
13254 IInstrumentationWatcher watcher) {
13255 // Refuse possible leaked file descriptors
13256 if (arguments != null && arguments.hasFileDescriptors()) {
13257 throw new IllegalArgumentException("File descriptors passed in Bundle");
13258 }
13259
13260 synchronized(this) {
13261 InstrumentationInfo ii = null;
13262 ApplicationInfo ai = null;
13263 try {
13264 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013265 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013266 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013267 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013268 } catch (PackageManager.NameNotFoundException e) {
13269 }
13270 if (ii == null) {
13271 reportStartInstrumentationFailure(watcher, className,
13272 "Unable to find instrumentation info for: " + className);
13273 return false;
13274 }
13275 if (ai == null) {
13276 reportStartInstrumentationFailure(watcher, className,
13277 "Unable to find instrumentation target package: " + ii.targetPackage);
13278 return false;
13279 }
13280
13281 int match = mContext.getPackageManager().checkSignatures(
13282 ii.targetPackage, ii.packageName);
13283 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13284 String msg = "Permission Denial: starting instrumentation "
13285 + className + " from pid="
13286 + Binder.getCallingPid()
13287 + ", uid=" + Binder.getCallingPid()
13288 + " not allowed because package " + ii.packageName
13289 + " does not have a signature matching the target "
13290 + ii.targetPackage;
13291 reportStartInstrumentationFailure(watcher, className, msg);
13292 throw new SecurityException(msg);
13293 }
13294
13295 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013296 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013297 ProcessRecord app = addAppLocked(ai);
13298 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013299 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013300 app.instrumentationProfileFile = profileFile;
13301 app.instrumentationArguments = arguments;
13302 app.instrumentationWatcher = watcher;
13303 app.instrumentationResultClass = className;
13304 Binder.restoreCallingIdentity(origId);
13305 }
13306
13307 return true;
13308 }
13309
13310 /**
13311 * Report errors that occur while attempting to start Instrumentation. Always writes the
13312 * error to the logs, but if somebody is watching, send the report there too. This enables
13313 * the "am" command to report errors with more information.
13314 *
13315 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13316 * @param cn The component name of the instrumentation.
13317 * @param report The error report.
13318 */
13319 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13320 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013321 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013322 try {
13323 if (watcher != null) {
13324 Bundle results = new Bundle();
13325 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13326 results.putString("Error", report);
13327 watcher.instrumentationStatus(cn, -1, results);
13328 }
13329 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013330 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013331 }
13332 }
13333
13334 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13335 if (app.instrumentationWatcher != null) {
13336 try {
13337 // NOTE: IInstrumentationWatcher *must* be oneway here
13338 app.instrumentationWatcher.instrumentationFinished(
13339 app.instrumentationClass,
13340 resultCode,
13341 results);
13342 } catch (RemoteException e) {
13343 }
13344 }
13345 app.instrumentationWatcher = null;
13346 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013347 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013348 app.instrumentationProfileFile = null;
13349 app.instrumentationArguments = null;
13350
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013351 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013352 }
13353
13354 public void finishInstrumentation(IApplicationThread target,
13355 int resultCode, Bundle results) {
13356 // Refuse possible leaked file descriptors
13357 if (results != null && results.hasFileDescriptors()) {
13358 throw new IllegalArgumentException("File descriptors passed in Intent");
13359 }
13360
13361 synchronized(this) {
13362 ProcessRecord app = getRecordForAppLocked(target);
13363 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013364 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013365 return;
13366 }
13367 final long origId = Binder.clearCallingIdentity();
13368 finishInstrumentationLocked(app, resultCode, results);
13369 Binder.restoreCallingIdentity(origId);
13370 }
13371 }
13372
13373 // =========================================================
13374 // CONFIGURATION
13375 // =========================================================
13376
13377 public ConfigurationInfo getDeviceConfigurationInfo() {
13378 ConfigurationInfo config = new ConfigurationInfo();
13379 synchronized (this) {
13380 config.reqTouchScreen = mConfiguration.touchscreen;
13381 config.reqKeyboardType = mConfiguration.keyboard;
13382 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013383 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13384 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013385 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13386 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013387 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13388 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013389 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13390 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013391 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392 }
13393 return config;
13394 }
13395
13396 public Configuration getConfiguration() {
13397 Configuration ci;
13398 synchronized(this) {
13399 ci = new Configuration(mConfiguration);
13400 }
13401 return ci;
13402 }
13403
13404 public void updateConfiguration(Configuration values) {
13405 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13406 "updateConfiguration()");
13407
13408 synchronized(this) {
13409 if (values == null && mWindowManager != null) {
13410 // sentinel: fetch the current configuration from the window manager
13411 values = mWindowManager.computeNewConfiguration();
13412 }
13413
13414 final long origId = Binder.clearCallingIdentity();
13415 updateConfigurationLocked(values, null);
13416 Binder.restoreCallingIdentity(origId);
13417 }
13418 }
13419
13420 /**
13421 * Do either or both things: (1) change the current configuration, and (2)
13422 * make sure the given activity is running with the (now) current
13423 * configuration. Returns true if the activity has been left running, or
13424 * false if <var>starting</var> is being destroyed to match the new
13425 * configuration.
13426 */
13427 public boolean updateConfigurationLocked(Configuration values,
13428 HistoryRecord starting) {
13429 int changes = 0;
13430
13431 boolean kept = true;
13432
13433 if (values != null) {
13434 Configuration newConfig = new Configuration(mConfiguration);
13435 changes = newConfig.updateFrom(values);
13436 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013437 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013438 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013439 }
13440
Doug Zongker2bec3d42009-12-04 12:52:44 -080013441 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013442
13443 if (values.locale != null) {
13444 saveLocaleLocked(values.locale,
13445 !values.locale.equals(mConfiguration.locale),
13446 values.userSetLocale);
13447 }
13448
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013449 mConfigurationSeq++;
13450 if (mConfigurationSeq <= 0) {
13451 mConfigurationSeq = 1;
13452 }
13453 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013454 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013455 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013456
13457 AttributeCache ac = AttributeCache.instance();
13458 if (ac != null) {
13459 ac.updateConfiguration(mConfiguration);
13460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013461
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013462 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13463 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13464 msg.obj = new Configuration(mConfiguration);
13465 mHandler.sendMessage(msg);
13466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013467
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013468 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13469 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013470 try {
13471 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013472 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013473 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013474 app.thread.scheduleConfigurationChanged(mConfiguration);
13475 }
13476 } catch (Exception e) {
13477 }
13478 }
13479 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013480 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13481 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013482 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13483 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013484 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13485 broadcastIntentLocked(null, null,
13486 new Intent(Intent.ACTION_LOCALE_CHANGED),
13487 null, null, 0, null, null,
13488 null, false, false, MY_PID, Process.SYSTEM_UID);
13489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013490 }
13491 }
13492
13493 if (changes != 0 && starting == null) {
13494 // If the configuration changed, and the caller is not already
13495 // in the process of starting an activity, then find the top
13496 // activity to check if its configuration needs to change.
13497 starting = topRunningActivityLocked(null);
13498 }
13499
13500 if (starting != null) {
13501 kept = ensureActivityConfigurationLocked(starting, changes);
13502 if (kept) {
13503 // If this didn't result in the starting activity being
13504 // destroyed, then we need to make sure at this point that all
13505 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013506 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013507 + ", ensuring others are correct.");
13508 ensureActivitiesVisibleLocked(starting, changes);
13509 }
13510 }
13511
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013512 if (values != null && mWindowManager != null) {
13513 mWindowManager.setNewConfiguration(mConfiguration);
13514 }
13515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013516 return kept;
13517 }
13518
13519 private final boolean relaunchActivityLocked(HistoryRecord r,
13520 int changes, boolean andResume) {
13521 List<ResultInfo> results = null;
13522 List<Intent> newIntents = null;
13523 if (andResume) {
13524 results = r.results;
13525 newIntents = r.newIntents;
13526 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013527 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013528 + " with results=" + results + " newIntents=" + newIntents
13529 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013530 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13531 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013532 r.task.taskId, r.shortComponentName);
13533
13534 r.startFreezingScreenLocked(r.app, 0);
13535
13536 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013537 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013538 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013539 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013540 // Note: don't need to call pauseIfSleepingLocked() here, because
13541 // the caller will only pass in 'andResume' if this activity is
13542 // currently resumed, which implies we aren't sleeping.
13543 } catch (RemoteException e) {
13544 return false;
13545 }
13546
13547 if (andResume) {
13548 r.results = null;
13549 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013550 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013551 }
13552
13553 return true;
13554 }
13555
13556 /**
13557 * Make sure the given activity matches the current configuration. Returns
13558 * false if the activity had to be destroyed. Returns true if the
13559 * configuration is the same, or the activity will remain running as-is
13560 * for whatever reason. Ensures the HistoryRecord is updated with the
13561 * correct configuration and all other bookkeeping is handled.
13562 */
13563 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13564 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013565 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013566 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13567 "Skipping config check (will change): " + r);
13568 return true;
13569 }
13570
Joe Onorato8a9b2202010-02-26 18:56:32 -080013571 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013572 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013573
13574 // Short circuit: if the two configurations are the exact same
13575 // object (the common case), then there is nothing to do.
13576 Configuration newConfig = mConfiguration;
13577 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013578 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013579 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013580 return true;
13581 }
13582
13583 // We don't worry about activities that are finishing.
13584 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013585 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013586 "Configuration doesn't matter in finishing " + r);
13587 r.stopFreezingScreenLocked(false);
13588 return true;
13589 }
13590
13591 // Okay we now are going to make this activity have the new config.
13592 // But then we need to figure out how it needs to deal with that.
13593 Configuration oldConfig = r.configuration;
13594 r.configuration = newConfig;
13595
13596 // If the activity isn't currently running, just leave the new
13597 // configuration and it will pick that up next time it starts.
13598 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013599 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013600 "Configuration doesn't matter not running " + r);
13601 r.stopFreezingScreenLocked(false);
13602 return true;
13603 }
13604
13605 // If the activity isn't persistent, there is a chance we will
13606 // need to restart it.
13607 if (!r.persistent) {
13608
13609 // Figure out what has changed between the two configurations.
13610 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013611 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013612 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013613 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013614 + Integer.toHexString(r.info.configChanges)
13615 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013616 }
13617 if ((changes&(~r.info.configChanges)) != 0) {
13618 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13619 r.configChangeFlags |= changes;
13620 r.startFreezingScreenLocked(r.app, globalChanges);
13621 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013622 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013623 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013624 destroyActivityLocked(r, true);
13625 } else if (r.state == ActivityState.PAUSING) {
13626 // A little annoying: we are waiting for this activity to
13627 // finish pausing. Let's not do anything now, but just
13628 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013629 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013630 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013631 r.configDestroy = true;
13632 return true;
13633 } else if (r.state == ActivityState.RESUMED) {
13634 // Try to optimize this case: the configuration is changing
13635 // and we need to restart the top, resumed activity.
13636 // Instead of doing the normal handshaking, just say
13637 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013638 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013639 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013640 relaunchActivityLocked(r, r.configChangeFlags, true);
13641 r.configChangeFlags = 0;
13642 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013643 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013644 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013645 relaunchActivityLocked(r, r.configChangeFlags, false);
13646 r.configChangeFlags = 0;
13647 }
13648
13649 // All done... tell the caller we weren't able to keep this
13650 // activity around.
13651 return false;
13652 }
13653 }
13654
13655 // Default case: the activity can handle this new configuration, so
13656 // hand it over. Note that we don't need to give it the new
13657 // configuration, since we always send configuration changes to all
13658 // process when they happen so it can just use whatever configuration
13659 // it last got.
13660 if (r.app != null && r.app.thread != null) {
13661 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013662 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013663 r.app.thread.scheduleActivityConfigurationChanged(r);
13664 } catch (RemoteException e) {
13665 // If process died, whatever.
13666 }
13667 }
13668 r.stopFreezingScreenLocked(false);
13669
13670 return true;
13671 }
13672
13673 /**
13674 * Save the locale. You must be inside a synchronized (this) block.
13675 */
13676 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13677 if(isDiff) {
13678 SystemProperties.set("user.language", l.getLanguage());
13679 SystemProperties.set("user.region", l.getCountry());
13680 }
13681
13682 if(isPersist) {
13683 SystemProperties.set("persist.sys.language", l.getLanguage());
13684 SystemProperties.set("persist.sys.country", l.getCountry());
13685 SystemProperties.set("persist.sys.localevar", l.getVariant());
13686 }
13687 }
13688
13689 // =========================================================
13690 // LIFETIME MANAGEMENT
13691 // =========================================================
13692
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013693 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13694 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013695 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013696 // This adjustment has already been computed. If we are calling
13697 // from the top, we may have already computed our adjustment with
13698 // an earlier hidden adjustment that isn't really for us... if
13699 // so, use the new hidden adjustment.
13700 if (!recursed && app.hidden) {
13701 app.curAdj = hiddenAdj;
13702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013703 return app.curAdj;
13704 }
13705
13706 if (app.thread == null) {
13707 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013708 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013709 return (app.curAdj=EMPTY_APP_ADJ);
13710 }
13711
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013712 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13713 // The max adjustment doesn't allow this app to be anything
13714 // below foreground, so it is not worth doing work for it.
13715 app.adjType = "fixed";
13716 app.adjSeq = mAdjSeq;
13717 app.curRawAdj = app.maxAdj;
13718 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13719 return (app.curAdj=app.maxAdj);
13720 }
13721
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013722 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013723 app.adjSource = null;
13724 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013725 app.empty = false;
13726 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013727
The Android Open Source Project4df24232009-03-05 14:34:35 -080013728 // Determine the importance of the process, starting with most
13729 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013730 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013731 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013732 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013733 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013734 // The last app on the list is the foreground app.
13735 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013736 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013737 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013738 } else if (app.instrumentationClass != null) {
13739 // Don't want to kill running instrumentation.
13740 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013741 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013742 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013743 } else if (app.persistentActivities > 0) {
13744 // Special persistent activities... shouldn't be used these days.
13745 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013746 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013747 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013748 } else if (app.curReceiver != null ||
13749 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13750 // An app that is currently receiving a broadcast also
13751 // counts as being in the foreground.
13752 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013753 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013754 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013755 } else if (app.executingServices.size() > 0) {
13756 // An app that is currently executing a service callback also
13757 // counts as being in the foreground.
13758 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013759 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013760 app.adjType = "exec-service";
13761 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013762 // The user is aware of this app, so make it visible.
13763 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013764 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013765 app.adjType = "foreground-service";
13766 } else if (app.forcingToForeground != null) {
13767 // The user is aware of this app, so make it visible.
13768 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013769 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013770 app.adjType = "force-foreground";
13771 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013772 } else if (app == mHomeProcess) {
13773 // This process is hosting what we currently consider to be the
13774 // home app, so we don't want to let it go into the background.
13775 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013776 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013777 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013778 } else if ((N=app.activities.size()) != 0) {
13779 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013780 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013781 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013782 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013783 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013784 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013785 for (int j=0; j<N; j++) {
13786 if (((HistoryRecord)app.activities.get(j)).visible) {
13787 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013788 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013789 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013790 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013791 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013792 break;
13793 }
13794 }
13795 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013796 // A very not-needed process. If this is lower in the lru list,
13797 // we will push it in to the empty bucket.
13798 app.hidden = true;
13799 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013800 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013801 adj = hiddenAdj;
13802 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013803 }
13804
Joe Onorato8a9b2202010-02-26 18:56:32 -080013805 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013806
The Android Open Source Project4df24232009-03-05 14:34:35 -080013807 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013808 // there are applications dependent on our services or providers, but
13809 // this gives us a baseline and makes sure we don't get into an
13810 // infinite recursion.
13811 app.adjSeq = mAdjSeq;
13812 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013813
Christopher Tate6fa95972009-06-05 18:43:55 -070013814 if (mBackupTarget != null && app == mBackupTarget.app) {
13815 // If possible we want to avoid killing apps while they're being backed up
13816 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013817 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013818 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013819 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013820 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013821 }
13822 }
13823
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013824 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13825 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013826 final long now = SystemClock.uptimeMillis();
13827 // This process is more important if the top activity is
13828 // bound to the service.
13829 Iterator jt = app.services.iterator();
13830 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13831 ServiceRecord s = (ServiceRecord)jt.next();
13832 if (s.startRequested) {
13833 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13834 // This service has seen some activity within
13835 // recent memory, so we will keep its process ahead
13836 // of the background processes.
13837 if (adj > SECONDARY_SERVER_ADJ) {
13838 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013839 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013840 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013841 }
13842 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013843 // If we have let the service slide into the background
13844 // state, still have some text describing what it is doing
13845 // even though the service no longer has an impact.
13846 if (adj > SECONDARY_SERVER_ADJ) {
13847 app.adjType = "started-bg-services";
13848 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013849 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013850 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13851 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013852 Iterator<ConnectionRecord> kt
13853 = s.connections.values().iterator();
13854 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13855 // XXX should compute this based on the max of
13856 // all connected clients.
13857 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013858 if (cr.binding.client == app) {
13859 // Binding to ourself is not interesting.
13860 continue;
13861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013862 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13863 ProcessRecord client = cr.binding.client;
13864 int myHiddenAdj = hiddenAdj;
13865 if (myHiddenAdj > client.hiddenAdj) {
13866 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13867 myHiddenAdj = client.hiddenAdj;
13868 } else {
13869 myHiddenAdj = VISIBLE_APP_ADJ;
13870 }
13871 }
13872 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013873 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013874 if (adj > clientAdj) {
13875 adj = clientAdj > VISIBLE_APP_ADJ
13876 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013877 if (!client.hidden) {
13878 app.hidden = false;
13879 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013880 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013881 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13882 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013883 app.adjSource = cr.binding.client;
13884 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013885 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013886 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13887 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13888 schedGroup = Process.THREAD_GROUP_DEFAULT;
13889 }
13890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013891 }
13892 HistoryRecord a = cr.activity;
13893 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013894 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013895 //}
13896 if (a != null && adj > FOREGROUND_APP_ADJ &&
13897 (a.state == ActivityState.RESUMED
13898 || a.state == ActivityState.PAUSING)) {
13899 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013900 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013901 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013902 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013903 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13904 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013905 app.adjSource = a;
13906 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013907 }
13908 }
13909 }
13910 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013911
13912 // Finally, f this process has active services running in it, we
13913 // would like to avoid killing it unless it would prevent the current
13914 // application from running. By default we put the process in
13915 // with the rest of the background processes; as we scan through
13916 // its services we may bump it up from there.
13917 if (adj > hiddenAdj) {
13918 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013919 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013920 app.adjType = "bg-services";
13921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013922 }
13923
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013924 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13925 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013926 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013927 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13928 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013929 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13930 if (cpr.clients.size() != 0) {
13931 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13932 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13933 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013934 if (client == app) {
13935 // Being our own client is not interesting.
13936 continue;
13937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013938 int myHiddenAdj = hiddenAdj;
13939 if (myHiddenAdj > client.hiddenAdj) {
13940 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13941 myHiddenAdj = client.hiddenAdj;
13942 } else {
13943 myHiddenAdj = FOREGROUND_APP_ADJ;
13944 }
13945 }
13946 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013947 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013948 if (adj > clientAdj) {
13949 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013950 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013951 if (!client.hidden) {
13952 app.hidden = false;
13953 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013954 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013955 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13956 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013957 app.adjSource = client;
13958 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013959 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013960 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13961 schedGroup = Process.THREAD_GROUP_DEFAULT;
13962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013963 }
13964 }
13965 // If the provider has external (non-framework) process
13966 // dependencies, ensure that its adjustment is at least
13967 // FOREGROUND_APP_ADJ.
13968 if (cpr.externals != 0) {
13969 if (adj > FOREGROUND_APP_ADJ) {
13970 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013971 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013972 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013973 app.adjType = "provider";
13974 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013975 }
13976 }
13977 }
13978 }
13979
13980 app.curRawAdj = adj;
13981
Joe Onorato8a9b2202010-02-26 18:56:32 -080013982 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013983 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13984 if (adj > app.maxAdj) {
13985 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013986 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13987 schedGroup = Process.THREAD_GROUP_DEFAULT;
13988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013989 }
13990
13991 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013992 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013994 return adj;
13995 }
13996
13997 /**
13998 * Ask a given process to GC right now.
13999 */
14000 final void performAppGcLocked(ProcessRecord app) {
14001 try {
14002 app.lastRequestedGc = SystemClock.uptimeMillis();
14003 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014004 if (app.reportLowMemory) {
14005 app.reportLowMemory = false;
14006 app.thread.scheduleLowMemory();
14007 } else {
14008 app.thread.processInBackground();
14009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014010 }
14011 } catch (Exception e) {
14012 // whatever.
14013 }
14014 }
14015
14016 /**
14017 * Returns true if things are idle enough to perform GCs.
14018 */
Josh Bartel7f208742010-02-25 11:01:44 -060014019 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014020 return mParallelBroadcasts.size() == 0
14021 && mOrderedBroadcasts.size() == 0
14022 && (mSleeping || (mResumedActivity != null &&
14023 mResumedActivity.idle));
14024 }
14025
14026 /**
14027 * Perform GCs on all processes that are waiting for it, but only
14028 * if things are idle.
14029 */
14030 final void performAppGcsLocked() {
14031 final int N = mProcessesToGc.size();
14032 if (N <= 0) {
14033 return;
14034 }
Josh Bartel7f208742010-02-25 11:01:44 -060014035 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014036 while (mProcessesToGc.size() > 0) {
14037 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014038 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
14039 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14040 <= SystemClock.uptimeMillis()) {
14041 // To avoid spamming the system, we will GC processes one
14042 // at a time, waiting a few seconds between each.
14043 performAppGcLocked(proc);
14044 scheduleAppGcsLocked();
14045 return;
14046 } else {
14047 // It hasn't been long enough since we last GCed this
14048 // process... put it in the list to wait for its time.
14049 addProcessToGcListLocked(proc);
14050 break;
14051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014052 }
14053 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014054
14055 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014056 }
14057 }
14058
14059 /**
14060 * If all looks good, perform GCs on all processes waiting for them.
14061 */
14062 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014063 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014064 performAppGcsLocked();
14065 return;
14066 }
14067 // Still not idle, wait some more.
14068 scheduleAppGcsLocked();
14069 }
14070
14071 /**
14072 * Schedule the execution of all pending app GCs.
14073 */
14074 final void scheduleAppGcsLocked() {
14075 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014076
14077 if (mProcessesToGc.size() > 0) {
14078 // Schedule a GC for the time to the next process.
14079 ProcessRecord proc = mProcessesToGc.get(0);
14080 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14081
14082 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14083 long now = SystemClock.uptimeMillis();
14084 if (when < (now+GC_TIMEOUT)) {
14085 when = now + GC_TIMEOUT;
14086 }
14087 mHandler.sendMessageAtTime(msg, when);
14088 }
14089 }
14090
14091 /**
14092 * Add a process to the array of processes waiting to be GCed. Keeps the
14093 * list in sorted order by the last GC time. The process can't already be
14094 * on the list.
14095 */
14096 final void addProcessToGcListLocked(ProcessRecord proc) {
14097 boolean added = false;
14098 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14099 if (mProcessesToGc.get(i).lastRequestedGc <
14100 proc.lastRequestedGc) {
14101 added = true;
14102 mProcessesToGc.add(i+1, proc);
14103 break;
14104 }
14105 }
14106 if (!added) {
14107 mProcessesToGc.add(0, proc);
14108 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014109 }
14110
14111 /**
14112 * Set up to ask a process to GC itself. This will either do it
14113 * immediately, or put it on the list of processes to gc the next
14114 * time things are idle.
14115 */
14116 final void scheduleAppGcLocked(ProcessRecord app) {
14117 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014118 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014119 return;
14120 }
14121 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014122 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014123 scheduleAppGcsLocked();
14124 }
14125 }
14126
14127 private final boolean updateOomAdjLocked(
14128 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14129 app.hiddenAdj = hiddenAdj;
14130
14131 if (app.thread == null) {
14132 return true;
14133 }
14134
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014135 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014136
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014137 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014138 if (app.curRawAdj != app.setRawAdj) {
14139 if (app.curRawAdj > FOREGROUND_APP_ADJ
14140 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14141 // If this app is transitioning from foreground to
14142 // non-foreground, have it do a gc.
14143 scheduleAppGcLocked(app);
14144 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14145 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14146 // Likewise do a gc when an app is moving in to the
14147 // background (such as a service stopping).
14148 scheduleAppGcLocked(app);
14149 }
14150 app.setRawAdj = app.curRawAdj;
14151 }
14152 if (adj != app.setAdj) {
14153 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014154 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014155 TAG, "Set app " + app.processName +
14156 " oom adj to " + adj);
14157 app.setAdj = adj;
14158 } else {
14159 return false;
14160 }
14161 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014162 if (app.setSchedGroup != app.curSchedGroup) {
14163 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014164 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014165 "Setting process group of " + app.processName
14166 + " to " + app.curSchedGroup);
14167 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014168 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014169 try {
14170 Process.setProcessGroup(app.pid, app.curSchedGroup);
14171 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014172 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014173 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014174 e.printStackTrace();
14175 } finally {
14176 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014177 }
14178 }
14179 if (false) {
14180 if (app.thread != null) {
14181 try {
14182 app.thread.setSchedulingGroup(app.curSchedGroup);
14183 } catch (RemoteException e) {
14184 }
14185 }
14186 }
14187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014188 }
14189
14190 return true;
14191 }
14192
14193 private final HistoryRecord resumedAppLocked() {
14194 HistoryRecord resumedActivity = mResumedActivity;
14195 if (resumedActivity == null || resumedActivity.app == null) {
14196 resumedActivity = mPausingActivity;
14197 if (resumedActivity == null || resumedActivity.app == null) {
14198 resumedActivity = topRunningActivityLocked(null);
14199 }
14200 }
14201 return resumedActivity;
14202 }
14203
14204 private final boolean updateOomAdjLocked(ProcessRecord app) {
14205 final HistoryRecord TOP_ACT = resumedAppLocked();
14206 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14207 int curAdj = app.curAdj;
14208 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14209 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14210
14211 mAdjSeq++;
14212
14213 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14214 if (res) {
14215 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14216 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14217 if (nowHidden != wasHidden) {
14218 // Changed to/from hidden state, so apps after it in the LRU
14219 // list may also be changed.
14220 updateOomAdjLocked();
14221 }
14222 }
14223 return res;
14224 }
14225
14226 private final boolean updateOomAdjLocked() {
14227 boolean didOomAdj = true;
14228 final HistoryRecord TOP_ACT = resumedAppLocked();
14229 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14230
14231 if (false) {
14232 RuntimeException e = new RuntimeException();
14233 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014234 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014235 }
14236
14237 mAdjSeq++;
14238
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014239 // Let's determine how many processes we have running vs.
14240 // how many slots we have for background processes; we may want
14241 // to put multiple processes in a slot of there are enough of
14242 // them.
14243 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14244 int factor = (mLruProcesses.size()-4)/numSlots;
14245 if (factor < 1) factor = 1;
14246 int step = 0;
14247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014248 // First try updating the OOM adjustment for each of the
14249 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014250 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014251 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14252 while (i > 0) {
14253 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014254 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014255 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014256 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014257 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014258 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014259 step++;
14260 if (step >= factor) {
14261 step = 0;
14262 curHiddenAdj++;
14263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014264 }
14265 } else {
14266 didOomAdj = false;
14267 }
14268 }
14269
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014270 // If we return false, we will fall back on killing processes to
14271 // have a fixed limit. Do this if a limit has been requested; else
14272 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014273 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14274 }
14275
14276 private final void trimApplications() {
14277 synchronized (this) {
14278 int i;
14279
14280 // First remove any unused application processes whose package
14281 // has been removed.
14282 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14283 final ProcessRecord app = mRemovedProcesses.get(i);
14284 if (app.activities.size() == 0
14285 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014286 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014287 TAG, "Exiting empty application process "
14288 + app.processName + " ("
14289 + (app.thread != null ? app.thread.asBinder() : null)
14290 + ")\n");
14291 if (app.pid > 0 && app.pid != MY_PID) {
14292 Process.killProcess(app.pid);
14293 } else {
14294 try {
14295 app.thread.scheduleExit();
14296 } catch (Exception e) {
14297 // Ignore exceptions.
14298 }
14299 }
14300 cleanUpApplicationRecordLocked(app, false, -1);
14301 mRemovedProcesses.remove(i);
14302
14303 if (app.persistent) {
14304 if (app.persistent) {
14305 addAppLocked(app.info);
14306 }
14307 }
14308 }
14309 }
14310
14311 // Now try updating the OOM adjustment for each of the
14312 // application processes based on their current state.
14313 // If the setOomAdj() API is not supported, then go with our
14314 // back-up plan...
14315 if (!updateOomAdjLocked()) {
14316
14317 // Count how many processes are running services.
14318 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014319 for (i=mLruProcesses.size()-1; i>=0; i--) {
14320 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014321
14322 if (app.persistent || app.services.size() != 0
14323 || app.curReceiver != null
14324 || app.persistentActivities > 0) {
14325 // Don't count processes holding services against our
14326 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014327 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014328 TAG, "Not trimming app " + app + " with services: "
14329 + app.services);
14330 numServiceProcs++;
14331 }
14332 }
14333
14334 int curMaxProcs = mProcessLimit;
14335 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14336 if (mAlwaysFinishActivities) {
14337 curMaxProcs = 1;
14338 }
14339 curMaxProcs += numServiceProcs;
14340
14341 // Quit as many processes as we can to get down to the desired
14342 // process count. First remove any processes that no longer
14343 // have activites running in them.
14344 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014345 i<mLruProcesses.size()
14346 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014347 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014348 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014349 // Quit an application only if it is not currently
14350 // running any activities.
14351 if (!app.persistent && app.activities.size() == 0
14352 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014353 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014354 TAG, "Exiting empty application process "
14355 + app.processName + " ("
14356 + (app.thread != null ? app.thread.asBinder() : null)
14357 + ")\n");
14358 if (app.pid > 0 && app.pid != MY_PID) {
14359 Process.killProcess(app.pid);
14360 } else {
14361 try {
14362 app.thread.scheduleExit();
14363 } catch (Exception e) {
14364 // Ignore exceptions.
14365 }
14366 }
14367 // todo: For now we assume the application is not buggy
14368 // or evil, and will quit as a result of our request.
14369 // Eventually we need to drive this off of the death
14370 // notification, and kill the process if it takes too long.
14371 cleanUpApplicationRecordLocked(app, false, i);
14372 i--;
14373 }
14374 }
14375
14376 // If we still have too many processes, now from the least
14377 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014378 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014379 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014380 " of " + curMaxProcs + " processes");
14381 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014382 i<mLruProcesses.size()
14383 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014384 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014385 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014386 // Quit the application only if we have a state saved for
14387 // all of its activities.
14388 boolean canQuit = !app.persistent && app.curReceiver == null
14389 && app.services.size() == 0
14390 && app.persistentActivities == 0;
14391 int NUMA = app.activities.size();
14392 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014393 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014394 TAG, "Looking to quit " + app.processName);
14395 for (j=0; j<NUMA && canQuit; j++) {
14396 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014397 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014398 TAG, " " + r.intent.getComponent().flattenToShortString()
14399 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14400 canQuit = (r.haveState || !r.stateNotNeeded)
14401 && !r.visible && r.stopped;
14402 }
14403 if (canQuit) {
14404 // Finish all of the activities, and then the app itself.
14405 for (j=0; j<NUMA; j++) {
14406 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14407 if (!r.finishing) {
14408 destroyActivityLocked(r, false);
14409 }
14410 r.resultTo = null;
14411 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014412 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014413 + app.processName + " ("
14414 + (app.thread != null ? app.thread.asBinder() : null)
14415 + ")\n");
14416 if (app.pid > 0 && app.pid != MY_PID) {
14417 Process.killProcess(app.pid);
14418 } else {
14419 try {
14420 app.thread.scheduleExit();
14421 } catch (Exception e) {
14422 // Ignore exceptions.
14423 }
14424 }
14425 // todo: For now we assume the application is not buggy
14426 // or evil, and will quit as a result of our request.
14427 // Eventually we need to drive this off of the death
14428 // notification, and kill the process if it takes too long.
14429 cleanUpApplicationRecordLocked(app, false, i);
14430 i--;
14431 //dump();
14432 }
14433 }
14434
14435 }
14436
14437 int curMaxActivities = MAX_ACTIVITIES;
14438 if (mAlwaysFinishActivities) {
14439 curMaxActivities = 1;
14440 }
14441
14442 // Finally, if there are too many activities now running, try to
14443 // finish as many as we can to get back down to the limit.
14444 for ( i=0;
14445 i<mLRUActivities.size()
14446 && mLRUActivities.size() > curMaxActivities;
14447 i++) {
14448 final HistoryRecord r
14449 = (HistoryRecord)mLRUActivities.get(i);
14450
14451 // We can finish this one if we have its icicle saved and
14452 // it is not persistent.
14453 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14454 && r.stopped && !r.persistent && !r.finishing) {
14455 final int origSize = mLRUActivities.size();
14456 destroyActivityLocked(r, true);
14457
14458 // This will remove it from the LRU list, so keep
14459 // our index at the same value. Note that this check to
14460 // see if the size changes is just paranoia -- if
14461 // something unexpected happens, we don't want to end up
14462 // in an infinite loop.
14463 if (origSize > mLRUActivities.size()) {
14464 i--;
14465 }
14466 }
14467 }
14468 }
14469 }
14470
14471 /** This method sends the specified signal to each of the persistent apps */
14472 public void signalPersistentProcesses(int sig) throws RemoteException {
14473 if (sig != Process.SIGNAL_USR1) {
14474 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14475 }
14476
14477 synchronized (this) {
14478 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14479 != PackageManager.PERMISSION_GRANTED) {
14480 throw new SecurityException("Requires permission "
14481 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14482 }
14483
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014484 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14485 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014486 if (r.thread != null && r.persistent) {
14487 Process.sendSignal(r.pid, sig);
14488 }
14489 }
14490 }
14491 }
14492
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014493 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014494 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014495
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014496 try {
14497 synchronized (this) {
14498 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14499 // its own permission.
14500 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14501 != PackageManager.PERMISSION_GRANTED) {
14502 throw new SecurityException("Requires permission "
14503 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014504 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014505
14506 if (start && fd == null) {
14507 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014508 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014509
14510 ProcessRecord proc = null;
14511 try {
14512 int pid = Integer.parseInt(process);
14513 synchronized (mPidsSelfLocked) {
14514 proc = mPidsSelfLocked.get(pid);
14515 }
14516 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014517 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014518
14519 if (proc == null) {
14520 HashMap<String, SparseArray<ProcessRecord>> all
14521 = mProcessNames.getMap();
14522 SparseArray<ProcessRecord> procs = all.get(process);
14523 if (procs != null && procs.size() > 0) {
14524 proc = procs.valueAt(0);
14525 }
14526 }
14527
14528 if (proc == null || proc.thread == null) {
14529 throw new IllegalArgumentException("Unknown process: " + process);
14530 }
14531
14532 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14533 if (isSecure) {
14534 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14535 throw new SecurityException("Process not debuggable: " + proc);
14536 }
14537 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014538
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014539 proc.thread.profilerControl(start, path, fd);
14540 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014541 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014542 }
14543 } catch (RemoteException e) {
14544 throw new IllegalStateException("Process disappeared");
14545 } finally {
14546 if (fd != null) {
14547 try {
14548 fd.close();
14549 } catch (IOException e) {
14550 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014551 }
14552 }
14553 }
14554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014555 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14556 public void monitor() {
14557 synchronized (this) { }
14558 }
14559}