blob: f5a8119c9295c647ec5b954cda4af5b3fb660665 [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;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020055import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.content.Intent;
57import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070058import android.content.IIntentReceiver;
59import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070060import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.content.pm.ActivityInfo;
62import android.content.pm.ApplicationInfo;
63import android.content.pm.ConfigurationInfo;
64import android.content.pm.IPackageDataObserver;
65import android.content.pm.IPackageManager;
66import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080067import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070069import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.content.pm.ProviderInfo;
71import android.content.pm.ResolveInfo;
72import android.content.pm.ServiceInfo;
73import android.content.res.Configuration;
74import android.graphics.Bitmap;
75import android.net.Uri;
76import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080077import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080078import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070079import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080080import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080082import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083import android.os.FileUtils;
84import android.os.Handler;
85import android.os.IBinder;
86import android.os.IPermissionController;
87import android.os.Looper;
88import android.os.Message;
89import android.os.Parcel;
90import android.os.ParcelFileDescriptor;
91import android.os.PowerManager;
92import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070093import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.RemoteException;
95import android.os.ServiceManager;
96import android.os.SystemClock;
97import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.util.Config;
100import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800101import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800102import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.util.PrintWriterPrinter;
104import android.util.SparseArray;
105import android.view.Gravity;
106import android.view.LayoutInflater;
107import android.view.View;
108import android.view.WindowManager;
109import android.view.WindowManagerPolicy;
110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import java.io.File;
112import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200114import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800115import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116import java.io.PrintWriter;
117import java.lang.IllegalStateException;
118import java.lang.ref.WeakReference;
119import java.util.ArrayList;
120import java.util.HashMap;
121import java.util.HashSet;
122import java.util.Iterator;
123import java.util.List;
124import java.util.Locale;
125import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700126import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700127import java.util.concurrent.atomic.AtomicBoolean;
128import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129
130public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
131 static final String TAG = "ActivityManager";
132 static final boolean DEBUG = false;
133 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
134 static final boolean DEBUG_SWITCH = localLOGV || false;
135 static final boolean DEBUG_TASKS = localLOGV || false;
136 static final boolean DEBUG_PAUSE = localLOGV || false;
137 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
138 static final boolean DEBUG_TRANSITION = localLOGV || false;
139 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700140 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 static final boolean DEBUG_SERVICE = localLOGV || false;
142 static final boolean DEBUG_VISBILITY = localLOGV || false;
143 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700144 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800145 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700147 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700148 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700149 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 static final boolean VALIDATE_TOKENS = false;
151 static final boolean SHOW_ACTIVITY_START_TIME = true;
152
153 // Control over CPU and battery monitoring.
154 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
155 static final boolean MONITOR_CPU_USAGE = true;
156 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
157 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
158 static final boolean MONITOR_THREAD_CPU_USAGE = false;
159
Dianne Hackborn1655be42009-05-08 14:29:01 -0700160 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700161 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 private static final String SYSTEM_SECURE = "ro.secure";
164
165 // This is the maximum number of application processes we would like
166 // to have running. Due to the asynchronous nature of things, we can
167 // temporarily go beyond this limit.
168 static final int MAX_PROCESSES = 2;
169
170 // Set to false to leave processes running indefinitely, relying on
171 // the kernel killing them as resources are required.
172 static final boolean ENFORCE_PROCESS_LIMIT = false;
173
174 // This is the maximum number of activities that we would like to have
175 // running at a given time.
176 static final int MAX_ACTIVITIES = 20;
177
178 // Maximum number of recent tasks that we can remember.
179 static final int MAX_RECENT_TASKS = 20;
180
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700181 // Amount of time after a call to stopAppSwitches() during which we will
182 // prevent further untrusted switches from happening.
183 static final long APP_SWITCH_DELAY_TIME = 5*1000;
184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 // How long until we reset a task when the user returns to it. Currently
186 // 30 minutes.
187 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
188
189 // Set to true to disable the icon that is shown while a new activity
190 // is being started.
191 static final boolean SHOW_APP_STARTING_ICON = true;
192
193 // How long we wait until giving up on the last activity to pause. This
194 // is short because it directly impacts the responsiveness of starting the
195 // next activity.
196 static final int PAUSE_TIMEOUT = 500;
197
198 /**
199 * How long we can hold the launch wake lock before giving up.
200 */
201 static final int LAUNCH_TIMEOUT = 10*1000;
202
203 // How long we wait for a launched process to attach to the activity manager
204 // before we decide it's never going to come up for real.
205 static final int PROC_START_TIMEOUT = 10*1000;
206
207 // How long we wait until giving up on the last activity telling us it
208 // is idle.
209 static final int IDLE_TIMEOUT = 10*1000;
210
211 // How long to wait after going idle before forcing apps to GC.
212 static final int GC_TIMEOUT = 5*1000;
213
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700214 // The minimum amount of time between successive GC requests for a process.
215 static final int GC_MIN_INTERVAL = 60*1000;
216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 // How long we wait until giving up on an activity telling us it has
218 // finished destroying itself.
219 static final int DESTROY_TIMEOUT = 10*1000;
220
221 // How long we allow a receiver to run before giving up on it.
222 static final int BROADCAST_TIMEOUT = 10*1000;
223
224 // How long we wait for a service to finish executing.
225 static final int SERVICE_TIMEOUT = 20*1000;
226
227 // How long a service needs to be running until restarting its process
228 // is no longer considered to be a relaunch of the service.
229 static final int SERVICE_RESTART_DURATION = 5*1000;
230
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700231 // How long a service needs to be running until it will start back at
232 // SERVICE_RESTART_DURATION after being killed.
233 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
234
235 // Multiplying factor to increase restart duration time by, for each time
236 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
237 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
238
239 // The minimum amount of time between restarting services that we allow.
240 // That is, when multiple services are restarting, we won't allow each
241 // to restart less than this amount of time from the last one.
242 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 // Maximum amount of time for there to be no activity on a service before
245 // we consider it non-essential and allow its process to go on the
246 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700247 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248
249 // How long we wait until we timeout on key dispatching.
250 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
251
252 // The minimum time we allow between crashes, for us to consider this
253 // application to be bad and stop and its services and reject broadcasts.
254 static final int MIN_CRASH_INTERVAL = 60*1000;
255
256 // How long we wait until we timeout on key dispatching during instrumentation.
257 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
258
259 // OOM adjustments for processes in various states:
260
261 // This is a process without anything currently running in it. Definitely
262 // the first to go! Value set in system/rootdir/init.rc on startup.
263 // This value is initalized in the constructor, careful when refering to
264 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800265 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266
267 // This is a process only hosting activities that are not visible,
268 // so it can be killed without any disruption. Value set in
269 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800270 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 static int HIDDEN_APP_MIN_ADJ;
272
The Android Open Source Project4df24232009-03-05 14:34:35 -0800273 // This is a process holding the home application -- we want to try
274 // avoiding killing it, even if it would normally be in the background,
275 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800276 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800277
Christopher Tate6fa95972009-06-05 18:43:55 -0700278 // This is a process currently hosting a backup operation. Killing it
279 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800280 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 // This is a process holding a secondary server -- killing it will not
283 // have much of an impact as far as the user is concerned. Value set in
284 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800285 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286
287 // This is a process only hosting activities that are visible to the
288 // user, so we'd prefer they don't disappear. Value set in
289 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800290 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
292 // This is the process running the current foreground app. We'd really
293 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800294 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295
296 // This is a process running a core server, such as telephony. Definitely
297 // don't want to kill it, but doing so is not completely fatal.
298 static final int CORE_SERVER_ADJ = -12;
299
300 // The system process runs at the default adjustment.
301 static final int SYSTEM_ADJ = -16;
302
303 // Memory pages are 4K.
304 static final int PAGE_SIZE = 4*1024;
305
306 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int EMPTY_APP_MEM;
308 static final int HIDDEN_APP_MEM;
309 static final int HOME_APP_MEM;
310 static final int BACKUP_APP_MEM;
311 static final int SECONDARY_SERVER_MEM;
312 static final int VISIBLE_APP_MEM;
313 static final int FOREGROUND_APP_MEM;
314
315 // The minimum number of hidden apps we want to be able to keep around,
316 // without empty apps being able to push them out of memory.
317 static final int MIN_HIDDEN_APPS = 2;
318
Dianne Hackborn8633e682010-04-22 16:03:41 -0700319 // The maximum number of hidden processes we will keep around before
320 // killing them; this is just a control to not let us go too crazy with
321 // keeping around processes on devices with large amounts of RAM.
322 static final int MAX_HIDDEN_APPS = 15;
323
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800324 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700325 // been idle for less than 15 seconds.
326 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800327
328 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700329 // been idle for less than 120 seconds.
330 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800331
332 static {
333 // These values are set in system/rootdir/init.rc on startup.
334 FOREGROUND_APP_ADJ =
335 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
336 VISIBLE_APP_ADJ =
337 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
338 SECONDARY_SERVER_ADJ =
339 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
340 BACKUP_APP_ADJ =
341 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
342 HOME_APP_ADJ =
343 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
344 HIDDEN_APP_MIN_ADJ =
345 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
346 EMPTY_APP_ADJ =
347 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
348 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
349 FOREGROUND_APP_MEM =
350 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
351 VISIBLE_APP_MEM =
352 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
353 SECONDARY_SERVER_MEM =
354 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
355 BACKUP_APP_MEM =
356 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
357 HOME_APP_MEM =
358 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
359 HIDDEN_APP_MEM =
360 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
361 EMPTY_APP_MEM =
362 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364
Dan Egnor42471dd2010-01-07 17:25:22 -0800365 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366
367 static final String[] EMPTY_STRING_ARRAY = new String[0];
368
369 enum ActivityState {
370 INITIALIZING,
371 RESUMED,
372 PAUSING,
373 PAUSED,
374 STOPPING,
375 STOPPED,
376 FINISHING,
377 DESTROYING,
378 DESTROYED
379 }
380
381 /**
382 * The back history of all previous (and possibly still
383 * running) activities. It contains HistoryRecord objects.
384 */
385 final ArrayList mHistory = new ArrayList();
386
387 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700388 * Description of a request to start a new activity, which has been held
389 * due to app switches being disabled.
390 */
391 class PendingActivityLaunch {
392 HistoryRecord r;
393 HistoryRecord sourceRecord;
394 Uri[] grantedUriPermissions;
395 int grantedMode;
396 boolean onlyIfNeeded;
397 }
398
399 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
400 = new ArrayList<PendingActivityLaunch>();
401
402 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800403 * List of people waiting to find out about the next launched activity.
404 */
405 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
406 = new ArrayList<IActivityManager.WaitResult>();
407
408 /**
409 * List of people waiting to find out about the next visible activity.
410 */
411 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
412 = new ArrayList<IActivityManager.WaitResult>();
413
414 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 * List of all active broadcasts that are to be executed immediately
416 * (without waiting for another broadcast to finish). Currently this only
417 * contains broadcasts to registered receivers, to avoid spinning up
418 * a bunch of processes to execute IntentReceiver components.
419 */
420 final ArrayList<BroadcastRecord> mParallelBroadcasts
421 = new ArrayList<BroadcastRecord>();
422
423 /**
424 * List of all active broadcasts that are to be executed one at a time.
425 * The object at the top of the list is the currently activity broadcasts;
426 * those after it are waiting for the top to finish..
427 */
428 final ArrayList<BroadcastRecord> mOrderedBroadcasts
429 = new ArrayList<BroadcastRecord>();
430
431 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800432 * Historical data of past broadcasts, for debugging.
433 */
434 static final int MAX_BROADCAST_HISTORY = 100;
435 final BroadcastRecord[] mBroadcastHistory
436 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
437
438 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 * Set when we current have a BROADCAST_INTENT_MSG in flight.
440 */
441 boolean mBroadcastsScheduled = false;
442
443 /**
444 * Set to indicate whether to issue an onUserLeaving callback when a
445 * newly launched activity is being brought in front of us.
446 */
447 boolean mUserLeaving = false;
448
449 /**
450 * When we are in the process of pausing an activity, before starting the
451 * next one, this variable holds the activity that is currently being paused.
452 */
453 HistoryRecord mPausingActivity = null;
454
455 /**
456 * Current activity that is resumed, or null if there is none.
457 */
458 HistoryRecord mResumedActivity = null;
459
460 /**
461 * Activity we have told the window manager to have key focus.
462 */
463 HistoryRecord mFocusedActivity = null;
464
465 /**
466 * This is the last activity that we put into the paused state. This is
467 * used to determine if we need to do an activity transition while sleeping,
468 * when we normally hold the top activity paused.
469 */
470 HistoryRecord mLastPausedActivity = null;
471
472 /**
473 * List of activities that are waiting for a new activity
474 * to become visible before completing whatever operation they are
475 * supposed to do.
476 */
477 final ArrayList mWaitingVisibleActivities = new ArrayList();
478
479 /**
480 * List of activities that are ready to be stopped, but waiting
481 * for the next activity to settle down before doing so. It contains
482 * HistoryRecord objects.
483 */
484 final ArrayList<HistoryRecord> mStoppingActivities
485 = new ArrayList<HistoryRecord>();
486
487 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700488 * Animations that for the current transition have requested not to
489 * be considered for the transition animation.
490 */
491 final ArrayList<HistoryRecord> mNoAnimActivities
492 = new ArrayList<HistoryRecord>();
493
494 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 * List of intents that were used to start the most recent tasks.
496 */
497 final ArrayList<TaskRecord> mRecentTasks
498 = new ArrayList<TaskRecord>();
499
500 /**
501 * List of activities that are ready to be finished, but waiting
502 * for the previous activity to settle down before doing so. It contains
503 * HistoryRecord objects.
504 */
505 final ArrayList mFinishingActivities = new ArrayList();
506
507 /**
508 * All of the applications we currently have running organized by name.
509 * The keys are strings of the application package name (as
510 * returned by the package manager), and the keys are ApplicationRecord
511 * objects.
512 */
513 final ProcessMap<ProcessRecord> mProcessNames
514 = new ProcessMap<ProcessRecord>();
515
516 /**
517 * The last time that various processes have crashed.
518 */
519 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
520
521 /**
522 * Set of applications that we consider to be bad, and will reject
523 * incoming broadcasts from (which the user has no control over).
524 * Processes are added to this set when they have crashed twice within
525 * a minimum amount of time; they are removed from it when they are
526 * later restarted (hopefully due to some user action). The value is the
527 * time it was added to the list.
528 */
529 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
530
531 /**
532 * All of the processes we currently have running organized by pid.
533 * The keys are the pid running the application.
534 *
535 * <p>NOTE: This object is protected by its own lock, NOT the global
536 * activity manager lock!
537 */
538 final SparseArray<ProcessRecord> mPidsSelfLocked
539 = new SparseArray<ProcessRecord>();
540
541 /**
542 * All of the processes that have been forced to be foreground. The key
543 * is the pid of the caller who requested it (we hold a death
544 * link on it).
545 */
546 abstract class ForegroundToken implements IBinder.DeathRecipient {
547 int pid;
548 IBinder token;
549 }
550 final SparseArray<ForegroundToken> mForegroundProcesses
551 = new SparseArray<ForegroundToken>();
552
553 /**
554 * List of records for processes that someone had tried to start before the
555 * system was ready. We don't start them at that point, but ensure they
556 * are started by the time booting is complete.
557 */
558 final ArrayList<ProcessRecord> mProcessesOnHold
559 = new ArrayList<ProcessRecord>();
560
561 /**
562 * List of records for processes that we have started and are waiting
563 * for them to call back. This is really only needed when running in
564 * single processes mode, in which case we do not have a unique pid for
565 * each process.
566 */
567 final ArrayList<ProcessRecord> mStartingProcesses
568 = new ArrayList<ProcessRecord>();
569
570 /**
571 * List of persistent applications that are in the process
572 * of being started.
573 */
574 final ArrayList<ProcessRecord> mPersistentStartingProcesses
575 = new ArrayList<ProcessRecord>();
576
577 /**
578 * Processes that are being forcibly torn down.
579 */
580 final ArrayList<ProcessRecord> mRemovedProcesses
581 = new ArrayList<ProcessRecord>();
582
583 /**
584 * List of running applications, sorted by recent usage.
585 * The first entry in the list is the least recently used.
586 * It contains ApplicationRecord objects. This list does NOT include
587 * any persistent application records (since we never want to exit them).
588 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800589 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 = new ArrayList<ProcessRecord>();
591
592 /**
593 * List of processes that should gc as soon as things are idle.
594 */
595 final ArrayList<ProcessRecord> mProcessesToGc
596 = new ArrayList<ProcessRecord>();
597
598 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800599 * This is the process holding what we currently consider to be
600 * the "home" activity.
601 */
602 private ProcessRecord mHomeProcess;
603
604 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 * List of running activities, sorted by recent usage.
606 * The first entry in the list is the least recently used.
607 * It contains HistoryRecord objects.
608 */
609 private final ArrayList mLRUActivities = new ArrayList();
610
611 /**
612 * Set of PendingResultRecord objects that are currently active.
613 */
614 final HashSet mPendingResultRecords = new HashSet();
615
616 /**
617 * Set of IntentSenderRecord objects that are currently active.
618 */
619 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
620 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
621
622 /**
623 * Intent broadcast that we have tried to start, but are
624 * waiting for its application's process to be created. We only
625 * need one (instead of a list) because we always process broadcasts
626 * one at a time, so no others can be started while waiting for this
627 * one.
628 */
629 BroadcastRecord mPendingBroadcast = null;
630
631 /**
632 * Keeps track of all IIntentReceivers that have been registered for
633 * broadcasts. Hash keys are the receiver IBinder, hash value is
634 * a ReceiverList.
635 */
636 final HashMap mRegisteredReceivers = new HashMap();
637
638 /**
639 * Resolver for broadcast intents to registered receivers.
640 * Holds BroadcastFilter (subclass of IntentFilter).
641 */
642 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
643 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
644 @Override
645 protected boolean allowFilterResult(
646 BroadcastFilter filter, List<BroadcastFilter> dest) {
647 IBinder target = filter.receiverList.receiver.asBinder();
648 for (int i=dest.size()-1; i>=0; i--) {
649 if (dest.get(i).receiverList.receiver.asBinder() == target) {
650 return false;
651 }
652 }
653 return true;
654 }
655 };
656
657 /**
658 * State of all active sticky broadcasts. Keys are the action of the
659 * sticky Intent, values are an ArrayList of all broadcasted intents with
660 * that action (which should usually be one).
661 */
662 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
663 new HashMap<String, ArrayList<Intent>>();
664
665 /**
666 * All currently running services.
667 */
668 final HashMap<ComponentName, ServiceRecord> mServices =
669 new HashMap<ComponentName, ServiceRecord>();
670
671 /**
672 * All currently running services indexed by the Intent used to start them.
673 */
674 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
675 new HashMap<Intent.FilterComparison, ServiceRecord>();
676
677 /**
678 * All currently bound service connections. Keys are the IBinder of
679 * the client's IServiceConnection.
680 */
681 final HashMap<IBinder, ConnectionRecord> mServiceConnections
682 = new HashMap<IBinder, ConnectionRecord>();
683
684 /**
685 * List of services that we have been asked to start,
686 * but haven't yet been able to. It is used to hold start requests
687 * while waiting for their corresponding application thread to get
688 * going.
689 */
690 final ArrayList<ServiceRecord> mPendingServices
691 = new ArrayList<ServiceRecord>();
692
693 /**
694 * List of services that are scheduled to restart following a crash.
695 */
696 final ArrayList<ServiceRecord> mRestartingServices
697 = new ArrayList<ServiceRecord>();
698
699 /**
700 * List of services that are in the process of being stopped.
701 */
702 final ArrayList<ServiceRecord> mStoppingServices
703 = new ArrayList<ServiceRecord>();
704
705 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700706 * Backup/restore process management
707 */
708 String mBackupAppName = null;
709 BackupRecord mBackupTarget = null;
710
711 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 * List of PendingThumbnailsRecord objects of clients who are still
713 * waiting to receive all of the thumbnails for a task.
714 */
715 final ArrayList mPendingThumbnails = new ArrayList();
716
717 /**
718 * List of HistoryRecord objects that have been finished and must
719 * still report back to a pending thumbnail receiver.
720 */
721 final ArrayList mCancelledThumbnails = new ArrayList();
722
723 /**
724 * All of the currently running global content providers. Keys are a
725 * string containing the provider name and values are a
726 * ContentProviderRecord object containing the data about it. Note
727 * that a single provider may be published under multiple names, so
728 * there may be multiple entries here for a single one in mProvidersByClass.
729 */
730 final HashMap mProvidersByName = new HashMap();
731
732 /**
733 * All of the currently running global content providers. Keys are a
734 * string containing the provider's implementation class and values are a
735 * ContentProviderRecord object containing the data about it.
736 */
737 final HashMap mProvidersByClass = new HashMap();
738
739 /**
740 * List of content providers who have clients waiting for them. The
741 * application is currently being launched and the provider will be
742 * removed from this list once it is published.
743 */
744 final ArrayList mLaunchingProviders = new ArrayList();
745
746 /**
747 * Global set of specific Uri permissions that have been granted.
748 */
749 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
750 = new SparseArray<HashMap<Uri, UriPermission>>();
751
752 /**
753 * Thread-local storage used to carry caller permissions over through
754 * indirect content-provider access.
755 * @see #ActivityManagerService.openContentUri()
756 */
757 private class Identity {
758 public int pid;
759 public int uid;
760
761 Identity(int _pid, int _uid) {
762 pid = _pid;
763 uid = _uid;
764 }
765 }
766 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
767
768 /**
769 * All information we have collected about the runtime performance of
770 * any user id that can impact battery performance.
771 */
772 final BatteryStatsService mBatteryStatsService;
773
774 /**
775 * information about component usage
776 */
777 final UsageStatsService mUsageStatsService;
778
779 /**
780 * Current configuration information. HistoryRecord objects are given
781 * a reference to this object to indicate which configuration they are
782 * currently running in, so this object must be kept immutable.
783 */
784 Configuration mConfiguration = new Configuration();
785
786 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800787 * Current sequencing integer of the configuration, for skipping old
788 * configurations.
789 */
790 int mConfigurationSeq = 0;
791
792 /**
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700793 * Set when we know we are going to be calling updateConfiguration()
794 * soon, so want to skip intermediate config checks.
795 */
796 boolean mConfigWillChange;
797
798 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700799 * Hardware-reported OpenGLES version.
800 */
801 final int GL_ES_VERSION;
802
803 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 * List of initialization arguments to pass to all processes when binding applications to them.
805 * For example, references to the commonly used services.
806 */
807 HashMap<String, IBinder> mAppBindArgs;
808
809 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700810 * Temporary to avoid allocations. Protected by main lock.
811 */
812 final StringBuilder mStringBuilder = new StringBuilder(256);
813
814 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 * Used to control how we initialize the service.
816 */
817 boolean mStartRunning = false;
818 ComponentName mTopComponent;
819 String mTopAction;
820 String mTopData;
821 boolean mSystemReady = false;
822 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700823 boolean mWaitingUpdate = false;
824 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825
826 Context mContext;
827
828 int mFactoryTest;
829
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700830 boolean mCheckedForSetup;
831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700833 * The time at which we will allow normal application switches again,
834 * after a call to {@link #stopAppSwitches()}.
835 */
836 long mAppSwitchesAllowedTime;
837
838 /**
839 * This is set to true after the first switch after mAppSwitchesAllowedTime
840 * is set; any switches after that will clear the time.
841 */
842 boolean mDidAppSwitch;
843
844 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 * Set while we are wanting to sleep, to prevent any
846 * activities from being started/resumed.
847 */
848 boolean mSleeping = false;
849
850 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700851 * Set if we are shutting down the system, similar to sleeping.
852 */
853 boolean mShuttingDown = false;
854
855 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 * Set when the system is going to sleep, until we have
857 * successfully paused the current activity and released our wake lock.
858 * At that point the system is allowed to actually sleep.
859 */
860 PowerManager.WakeLock mGoingToSleep;
861
862 /**
863 * We don't want to allow the device to go to sleep while in the process
864 * of launching an activity. This is primarily to allow alarm intent
865 * receivers to launch an activity and get that to run before the device
866 * goes back to sleep.
867 */
868 PowerManager.WakeLock mLaunchingActivity;
869
870 /**
871 * Task identifier that activities are currently being started
872 * in. Incremented each time a new task is created.
873 * todo: Replace this with a TokenSpace class that generates non-repeating
874 * integers that won't wrap.
875 */
876 int mCurTask = 1;
877
878 /**
879 * Current sequence id for oom_adj computation traversal.
880 */
881 int mAdjSeq = 0;
882
883 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700884 * Current sequence id for process LRU updating.
885 */
886 int mLruSeq = 0;
887
888 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
890 * is set, indicating the user wants processes started in such a way
891 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
892 * running in each process (thus no pre-initialized process, etc).
893 */
894 boolean mSimpleProcessManagement = false;
895
896 /**
897 * System monitoring: number of processes that died since the last
898 * N procs were started.
899 */
900 int[] mProcDeaths = new int[20];
901
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700902 /**
903 * This is set if we had to do a delayed dexopt of an app before launching
904 * it, to increasing the ANR timeouts in that case.
905 */
906 boolean mDidDexOpt;
907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 String mDebugApp = null;
909 boolean mWaitForDebugger = false;
910 boolean mDebugTransient = false;
911 String mOrigDebugApp = null;
912 boolean mOrigWaitForDebugger = false;
913 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700914 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700916 final RemoteCallbackList<IActivityWatcher> mWatchers
917 = new RemoteCallbackList<IActivityWatcher>();
918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 /**
920 * Callback of last caller to {@link #requestPss}.
921 */
922 Runnable mRequestPssCallback;
923
924 /**
925 * Remaining processes for which we are waiting results from the last
926 * call to {@link #requestPss}.
927 */
928 final ArrayList<ProcessRecord> mRequestPssList
929 = new ArrayList<ProcessRecord>();
930
931 /**
932 * Runtime statistics collection thread. This object's lock is used to
933 * protect all related state.
934 */
935 final Thread mProcessStatsThread;
936
937 /**
938 * Used to collect process stats when showing not responding dialog.
939 * Protected by mProcessStatsThread.
940 */
941 final ProcessStats mProcessStats = new ProcessStats(
942 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700943 final AtomicLong mLastCpuTime = new AtomicLong(0);
944 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 long mLastWriteTime = 0;
947
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700948 long mInitialStartTime = 0;
949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 /**
951 * Set to true after the system has finished booting.
952 */
953 boolean mBooted = false;
954
955 int mProcessLimit = 0;
956
957 WindowManagerService mWindowManager;
958
959 static ActivityManagerService mSelf;
960 static ActivityThread mSystemThread;
961
962 private final class AppDeathRecipient implements IBinder.DeathRecipient {
963 final ProcessRecord mApp;
964 final int mPid;
965 final IApplicationThread mAppThread;
966
967 AppDeathRecipient(ProcessRecord app, int pid,
968 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800969 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 TAG, "New death recipient " + this
971 + " for thread " + thread.asBinder());
972 mApp = app;
973 mPid = pid;
974 mAppThread = thread;
975 }
976
977 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800978 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 TAG, "Death received in " + this
980 + " for thread " + mAppThread.asBinder());
981 removeRequestedPss(mApp);
982 synchronized(ActivityManagerService.this) {
983 appDiedLocked(mApp, mPid, mAppThread);
984 }
985 }
986 }
987
988 static final int SHOW_ERROR_MSG = 1;
989 static final int SHOW_NOT_RESPONDING_MSG = 2;
990 static final int SHOW_FACTORY_ERROR_MSG = 3;
991 static final int UPDATE_CONFIGURATION_MSG = 4;
992 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
993 static final int WAIT_FOR_DEBUGGER_MSG = 6;
994 static final int BROADCAST_INTENT_MSG = 7;
995 static final int BROADCAST_TIMEOUT_MSG = 8;
996 static final int PAUSE_TIMEOUT_MSG = 9;
997 static final int IDLE_TIMEOUT_MSG = 10;
998 static final int IDLE_NOW_MSG = 11;
999 static final int SERVICE_TIMEOUT_MSG = 12;
1000 static final int UPDATE_TIME_ZONE = 13;
1001 static final int SHOW_UID_ERROR_MSG = 14;
1002 static final int IM_FEELING_LUCKY_MSG = 15;
1003 static final int LAUNCH_TIMEOUT_MSG = 16;
1004 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 static final int RESUME_TOP_ACTIVITY_MSG = 19;
1006 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001007 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001008 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001009 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010
1011 AlertDialog mUidAlert;
1012
1013 final Handler mHandler = new Handler() {
1014 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001015 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 //}
1017
1018 public void handleMessage(Message msg) {
1019 switch (msg.what) {
1020 case SHOW_ERROR_MSG: {
1021 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 synchronized (ActivityManagerService.this) {
1023 ProcessRecord proc = (ProcessRecord)data.get("app");
1024 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001025 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 return;
1027 }
1028 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001029 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001030 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 d.show();
1032 proc.crashDialog = d;
1033 } else {
1034 // The device is asleep, so just pretend that the user
1035 // saw a crash dialog and hit "force quit".
1036 res.set(0);
1037 }
1038 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001039
1040 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 } break;
1042 case SHOW_NOT_RESPONDING_MSG: {
1043 synchronized (ActivityManagerService.this) {
1044 HashMap data = (HashMap) msg.obj;
1045 ProcessRecord proc = (ProcessRecord)data.get("app");
1046 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001047 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 return;
1049 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001050
1051 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1052 null, null, 0, null, null, null,
1053 false, false, MY_PID, Process.SYSTEM_UID);
1054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1056 mContext, proc, (HistoryRecord)data.get("activity"));
1057 d.show();
1058 proc.anrDialog = d;
1059 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001060
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001061 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 } break;
1063 case SHOW_FACTORY_ERROR_MSG: {
1064 Dialog d = new FactoryErrorDialog(
1065 mContext, msg.getData().getCharSequence("msg"));
1066 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001067 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 } break;
1069 case UPDATE_CONFIGURATION_MSG: {
1070 final ContentResolver resolver = mContext.getContentResolver();
1071 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1072 } break;
1073 case GC_BACKGROUND_PROCESSES_MSG: {
1074 synchronized (ActivityManagerService.this) {
1075 performAppGcsIfAppropriateLocked();
1076 }
1077 } break;
1078 case WAIT_FOR_DEBUGGER_MSG: {
1079 synchronized (ActivityManagerService.this) {
1080 ProcessRecord app = (ProcessRecord)msg.obj;
1081 if (msg.arg1 != 0) {
1082 if (!app.waitedForDebugger) {
1083 Dialog d = new AppWaitingForDebuggerDialog(
1084 ActivityManagerService.this,
1085 mContext, app);
1086 app.waitDialog = d;
1087 app.waitedForDebugger = true;
1088 d.show();
1089 }
1090 } else {
1091 if (app.waitDialog != null) {
1092 app.waitDialog.dismiss();
1093 app.waitDialog = null;
1094 }
1095 }
1096 }
1097 } break;
1098 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001099 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 TAG, "Received BROADCAST_INTENT_MSG");
1101 processNextBroadcast(true);
1102 } break;
1103 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001104 if (mDidDexOpt) {
1105 mDidDexOpt = false;
1106 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1107 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1108 return;
1109 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001110 // Only process broadcast timeouts if the system is ready. That way
1111 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1112 // to do heavy lifting for system up
1113 if (mSystemReady) {
1114 broadcastTimeout();
1115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 } break;
1117 case PAUSE_TIMEOUT_MSG: {
1118 IBinder token = (IBinder)msg.obj;
1119 // We don't at this point know if the activity is fullscreen,
1120 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001121 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 activityPaused(token, null, true);
1123 } break;
1124 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001125 if (mDidDexOpt) {
1126 mDidDexOpt = false;
1127 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1128 nmsg.obj = msg.obj;
1129 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1130 return;
1131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 // We don't at this point know if the activity is fullscreen,
1133 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001134 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001135 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001136 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 } break;
1138 case DESTROY_TIMEOUT_MSG: {
1139 IBinder token = (IBinder)msg.obj;
1140 // We don't at this point know if the activity is fullscreen,
1141 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001142 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143 activityDestroyed(token);
1144 } break;
1145 case IDLE_NOW_MSG: {
1146 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001147 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 } break;
1149 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001150 if (mDidDexOpt) {
1151 mDidDexOpt = false;
1152 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1153 nmsg.obj = msg.obj;
1154 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1155 return;
1156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 serviceTimeout((ProcessRecord)msg.obj);
1158 } break;
1159 case UPDATE_TIME_ZONE: {
1160 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001161 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1162 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 if (r.thread != null) {
1164 try {
1165 r.thread.updateTimeZone();
1166 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001167 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 }
1169 }
1170 }
1171 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001172 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 case SHOW_UID_ERROR_MSG: {
1174 // XXX This is a temporary dialog, no need to localize.
1175 AlertDialog d = new BaseErrorDialog(mContext);
1176 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1177 d.setCancelable(false);
1178 d.setTitle("System UIDs Inconsistent");
1179 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001180 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1182 mUidAlert = d;
1183 d.show();
1184 } break;
1185 case IM_FEELING_LUCKY_MSG: {
1186 if (mUidAlert != null) {
1187 mUidAlert.dismiss();
1188 mUidAlert = null;
1189 }
1190 } break;
1191 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001192 if (mDidDexOpt) {
1193 mDidDexOpt = false;
1194 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1195 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1196 return;
1197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 synchronized (ActivityManagerService.this) {
1199 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001200 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 mLaunchingActivity.release();
1202 }
1203 }
1204 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 case RESUME_TOP_ACTIVITY_MSG: {
1206 synchronized (ActivityManagerService.this) {
1207 resumeTopActivityLocked(null);
1208 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001209 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001211 if (mDidDexOpt) {
1212 mDidDexOpt = false;
1213 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1214 nmsg.obj = msg.obj;
1215 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1216 return;
1217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 ProcessRecord app = (ProcessRecord)msg.obj;
1219 synchronized (ActivityManagerService.this) {
1220 processStartTimedOutLocked(app);
1221 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001222 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001223 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1224 synchronized (ActivityManagerService.this) {
1225 doPendingActivityLaunchesLocked(true);
1226 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001227 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001228 case KILL_APPLICATION_MSG: {
1229 synchronized (ActivityManagerService.this) {
1230 int uid = msg.arg1;
1231 boolean restart = (msg.arg2 == 1);
1232 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001233 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001234 }
1235 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001236 case FINALIZE_PENDING_INTENT_MSG: {
1237 ((PendingIntentRecord)msg.obj).completeFinalize();
1238 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 }
1240 }
1241 };
1242
1243 public static void setSystemProcess() {
1244 try {
1245 ActivityManagerService m = mSelf;
1246
1247 ServiceManager.addService("activity", m);
1248 ServiceManager.addService("meminfo", new MemBinder(m));
1249 if (MONITOR_CPU_USAGE) {
1250 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 ServiceManager.addService("permission", new PermissionController(m));
1253
1254 ApplicationInfo info =
1255 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001256 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001257 mSystemThread.installSystemApplicationInfo(info);
1258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 synchronized (mSelf) {
1260 ProcessRecord app = mSelf.newProcessRecordLocked(
1261 mSystemThread.getApplicationThread(), info,
1262 info.processName);
1263 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001264 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 app.maxAdj = SYSTEM_ADJ;
1266 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1267 synchronized (mSelf.mPidsSelfLocked) {
1268 mSelf.mPidsSelfLocked.put(app.pid, app);
1269 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001270 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001271 }
1272 } catch (PackageManager.NameNotFoundException e) {
1273 throw new RuntimeException(
1274 "Unable to find android system package", e);
1275 }
1276 }
1277
1278 public void setWindowManager(WindowManagerService wm) {
1279 mWindowManager = wm;
1280 }
1281
1282 public static final Context main(int factoryTest) {
1283 AThread thr = new AThread();
1284 thr.start();
1285
1286 synchronized (thr) {
1287 while (thr.mService == null) {
1288 try {
1289 thr.wait();
1290 } catch (InterruptedException e) {
1291 }
1292 }
1293 }
1294
1295 ActivityManagerService m = thr.mService;
1296 mSelf = m;
1297 ActivityThread at = ActivityThread.systemMain();
1298 mSystemThread = at;
1299 Context context = at.getSystemContext();
1300 m.mContext = context;
1301 m.mFactoryTest = factoryTest;
1302 PowerManager pm =
1303 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1304 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1305 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1306 m.mLaunchingActivity.setReferenceCounted(false);
1307
1308 m.mBatteryStatsService.publish(context);
1309 m.mUsageStatsService.publish(context);
1310
1311 synchronized (thr) {
1312 thr.mReady = true;
1313 thr.notifyAll();
1314 }
1315
1316 m.startRunning(null, null, null, null);
1317
1318 return context;
1319 }
1320
1321 public static ActivityManagerService self() {
1322 return mSelf;
1323 }
1324
1325 static class AThread extends Thread {
1326 ActivityManagerService mService;
1327 boolean mReady = false;
1328
1329 public AThread() {
1330 super("ActivityManager");
1331 }
1332
1333 public void run() {
1334 Looper.prepare();
1335
1336 android.os.Process.setThreadPriority(
1337 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1338
1339 ActivityManagerService m = new ActivityManagerService();
1340
1341 synchronized (this) {
1342 mService = m;
1343 notifyAll();
1344 }
1345
1346 synchronized (this) {
1347 while (!mReady) {
1348 try {
1349 wait();
1350 } catch (InterruptedException e) {
1351 }
1352 }
1353 }
1354
1355 Looper.loop();
1356 }
1357 }
1358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001359 static class MemBinder extends Binder {
1360 ActivityManagerService mActivityManagerService;
1361 MemBinder(ActivityManagerService activityManagerService) {
1362 mActivityManagerService = activityManagerService;
1363 }
1364
1365 @Override
1366 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1367 ActivityManagerService service = mActivityManagerService;
1368 ArrayList<ProcessRecord> procs;
1369 synchronized (mActivityManagerService) {
1370 if (args != null && args.length > 0
1371 && args[0].charAt(0) != '-') {
1372 procs = new ArrayList<ProcessRecord>();
1373 int pid = -1;
1374 try {
1375 pid = Integer.parseInt(args[0]);
1376 } catch (NumberFormatException e) {
1377
1378 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001379 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1380 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 if (proc.pid == pid) {
1382 procs.add(proc);
1383 } else if (proc.processName.equals(args[0])) {
1384 procs.add(proc);
1385 }
1386 }
1387 if (procs.size() <= 0) {
1388 pw.println("No process found for: " + args[0]);
1389 return;
1390 }
1391 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001392 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
1394 }
1395 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1396 }
1397 }
1398
1399 static class CpuBinder extends Binder {
1400 ActivityManagerService mActivityManagerService;
1401 CpuBinder(ActivityManagerService activityManagerService) {
1402 mActivityManagerService = activityManagerService;
1403 }
1404
1405 @Override
1406 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1407 synchronized (mActivityManagerService.mProcessStatsThread) {
1408 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1409 }
1410 }
1411 }
1412
1413 private ActivityManagerService() {
1414 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1415 if (v != null && Integer.getInteger(v) != 0) {
1416 mSimpleProcessManagement = true;
1417 }
1418 v = System.getenv("ANDROID_DEBUG_APP");
1419 if (v != null) {
1420 mSimpleProcessManagement = true;
1421 }
1422
Joe Onorato8a9b2202010-02-26 18:56:32 -08001423 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 File dataDir = Environment.getDataDirectory();
1426 File systemDir = new File(dataDir, "system");
1427 systemDir.mkdirs();
1428 mBatteryStatsService = new BatteryStatsService(new File(
1429 systemDir, "batterystats.bin").toString());
1430 mBatteryStatsService.getActiveStatistics().readLocked();
1431 mBatteryStatsService.getActiveStatistics().writeLocked();
1432
1433 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001434 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435
Jack Palevichb90d28c2009-07-22 15:35:24 -07001436 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1437 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1438
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001439 mConfiguration.setToDefaults();
1440 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 mProcessStats.init();
1442
1443 // Add ourself to the Watchdog monitors.
1444 Watchdog.getInstance().addMonitor(this);
1445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 mProcessStatsThread = new Thread("ProcessStats") {
1447 public void run() {
1448 while (true) {
1449 try {
1450 try {
1451 synchronized(this) {
1452 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001453 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001455 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 // + ", write delay=" + nextWriteDelay);
1457 if (nextWriteDelay < nextCpuDelay) {
1458 nextCpuDelay = nextWriteDelay;
1459 }
1460 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001461 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 this.wait(nextCpuDelay);
1463 }
1464 }
1465 } catch (InterruptedException e) {
1466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 updateCpuStatsNow();
1468 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001469 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 }
1471 }
1472 }
1473 };
1474 mProcessStatsThread.start();
1475 }
1476
1477 @Override
1478 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1479 throws RemoteException {
1480 try {
1481 return super.onTransact(code, data, reply, flags);
1482 } catch (RuntimeException e) {
1483 // The activity manager only throws security exceptions, so let's
1484 // log all others.
1485 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001486 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 }
1488 throw e;
1489 }
1490 }
1491
1492 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001493 final long now = SystemClock.uptimeMillis();
1494 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1495 return;
1496 }
1497 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1498 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 mProcessStatsThread.notify();
1500 }
1501 }
1502 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 void updateCpuStatsNow() {
1505 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001506 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 final long now = SystemClock.uptimeMillis();
1508 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001511 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1512 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 haveNewCpuStats = true;
1514 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001515 //Slog.i(TAG, mProcessStats.printCurrentState());
1516 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 // + mProcessStats.getTotalCpuPercent() + "%");
1518
Joe Onorato8a9b2202010-02-26 18:56:32 -08001519 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 if ("true".equals(SystemProperties.get("events.cpu"))) {
1521 int user = mProcessStats.getLastUserTime();
1522 int system = mProcessStats.getLastSystemTime();
1523 int iowait = mProcessStats.getLastIoWaitTime();
1524 int irq = mProcessStats.getLastIrqTime();
1525 int softIrq = mProcessStats.getLastSoftIrqTime();
1526 int idle = mProcessStats.getLastIdleTime();
1527
1528 int total = user + system + iowait + irq + softIrq + idle;
1529 if (total == 0) total = 1;
1530
Doug Zongker2bec3d42009-12-04 12:52:44 -08001531 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 ((user+system+iowait+irq+softIrq) * 100) / total,
1533 (user * 100) / total,
1534 (system * 100) / total,
1535 (iowait * 100) / total,
1536 (irq * 100) / total,
1537 (softIrq * 100) / total);
1538 }
1539 }
1540
Amith Yamasanie43530a2009-08-21 13:11:37 -07001541 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001542 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001543 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 synchronized(mPidsSelfLocked) {
1545 if (haveNewCpuStats) {
1546 if (mBatteryStatsService.isOnBattery()) {
1547 final int N = mProcessStats.countWorkingStats();
1548 for (int i=0; i<N; i++) {
1549 ProcessStats.Stats st
1550 = mProcessStats.getWorkingStats(i);
1551 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1552 if (pr != null) {
1553 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1554 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001555 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001556 } else {
1557 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001558 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001559 if (ps != null) {
1560 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001561 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 }
1564 }
1565 }
1566 }
1567 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1570 mLastWriteTime = now;
1571 mBatteryStatsService.getActiveStatistics().writeLocked();
1572 }
1573 }
1574 }
1575 }
1576
1577 /**
1578 * Initialize the application bind args. These are passed to each
1579 * process when the bindApplication() IPC is sent to the process. They're
1580 * lazily setup to make sure the services are running when they're asked for.
1581 */
1582 private HashMap<String, IBinder> getCommonServicesLocked() {
1583 if (mAppBindArgs == null) {
1584 mAppBindArgs = new HashMap<String, IBinder>();
1585
1586 // Setup the application init args
1587 mAppBindArgs.put("package", ServiceManager.getService("package"));
1588 mAppBindArgs.put("window", ServiceManager.getService("window"));
1589 mAppBindArgs.put(Context.ALARM_SERVICE,
1590 ServiceManager.getService(Context.ALARM_SERVICE));
1591 }
1592 return mAppBindArgs;
1593 }
1594
1595 private final void setFocusedActivityLocked(HistoryRecord r) {
1596 if (mFocusedActivity != r) {
1597 mFocusedActivity = r;
1598 mWindowManager.setFocusedApp(r, true);
1599 }
1600 }
1601
Dianne Hackborn906497c2010-05-10 15:57:38 -07001602 private final void updateLruProcessInternalLocked(ProcessRecord app,
1603 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001605 int lrui = mLruProcesses.indexOf(app);
1606 if (lrui >= 0) mLruProcesses.remove(lrui);
1607
1608 int i = mLruProcesses.size()-1;
1609 int skipTop = 0;
1610
Dianne Hackborn906497c2010-05-10 15:57:38 -07001611 app.lruSeq = mLruSeq;
1612
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001613 // compute the new weight for this process.
1614 if (updateActivityTime) {
1615 app.lastActivityTime = SystemClock.uptimeMillis();
1616 }
1617 if (app.activities.size() > 0) {
1618 // If this process has activities, we more strongly want to keep
1619 // it around.
1620 app.lruWeight = app.lastActivityTime;
1621 } else if (app.pubProviders.size() > 0) {
1622 // If this process contains content providers, we want to keep
1623 // it a little more strongly.
1624 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1625 // Also don't let it kick out the first few "real" hidden processes.
1626 skipTop = MIN_HIDDEN_APPS;
1627 } else {
1628 // If this process doesn't have activities, we less strongly
1629 // want to keep it around, and generally want to avoid getting
1630 // in front of any very recently used activities.
1631 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1632 // Also don't let it kick out the first few "real" hidden processes.
1633 skipTop = MIN_HIDDEN_APPS;
1634 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001635
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001636 while (i >= 0) {
1637 ProcessRecord p = mLruProcesses.get(i);
1638 // If this app shouldn't be in front of the first N background
1639 // apps, then skip over that many that are currently hidden.
1640 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1641 skipTop--;
1642 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001643 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001644 mLruProcesses.add(i+1, app);
1645 break;
1646 }
1647 i--;
1648 }
1649 if (i < 0) {
1650 mLruProcesses.add(0, app);
1651 }
1652
Dianne Hackborn906497c2010-05-10 15:57:38 -07001653 // If the app is currently using a content provider or service,
1654 // bump those processes as well.
1655 if (app.connections.size() > 0) {
1656 for (ConnectionRecord cr : app.connections) {
1657 if (cr.binding != null && cr.binding.service != null
1658 && cr.binding.service.app != null
1659 && cr.binding.service.app.lruSeq != mLruSeq) {
1660 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1661 updateActivityTime, i+1);
1662 }
1663 }
1664 }
1665 if (app.conProviders.size() > 0) {
1666 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1667 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1668 updateLruProcessInternalLocked(cpr.app, oomAdj,
1669 updateActivityTime, i+1);
1670 }
1671 }
1672 }
1673
Joe Onorato8a9b2202010-02-26 18:56:32 -08001674 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 if (oomAdj) {
1676 updateOomAdjLocked();
1677 }
1678 }
1679
Dianne Hackborn906497c2010-05-10 15:57:38 -07001680 private final void updateLruProcessLocked(ProcessRecord app,
1681 boolean oomAdj, boolean updateActivityTime) {
1682 mLruSeq++;
1683 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1684 }
1685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001686 private final boolean updateLRUListLocked(HistoryRecord r) {
1687 final boolean hadit = mLRUActivities.remove(r);
1688 mLRUActivities.add(r);
1689 return hadit;
1690 }
1691
1692 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1693 int i = mHistory.size()-1;
1694 while (i >= 0) {
1695 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1696 if (!r.finishing && r != notTop) {
1697 return r;
1698 }
1699 i--;
1700 }
1701 return null;
1702 }
1703
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001704 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1705 int i = mHistory.size()-1;
1706 while (i >= 0) {
1707 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1708 if (!r.finishing && !r.delayedResume && r != notTop) {
1709 return r;
1710 }
1711 i--;
1712 }
1713 return null;
1714 }
1715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 /**
1717 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001718 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 *
1720 * @param token If non-null, any history records matching this token will be skipped.
1721 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1722 *
1723 * @return Returns the HistoryRecord of the next activity on the stack.
1724 */
1725 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1726 int i = mHistory.size()-1;
1727 while (i >= 0) {
1728 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1729 // Note: the taskId check depends on real taskId fields being non-zero
1730 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1731 return r;
1732 }
1733 i--;
1734 }
1735 return null;
1736 }
1737
1738 private final ProcessRecord getProcessRecordLocked(
1739 String processName, int uid) {
1740 if (uid == Process.SYSTEM_UID) {
1741 // The system gets to run in any process. If there are multiple
1742 // processes with the same uid, just pick the first (this
1743 // should never happen).
1744 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1745 processName);
1746 return procs != null ? procs.valueAt(0) : null;
1747 }
1748 ProcessRecord proc = mProcessNames.get(processName, uid);
1749 return proc;
1750 }
1751
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001752 private void ensurePackageDexOpt(String packageName) {
1753 IPackageManager pm = ActivityThread.getPackageManager();
1754 try {
1755 if (pm.performDexOpt(packageName)) {
1756 mDidDexOpt = true;
1757 }
1758 } catch (RemoteException e) {
1759 }
1760 }
1761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 private boolean isNextTransitionForward() {
1763 int transit = mWindowManager.getPendingAppTransition();
1764 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1765 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1766 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1767 }
1768
1769 private final boolean realStartActivityLocked(HistoryRecord r,
1770 ProcessRecord app, boolean andResume, boolean checkConfig)
1771 throws RemoteException {
1772
1773 r.startFreezingScreenLocked(app, 0);
1774 mWindowManager.setAppVisibility(r, true);
1775
1776 // Have the window manager re-evaluate the orientation of
1777 // the screen based on the new activity order. Note that
1778 // as a result of this, it can call back into the activity
1779 // manager with a new orientation. We don't care about that,
1780 // because the activity is not currently running so we are
1781 // just restarting it anyway.
1782 if (checkConfig) {
1783 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001784 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 r.mayFreezeScreenLocked(app) ? r : null);
1786 updateConfigurationLocked(config, r);
1787 }
1788
1789 r.app = app;
1790
Joe Onorato8a9b2202010-02-26 18:56:32 -08001791 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792
1793 int idx = app.activities.indexOf(r);
1794 if (idx < 0) {
1795 app.activities.add(r);
1796 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001797 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798
1799 try {
1800 if (app.thread == null) {
1801 throw new RemoteException();
1802 }
1803 List<ResultInfo> results = null;
1804 List<Intent> newIntents = null;
1805 if (andResume) {
1806 results = r.results;
1807 newIntents = r.newIntents;
1808 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001809 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 + " icicle=" + r.icicle
1811 + " with results=" + results + " newIntents=" + newIntents
1812 + " andResume=" + andResume);
1813 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001814 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 System.identityHashCode(r),
1816 r.task.taskId, r.shortComponentName);
1817 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001818 if (r.isHomeActivity) {
1819 mHomeProcess = app;
1820 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001821 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001823 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001824 r.info, r.icicle, results, newIntents, !andResume,
1825 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001826 } catch (RemoteException e) {
1827 if (r.launchFailed) {
1828 // This is the second time we failed -- finish activity
1829 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001830 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 + r.intent.getComponent().flattenToShortString()
1832 + ", giving up", e);
1833 appDiedLocked(app, app.pid, app.thread);
1834 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1835 "2nd-crash");
1836 return false;
1837 }
1838
1839 // This is the first time we failed -- restart process and
1840 // retry.
1841 app.activities.remove(r);
1842 throw e;
1843 }
1844
1845 r.launchFailed = false;
1846 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001847 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 + " being launched, but already in LRU list");
1849 }
1850
1851 if (andResume) {
1852 // As part of the process of launching, ActivityThread also performs
1853 // a resume.
1854 r.state = ActivityState.RESUMED;
1855 r.icicle = null;
1856 r.haveState = false;
1857 r.stopped = false;
1858 mResumedActivity = r;
1859 r.task.touchActiveTime();
1860 completeResumeLocked(r);
1861 pauseIfSleepingLocked();
1862 } else {
1863 // This activity is not starting in the resumed state... which
1864 // should look like we asked it to pause+stop (but remain visible),
1865 // and it has done so and reported back the current icicle and
1866 // other state.
1867 r.state = ActivityState.STOPPED;
1868 r.stopped = true;
1869 }
1870
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001871 // Launch the new version setup screen if needed. We do this -after-
1872 // launching the initial activity (that is, home), so that it can have
1873 // a chance to initialize itself while in the background, making the
1874 // switch back to it faster and look better.
1875 startSetupActivityLocked();
1876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 return true;
1878 }
1879
1880 private final void startSpecificActivityLocked(HistoryRecord r,
1881 boolean andResume, boolean checkConfig) {
1882 // Is this activity's application already running?
1883 ProcessRecord app = getProcessRecordLocked(r.processName,
1884 r.info.applicationInfo.uid);
1885
1886 if (r.startTime == 0) {
1887 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001888 if (mInitialStartTime == 0) {
1889 mInitialStartTime = r.startTime;
1890 }
1891 } else if (mInitialStartTime == 0) {
1892 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 }
1894
1895 if (app != null && app.thread != null) {
1896 try {
1897 realStartActivityLocked(r, app, andResume, checkConfig);
1898 return;
1899 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001900 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 + r.intent.getComponent().flattenToShortString(), e);
1902 }
1903
1904 // If a dead object exception was thrown -- fall through to
1905 // restart the application.
1906 }
1907
1908 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001909 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 }
1911
1912 private final ProcessRecord startProcessLocked(String processName,
1913 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001914 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1916 // We don't have to do anything more if:
1917 // (1) There is an existing application record; and
1918 // (2) The caller doesn't think it is dead, OR there is no thread
1919 // object attached to it so we know it couldn't have crashed; and
1920 // (3) There is a pid assigned to it, so it is either starting or
1921 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001922 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923 + " app=" + app + " knownToBeDead=" + knownToBeDead
1924 + " thread=" + (app != null ? app.thread : null)
1925 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001926 if (app != null && app.pid > 0) {
1927 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001928 // We already have the app running, or are waiting for it to
1929 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001930 return app;
1931 } else {
1932 // An application record is attached to a previous process,
1933 // clean it up now.
1934 handleAppDiedLocked(app, true);
1935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 String hostingNameStr = hostingName != null
1939 ? hostingName.flattenToShortString() : null;
1940
1941 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1942 // If we are in the background, then check to see if this process
1943 // is bad. If so, we will just silently fail.
1944 if (mBadProcesses.get(info.processName, info.uid) != null) {
1945 return null;
1946 }
1947 } else {
1948 // When the user is explicitly starting a process, then clear its
1949 // crash count so that we won't make it bad until they see at
1950 // least one crash dialog again, and make the process good again
1951 // if it had been bad.
1952 mProcessCrashTimes.remove(info.processName, info.uid);
1953 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001954 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 info.processName);
1956 mBadProcesses.remove(info.processName, info.uid);
1957 if (app != null) {
1958 app.bad = false;
1959 }
1960 }
1961 }
1962
1963 if (app == null) {
1964 app = newProcessRecordLocked(null, info, processName);
1965 mProcessNames.put(processName, info.uid, app);
1966 } else {
1967 // If this is a new package in the process, add the package to the list
1968 app.addPackage(info.packageName);
1969 }
1970
1971 // If the system is not ready yet, then hold off on starting this
1972 // process until it is.
1973 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001974 && !isAllowedWhileBooting(info)
1975 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 if (!mProcessesOnHold.contains(app)) {
1977 mProcessesOnHold.add(app);
1978 }
1979 return app;
1980 }
1981
1982 startProcessLocked(app, hostingType, hostingNameStr);
1983 return (app.pid != 0) ? app : null;
1984 }
1985
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001986 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1987 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1988 }
1989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 private final void startProcessLocked(ProcessRecord app,
1991 String hostingType, String hostingNameStr) {
1992 if (app.pid > 0 && app.pid != MY_PID) {
1993 synchronized (mPidsSelfLocked) {
1994 mPidsSelfLocked.remove(app.pid);
1995 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1996 }
1997 app.pid = 0;
1998 }
1999
2000 mProcessesOnHold.remove(app);
2001
2002 updateCpuStats();
2003
2004 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
2005 mProcDeaths[0] = 0;
2006
2007 try {
2008 int uid = app.info.uid;
2009 int[] gids = null;
2010 try {
2011 gids = mContext.getPackageManager().getPackageGids(
2012 app.info.packageName);
2013 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002014 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 }
2016 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2017 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2018 && mTopComponent != null
2019 && app.processName.equals(mTopComponent.getPackageName())) {
2020 uid = 0;
2021 }
2022 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2023 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2024 uid = 0;
2025 }
2026 }
2027 int debugFlags = 0;
2028 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2029 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
2030 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002031 // Run the app in safe mode if its manifest requests so or the
2032 // system is booted in safe mode.
2033 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2034 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002035 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2036 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2038 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2039 }
2040 if ("1".equals(SystemProperties.get("debug.assert"))) {
2041 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2042 }
2043 int pid = Process.start("android.app.ActivityThread",
2044 mSimpleProcessManagement ? app.processName : null, uid, uid,
2045 gids, debugFlags, null);
2046 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2047 synchronized (bs) {
2048 if (bs.isOnBattery()) {
2049 app.batteryStats.incStartsLocked();
2050 }
2051 }
2052
Doug Zongker2bec3d42009-12-04 12:52:44 -08002053 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 app.processName, hostingType,
2055 hostingNameStr != null ? hostingNameStr : "");
2056
2057 if (app.persistent) {
2058 Watchdog.getInstance().processStarted(app, app.processName, pid);
2059 }
2060
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002061 StringBuilder buf = mStringBuilder;
2062 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 buf.append("Start proc ");
2064 buf.append(app.processName);
2065 buf.append(" for ");
2066 buf.append(hostingType);
2067 if (hostingNameStr != null) {
2068 buf.append(" ");
2069 buf.append(hostingNameStr);
2070 }
2071 buf.append(": pid=");
2072 buf.append(pid);
2073 buf.append(" uid=");
2074 buf.append(uid);
2075 buf.append(" gids={");
2076 if (gids != null) {
2077 for (int gi=0; gi<gids.length; gi++) {
2078 if (gi != 0) buf.append(", ");
2079 buf.append(gids[gi]);
2080
2081 }
2082 }
2083 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002084 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 if (pid == 0 || pid == MY_PID) {
2086 // Processes are being emulated with threads.
2087 app.pid = MY_PID;
2088 app.removed = false;
2089 mStartingProcesses.add(app);
2090 } else if (pid > 0) {
2091 app.pid = pid;
2092 app.removed = false;
2093 synchronized (mPidsSelfLocked) {
2094 this.mPidsSelfLocked.put(pid, app);
2095 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2096 msg.obj = app;
2097 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2098 }
2099 } else {
2100 app.pid = 0;
2101 RuntimeException e = new RuntimeException(
2102 "Failure starting process " + app.processName
2103 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002104 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105 }
2106 } catch (RuntimeException e) {
2107 // XXX do better error recovery.
2108 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002109 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 }
2111 }
2112
2113 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2114 if (mPausingActivity != null) {
2115 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002116 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 + mPausingActivity, e);
2118 }
2119 HistoryRecord prev = mResumedActivity;
2120 if (prev == null) {
2121 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002122 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 resumeTopActivityLocked(null);
2124 return;
2125 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002126 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 mResumedActivity = null;
2128 mPausingActivity = prev;
2129 mLastPausedActivity = prev;
2130 prev.state = ActivityState.PAUSING;
2131 prev.task.touchActiveTime();
2132
2133 updateCpuStats();
2134
2135 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002136 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002137 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002138 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 System.identityHashCode(prev),
2140 prev.shortComponentName);
2141 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2142 prev.configChangeFlags);
2143 updateUsageStats(prev, false);
2144 } catch (Exception e) {
2145 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002146 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 mPausingActivity = null;
2148 mLastPausedActivity = null;
2149 }
2150 } else {
2151 mPausingActivity = null;
2152 mLastPausedActivity = null;
2153 }
2154
2155 // If we are not going to sleep, we want to ensure the device is
2156 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002157 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158 mLaunchingActivity.acquire();
2159 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2160 // To be safe, don't allow the wake lock to be held for too long.
2161 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2162 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2163 }
2164 }
2165
2166
2167 if (mPausingActivity != null) {
2168 // Have the window manager pause its key dispatching until the new
2169 // activity has started. If we're pausing the activity just because
2170 // the screen is being turned off and the UI is sleeping, don't interrupt
2171 // key dispatch; the same activity will pick it up again on wakeup.
2172 if (!uiSleeping) {
2173 prev.pauseKeyDispatchingLocked();
2174 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002175 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 }
2177
2178 // Schedule a pause timeout in case the app doesn't respond.
2179 // We don't give it much time because this directly impacts the
2180 // responsiveness seen by the user.
2181 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2182 msg.obj = prev;
2183 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002184 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 } else {
2186 // This activity failed to schedule the
2187 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002188 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002189 resumeTopActivityLocked(null);
2190 }
2191 }
2192
2193 private final void completePauseLocked() {
2194 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002195 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196
2197 if (prev != null) {
2198 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002199 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2201 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002202 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 if (prev.waitingVisible) {
2204 prev.waitingVisible = false;
2205 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002206 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 TAG, "Complete pause, no longer waiting: " + prev);
2208 }
2209 if (prev.configDestroy) {
2210 // The previous is being paused because the configuration
2211 // is changing, which means it is actually stopping...
2212 // To juggle the fact that we are also starting a new
2213 // instance right now, we need to first completely stop
2214 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002215 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 destroyActivityLocked(prev, true);
2217 } else {
2218 mStoppingActivities.add(prev);
2219 if (mStoppingActivities.size() > 3) {
2220 // If we already have a few activities waiting to stop,
2221 // then give up on things going idle and start clearing
2222 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002223 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002224 Message msg = Message.obtain();
2225 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2226 mHandler.sendMessage(msg);
2227 }
2228 }
2229 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002230 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 prev = null;
2232 }
2233 mPausingActivity = null;
2234 }
2235
Dianne Hackborn55280a92009-05-07 15:53:46 -07002236 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237 resumeTopActivityLocked(prev);
2238 } else {
2239 if (mGoingToSleep.isHeld()) {
2240 mGoingToSleep.release();
2241 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002242 if (mShuttingDown) {
2243 notifyAll();
2244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002245 }
2246
2247 if (prev != null) {
2248 prev.resumeKeyDispatchingLocked();
2249 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002250
2251 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2252 long diff = 0;
2253 synchronized (mProcessStatsThread) {
2254 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2255 }
2256 if (diff > 0) {
2257 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2258 synchronized (bsi) {
2259 BatteryStatsImpl.Uid.Proc ps =
2260 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2261 prev.info.packageName);
2262 if (ps != null) {
2263 ps.addForegroundTimeLocked(diff);
2264 }
2265 }
2266 }
2267 }
2268 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 }
2270
2271 /**
2272 * Once we know that we have asked an application to put an activity in
2273 * the resumed state (either by launching it or explicitly telling it),
2274 * this function updates the rest of our state to match that fact.
2275 */
2276 private final void completeResumeLocked(HistoryRecord next) {
2277 next.idle = false;
2278 next.results = null;
2279 next.newIntents = null;
2280
2281 // schedule an idle timeout in case the app doesn't do it for us.
2282 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2283 msg.obj = next;
2284 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2285
2286 if (false) {
2287 // The activity was never told to pause, so just keep
2288 // things going as-is. To maintain our own state,
2289 // we need to emulate it coming back and saying it is
2290 // idle.
2291 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2292 msg.obj = next;
2293 mHandler.sendMessage(msg);
2294 }
2295
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002296 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002298 next.thumbnail = null;
2299 setFocusedActivityLocked(next);
2300 next.resumeKeyDispatchingLocked();
2301 ensureActivitiesVisibleLocked(null, 0);
2302 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002303 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002304
2305 // Mark the point when the activity is resuming
2306 // TODO: To be more accurate, the mark should be before the onCreate,
2307 // not after the onResume. But for subsequent starts, onResume is fine.
2308 if (next.app != null) {
2309 synchronized (mProcessStatsThread) {
2310 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2311 }
2312 } else {
2313 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 }
2316
2317 /**
2318 * Make sure that all activities that need to be visible (that is, they
2319 * currently can be seen by the user) actually are.
2320 */
2321 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2322 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002323 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 TAG, "ensureActivitiesVisible behind " + top
2325 + " configChanges=0x" + Integer.toHexString(configChanges));
2326
2327 // If the top activity is not fullscreen, then we need to
2328 // make sure any activities under it are now visible.
2329 final int count = mHistory.size();
2330 int i = count-1;
2331 while (mHistory.get(i) != top) {
2332 i--;
2333 }
2334 HistoryRecord r;
2335 boolean behindFullscreen = false;
2336 for (; i>=0; i--) {
2337 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002338 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002339 TAG, "Make visible? " + r + " finishing=" + r.finishing
2340 + " state=" + r.state);
2341 if (r.finishing) {
2342 continue;
2343 }
2344
2345 final boolean doThisProcess = onlyThisProcess == null
2346 || onlyThisProcess.equals(r.processName);
2347
2348 // First: if this is not the current activity being started, make
2349 // sure it matches the current configuration.
2350 if (r != starting && doThisProcess) {
2351 ensureActivityConfigurationLocked(r, 0);
2352 }
2353
2354 if (r.app == null || r.app.thread == null) {
2355 if (onlyThisProcess == null
2356 || onlyThisProcess.equals(r.processName)) {
2357 // This activity needs to be visible, but isn't even
2358 // running... get it started, but don't resume it
2359 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002360 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 TAG, "Start and freeze screen for " + r);
2362 if (r != starting) {
2363 r.startFreezingScreenLocked(r.app, configChanges);
2364 }
2365 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002366 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 TAG, "Starting and making visible: " + r);
2368 mWindowManager.setAppVisibility(r, true);
2369 }
2370 if (r != starting) {
2371 startSpecificActivityLocked(r, false, false);
2372 }
2373 }
2374
2375 } else if (r.visible) {
2376 // If this activity is already visible, then there is nothing
2377 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002378 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 TAG, "Skipping: already visible at " + r);
2380 r.stopFreezingScreenLocked(false);
2381
2382 } else if (onlyThisProcess == null) {
2383 // This activity is not currently visible, but is running.
2384 // Tell it to become visible.
2385 r.visible = true;
2386 if (r.state != ActivityState.RESUMED && r != starting) {
2387 // If this activity is paused, tell it
2388 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002389 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 TAG, "Making visible and scheduling visibility: " + r);
2391 try {
2392 mWindowManager.setAppVisibility(r, true);
2393 r.app.thread.scheduleWindowVisibility(r, true);
2394 r.stopFreezingScreenLocked(false);
2395 } catch (Exception e) {
2396 // Just skip on any failure; we'll make it
2397 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002398 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 + r.intent.getComponent(), e);
2400 }
2401 }
2402 }
2403
2404 // Aggregate current change flags.
2405 configChanges |= r.configChangeFlags;
2406
2407 if (r.fullscreen) {
2408 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002409 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002410 TAG, "Stopping: fullscreen at " + r);
2411 behindFullscreen = true;
2412 i--;
2413 break;
2414 }
2415 }
2416
2417 // Now for any activities that aren't visible to the user, make
2418 // sure they no longer are keeping the screen frozen.
2419 while (i >= 0) {
2420 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002421 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2423 + " state=" + r.state
2424 + " behindFullscreen=" + behindFullscreen);
2425 if (!r.finishing) {
2426 if (behindFullscreen) {
2427 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002428 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 TAG, "Making invisible: " + r);
2430 r.visible = false;
2431 try {
2432 mWindowManager.setAppVisibility(r, false);
2433 if ((r.state == ActivityState.STOPPING
2434 || r.state == ActivityState.STOPPED)
2435 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002436 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002437 TAG, "Scheduling invisibility: " + r);
2438 r.app.thread.scheduleWindowVisibility(r, false);
2439 }
2440 } catch (Exception e) {
2441 // Just skip on any failure; we'll make it
2442 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002443 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002444 + r.intent.getComponent(), e);
2445 }
2446 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002447 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002448 TAG, "Already invisible: " + r);
2449 }
2450 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002451 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002452 TAG, "Now behindFullscreen: " + r);
2453 behindFullscreen = true;
2454 }
2455 }
2456 i--;
2457 }
2458 }
2459
2460 /**
2461 * Version of ensureActivitiesVisible that can easily be called anywhere.
2462 */
2463 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2464 int configChanges) {
2465 HistoryRecord r = topRunningActivityLocked(null);
2466 if (r != null) {
2467 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2468 }
2469 }
2470
2471 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2472 if (resumed) {
2473 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2474 } else {
2475 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2476 }
2477 }
2478
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002479 private boolean startHomeActivityLocked() {
2480 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2481 && mTopAction == null) {
2482 // We are running in factory test mode, but unable to find
2483 // the factory test app, so just sit around displaying the
2484 // error message and don't try to start anything.
2485 return false;
2486 }
2487 Intent intent = new Intent(
2488 mTopAction,
2489 mTopData != null ? Uri.parse(mTopData) : null);
2490 intent.setComponent(mTopComponent);
2491 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2492 intent.addCategory(Intent.CATEGORY_HOME);
2493 }
2494 ActivityInfo aInfo =
2495 intent.resolveActivityInfo(mContext.getPackageManager(),
2496 STOCK_PM_FLAGS);
2497 if (aInfo != null) {
2498 intent.setComponent(new ComponentName(
2499 aInfo.applicationInfo.packageName, aInfo.name));
2500 // Don't do this if the home app is currently being
2501 // instrumented.
2502 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2503 aInfo.applicationInfo.uid);
2504 if (app == null || app.instrumentationClass == null) {
2505 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2506 startActivityLocked(null, intent, null, null, 0, aInfo,
2507 null, null, 0, 0, 0, false, false);
2508 }
2509 }
2510
2511
2512 return true;
2513 }
2514
2515 /**
2516 * Starts the "new version setup screen" if appropriate.
2517 */
2518 private void startSetupActivityLocked() {
2519 // Only do this once per boot.
2520 if (mCheckedForSetup) {
2521 return;
2522 }
2523
2524 // We will show this screen if the current one is a different
2525 // version than the last one shown, and we are not running in
2526 // low-level factory test mode.
2527 final ContentResolver resolver = mContext.getContentResolver();
2528 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2529 Settings.Secure.getInt(resolver,
2530 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2531 mCheckedForSetup = true;
2532
2533 // See if we should be showing the platform update setup UI.
2534 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2535 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2536 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2537
2538 // We don't allow third party apps to replace this.
2539 ResolveInfo ri = null;
2540 for (int i=0; ris != null && i<ris.size(); i++) {
2541 if ((ris.get(i).activityInfo.applicationInfo.flags
2542 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2543 ri = ris.get(i);
2544 break;
2545 }
2546 }
2547
2548 if (ri != null) {
2549 String vers = ri.activityInfo.metaData != null
2550 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2551 : null;
2552 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2553 vers = ri.activityInfo.applicationInfo.metaData.getString(
2554 Intent.METADATA_SETUP_VERSION);
2555 }
2556 String lastVers = Settings.Secure.getString(
2557 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2558 if (vers != null && !vers.equals(lastVers)) {
2559 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2560 intent.setComponent(new ComponentName(
2561 ri.activityInfo.packageName, ri.activityInfo.name));
2562 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2563 null, null, 0, 0, 0, false, false);
2564 }
2565 }
2566 }
2567 }
2568
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002569 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002570 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002571
2572 final int identHash = System.identityHashCode(r);
2573 updateUsageStats(r, true);
2574
2575 int i = mWatchers.beginBroadcast();
2576 while (i > 0) {
2577 i--;
2578 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2579 if (w != null) {
2580 try {
2581 w.activityResuming(identHash);
2582 } catch (RemoteException e) {
2583 }
2584 }
2585 }
2586 mWatchers.finishBroadcast();
2587 }
2588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589 /**
2590 * Ensure that the top activity in the stack is resumed.
2591 *
2592 * @param prev The previously resumed activity, for when in the process
2593 * of pausing; can be null to call from elsewhere.
2594 *
2595 * @return Returns true if something is being resumed, or false if
2596 * nothing happened.
2597 */
2598 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2599 // Find the first activity that is not finishing.
2600 HistoryRecord next = topRunningActivityLocked(null);
2601
2602 // Remember how we'll process this pause/resume situation, and ensure
2603 // that the state is reset however we wind up proceeding.
2604 final boolean userLeaving = mUserLeaving;
2605 mUserLeaving = false;
2606
2607 if (next == null) {
2608 // There are no more activities! Let's just start up the
2609 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002610 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002611 }
2612
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002613 next.delayedResume = false;
2614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 // If the top activity is the resumed one, nothing to do.
2616 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2617 // Make sure we have executed any pending transitions, since there
2618 // should be nothing left to do at this point.
2619 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002620 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 return false;
2622 }
2623
2624 // If we are sleeping, and there is no resumed activity, and the top
2625 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002626 if ((mSleeping || mShuttingDown)
2627 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 // Make sure we have executed any pending transitions, since there
2629 // should be nothing left to do at this point.
2630 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002631 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 return false;
2633 }
2634
2635 // The activity may be waiting for stop, but that is no longer
2636 // appropriate for it.
2637 mStoppingActivities.remove(next);
2638 mWaitingVisibleActivities.remove(next);
2639
Joe Onorato8a9b2202010-02-26 18:56:32 -08002640 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641
2642 // If we are currently pausing an activity, then don't do anything
2643 // until that is done.
2644 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002645 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002646 return false;
2647 }
2648
2649 // We need to start pausing the current activity so the top one
2650 // can be resumed...
2651 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002652 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653 startPausingLocked(userLeaving, false);
2654 return true;
2655 }
2656
2657 if (prev != null && prev != next) {
2658 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2659 prev.waitingVisible = true;
2660 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002661 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002662 TAG, "Resuming top, waiting visible to hide: " + prev);
2663 } else {
2664 // The next activity is already visible, so hide the previous
2665 // activity's windows right now so we can show the new one ASAP.
2666 // We only do this if the previous is finishing, which should mean
2667 // it is on top of the one being resumed so hiding it quickly
2668 // is good. Otherwise, we want to do the normal route of allowing
2669 // the resumed activity to be shown so we can decide if the
2670 // previous should actually be hidden depending on whether the
2671 // new one is found to be full-screen or not.
2672 if (prev.finishing) {
2673 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002674 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002675 + prev + ", waitingVisible="
2676 + (prev != null ? prev.waitingVisible : null)
2677 + ", nowVisible=" + next.nowVisible);
2678 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002679 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 + prev + ", waitingVisible="
2681 + (prev != null ? prev.waitingVisible : null)
2682 + ", nowVisible=" + next.nowVisible);
2683 }
2684 }
2685 }
2686
2687 // We are starting up the next activity, so tell the window manager
2688 // that the previous one will be hidden soon. This way it can know
2689 // to ignore it when computing the desired screen orientation.
2690 if (prev != null) {
2691 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002692 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002694 if (mNoAnimActivities.contains(prev)) {
2695 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2696 } else {
2697 mWindowManager.prepareAppTransition(prev.task == next.task
2698 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2699 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 mWindowManager.setAppWillBeHidden(prev);
2702 mWindowManager.setAppVisibility(prev, false);
2703 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002704 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002706 if (mNoAnimActivities.contains(next)) {
2707 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2708 } else {
2709 mWindowManager.prepareAppTransition(prev.task == next.task
2710 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2711 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 }
2714 if (false) {
2715 mWindowManager.setAppWillBeHidden(prev);
2716 mWindowManager.setAppVisibility(prev, false);
2717 }
2718 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002719 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002721 if (mNoAnimActivities.contains(next)) {
2722 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2723 } else {
2724 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 }
2727
2728 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002729 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730
2731 // This activity is now becoming visible.
2732 mWindowManager.setAppVisibility(next, true);
2733
2734 HistoryRecord lastResumedActivity = mResumedActivity;
2735 ActivityState lastState = next.state;
2736
2737 updateCpuStats();
2738
2739 next.state = ActivityState.RESUMED;
2740 mResumedActivity = next;
2741 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002742 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002743 updateLRUListLocked(next);
2744
2745 // Have the window manager re-evaluate the orientation of
2746 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002747 boolean updated;
2748 synchronized (this) {
2749 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2750 mConfiguration,
2751 next.mayFreezeScreenLocked(next.app) ? next : null);
2752 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002753 next.frozenBeforeDestroy = true;
2754 }
2755 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002756 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002757 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002758 // The configuration update wasn't able to keep the existing
2759 // instance of the activity, and instead started a new one.
2760 // We should be all done, but let's just make sure our activity
2761 // is still at the top and schedule another run if something
2762 // weird happened.
2763 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002764 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 "Activity config changed during resume: " + next
2766 + ", new next: " + nextNext);
2767 if (nextNext != next) {
2768 // Do over!
2769 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2770 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002771 setFocusedActivityLocked(next);
2772 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002773 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002774 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 return true;
2776 }
2777
2778 try {
2779 // Deliver all pending results.
2780 ArrayList a = next.results;
2781 if (a != null) {
2782 final int N = a.size();
2783 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002784 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785 TAG, "Delivering results to " + next
2786 + ": " + a);
2787 next.app.thread.scheduleSendResult(next, a);
2788 }
2789 }
2790
2791 if (next.newIntents != null) {
2792 next.app.thread.scheduleNewIntent(next.newIntents, next);
2793 }
2794
Doug Zongker2bec3d42009-12-04 12:52:44 -08002795 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002796 System.identityHashCode(next),
2797 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002798
2799 next.app.thread.scheduleResumeActivity(next,
2800 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002802 pauseIfSleepingLocked();
2803
2804 } catch (Exception e) {
2805 // Whoops, need to restart this activity!
2806 next.state = lastState;
2807 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002808 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 if (!next.hasBeenLaunched) {
2810 next.hasBeenLaunched = true;
2811 } else {
2812 if (SHOW_APP_STARTING_ICON) {
2813 mWindowManager.setAppStartingWindow(
2814 next, next.packageName, next.theme,
2815 next.nonLocalizedLabel,
2816 next.labelRes, next.icon, null, true);
2817 }
2818 }
2819 startSpecificActivityLocked(next, true, false);
2820 return true;
2821 }
2822
2823 // From this point on, if something goes wrong there is no way
2824 // to recover the activity.
2825 try {
2826 next.visible = true;
2827 completeResumeLocked(next);
2828 } catch (Exception e) {
2829 // If any exception gets thrown, toss away this
2830 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002831 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002832 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2833 "resume-exception");
2834 return true;
2835 }
2836
2837 // Didn't need to use the icicle, and it is now out of date.
2838 next.icicle = null;
2839 next.haveState = false;
2840 next.stopped = false;
2841
2842 } else {
2843 // Whoops, need to restart this activity!
2844 if (!next.hasBeenLaunched) {
2845 next.hasBeenLaunched = true;
2846 } else {
2847 if (SHOW_APP_STARTING_ICON) {
2848 mWindowManager.setAppStartingWindow(
2849 next, next.packageName, next.theme,
2850 next.nonLocalizedLabel,
2851 next.labelRes, next.icon, null, true);
2852 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002853 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002854 }
2855 startSpecificActivityLocked(next, true, true);
2856 }
2857
2858 return true;
2859 }
2860
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002861 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2862 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863 final int NH = mHistory.size();
2864
2865 int addPos = -1;
2866
2867 if (!newTask) {
2868 // If starting in an existing task, find where that is...
2869 HistoryRecord next = null;
2870 boolean startIt = true;
2871 for (int i = NH-1; i >= 0; i--) {
2872 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2873 if (p.finishing) {
2874 continue;
2875 }
2876 if (p.task == r.task) {
2877 // Here it is! Now, if this is not yet visible to the
2878 // user, then just add it without starting; it will
2879 // get started when the user navigates back to it.
2880 addPos = i+1;
2881 if (!startIt) {
2882 mHistory.add(addPos, r);
2883 r.inHistory = true;
2884 r.task.numActivities++;
2885 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2886 r.info.screenOrientation, r.fullscreen);
2887 if (VALIDATE_TOKENS) {
2888 mWindowManager.validateAppTokens(mHistory);
2889 }
2890 return;
2891 }
2892 break;
2893 }
2894 if (p.fullscreen) {
2895 startIt = false;
2896 }
2897 next = p;
2898 }
2899 }
2900
2901 // Place a new activity at top of stack, so it is next to interact
2902 // with the user.
2903 if (addPos < 0) {
2904 addPos = mHistory.size();
2905 }
2906
2907 // If we are not placing the new activity frontmost, we do not want
2908 // to deliver the onUserLeaving callback to the actual frontmost
2909 // activity
2910 if (addPos < NH) {
2911 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002912 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002913 }
2914
2915 // Slot the activity into the history stack and proceed
2916 mHistory.add(addPos, r);
2917 r.inHistory = true;
2918 r.frontOfTask = newTask;
2919 r.task.numActivities++;
2920 if (NH > 0) {
2921 // We want to show the starting preview window if we are
2922 // switching to a new task, or the next activity's process is
2923 // not currently running.
2924 boolean showStartingIcon = newTask;
2925 ProcessRecord proc = r.app;
2926 if (proc == null) {
2927 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2928 }
2929 if (proc == null || proc.thread == null) {
2930 showStartingIcon = true;
2931 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002932 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002934 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2935 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2936 mNoAnimActivities.add(r);
2937 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2938 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2939 mNoAnimActivities.remove(r);
2940 } else {
2941 mWindowManager.prepareAppTransition(newTask
2942 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2943 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2944 mNoAnimActivities.remove(r);
2945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946 mWindowManager.addAppToken(
2947 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2948 boolean doShow = true;
2949 if (newTask) {
2950 // Even though this activity is starting fresh, we still need
2951 // to reset it to make sure we apply affinities to move any
2952 // existing activities from other tasks in to it.
2953 // If the caller has requested that the target task be
2954 // reset, then do so.
2955 if ((r.intent.getFlags()
2956 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2957 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002958 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 }
2960 }
2961 if (SHOW_APP_STARTING_ICON && doShow) {
2962 // Figure out if we are transitioning from another activity that is
2963 // "has the same starting icon" as the next one. This allows the
2964 // window manager to keep the previous window it had previously
2965 // created, if it still had one.
2966 HistoryRecord prev = mResumedActivity;
2967 if (prev != null) {
2968 // We don't want to reuse the previous starting preview if:
2969 // (1) The current activity is in a different task.
2970 if (prev.task != r.task) prev = null;
2971 // (2) The current activity is already displayed.
2972 else if (prev.nowVisible) prev = null;
2973 }
2974 mWindowManager.setAppStartingWindow(
2975 r, r.packageName, r.theme, r.nonLocalizedLabel,
2976 r.labelRes, r.icon, prev, showStartingIcon);
2977 }
2978 } else {
2979 // If this is the first activity, don't do any fancy animations,
2980 // because there is nothing for it to animate on top of.
2981 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2982 r.info.screenOrientation, r.fullscreen);
2983 }
2984 if (VALIDATE_TOKENS) {
2985 mWindowManager.validateAppTokens(mHistory);
2986 }
2987
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002988 if (doResume) {
2989 resumeTopActivityLocked(null);
2990 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 }
2992
2993 /**
2994 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002995 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2996 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 * an instance of that activity in the stack and, if found, finish all
2998 * activities on top of it and return the instance.
2999 *
3000 * @param newR Description of the new activity being started.
3001 * @return Returns the old activity that should be continue to be used,
3002 * or null if none was found.
3003 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003004 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003005 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003007
3008 // First find the requested task.
3009 while (i > 0) {
3010 i--;
3011 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3012 if (r.task.taskId == taskId) {
3013 i++;
3014 break;
3015 }
3016 }
3017
3018 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 while (i > 0) {
3020 i--;
3021 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3022 if (r.finishing) {
3023 continue;
3024 }
3025 if (r.task.taskId != taskId) {
3026 return null;
3027 }
3028 if (r.realActivity.equals(newR.realActivity)) {
3029 // Here it is! Now finish everything in front...
3030 HistoryRecord ret = r;
3031 if (doClear) {
3032 while (i < (mHistory.size()-1)) {
3033 i++;
3034 r = (HistoryRecord)mHistory.get(i);
3035 if (r.finishing) {
3036 continue;
3037 }
3038 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3039 null, "clear")) {
3040 i--;
3041 }
3042 }
3043 }
3044
3045 // Finally, if this is a normal launch mode (that is, not
3046 // expecting onNewIntent()), then we will finish the current
3047 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003048 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3049 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003050 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003051 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003053 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 null, "clear");
3055 }
3056 return null;
3057 }
3058 }
3059
3060 return ret;
3061 }
3062 }
3063
3064 return null;
3065 }
3066
3067 /**
3068 * Find the activity in the history stack within the given task. Returns
3069 * the index within the history at which it's found, or < 0 if not found.
3070 */
3071 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3072 int i = mHistory.size();
3073 while (i > 0) {
3074 i--;
3075 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3076 if (candidate.task.taskId != task) {
3077 break;
3078 }
3079 if (candidate.realActivity.equals(r.realActivity)) {
3080 return i;
3081 }
3082 }
3083
3084 return -1;
3085 }
3086
3087 /**
3088 * Reorder the history stack so that the activity at the given index is
3089 * brought to the front.
3090 */
3091 private final HistoryRecord moveActivityToFrontLocked(int where) {
3092 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3093 int top = mHistory.size();
3094 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3095 mHistory.add(top, newTop);
3096 oldTop.frontOfTask = false;
3097 newTop.frontOfTask = true;
3098 return newTop;
3099 }
3100
3101 /**
3102 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3103 * method will be called at the proper time.
3104 */
3105 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3106 boolean sent = false;
3107 if (r.state == ActivityState.RESUMED
3108 && r.app != null && r.app.thread != null) {
3109 try {
3110 ArrayList<Intent> ar = new ArrayList<Intent>();
3111 ar.add(new Intent(intent));
3112 r.app.thread.scheduleNewIntent(ar, r);
3113 sent = true;
3114 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003115 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116 }
3117 }
3118 if (!sent) {
3119 r.addNewIntentLocked(new Intent(intent));
3120 }
3121 }
3122
3123 private final void logStartActivity(int tag, HistoryRecord r,
3124 TaskRecord task) {
3125 EventLog.writeEvent(tag,
3126 System.identityHashCode(r), task.taskId,
3127 r.shortComponentName, r.intent.getAction(),
3128 r.intent.getType(), r.intent.getDataString(),
3129 r.intent.getFlags());
3130 }
3131
3132 private final int startActivityLocked(IApplicationThread caller,
3133 Intent intent, String resolvedType,
3134 Uri[] grantedUriPermissions,
3135 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3136 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003137 int callingPid, int callingUid, boolean onlyIfNeeded,
3138 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003139 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140
3141 HistoryRecord sourceRecord = null;
3142 HistoryRecord resultRecord = null;
3143 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003144 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003145 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003146 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3147 if (index >= 0) {
3148 sourceRecord = (HistoryRecord)mHistory.get(index);
3149 if (requestCode >= 0 && !sourceRecord.finishing) {
3150 resultRecord = sourceRecord;
3151 }
3152 }
3153 }
3154
3155 int launchFlags = intent.getFlags();
3156
3157 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3158 && sourceRecord != null) {
3159 // Transfer the result target from the source activity to the new
3160 // one being started, including any failures.
3161 if (requestCode >= 0) {
3162 return START_FORWARD_AND_REQUEST_CONFLICT;
3163 }
3164 resultRecord = sourceRecord.resultTo;
3165 resultWho = sourceRecord.resultWho;
3166 requestCode = sourceRecord.requestCode;
3167 sourceRecord.resultTo = null;
3168 if (resultRecord != null) {
3169 resultRecord.removeResultsLocked(
3170 sourceRecord, resultWho, requestCode);
3171 }
3172 }
3173
3174 int err = START_SUCCESS;
3175
3176 if (intent.getComponent() == null) {
3177 // We couldn't find a class that can handle the given Intent.
3178 // That's the end of that!
3179 err = START_INTENT_NOT_RESOLVED;
3180 }
3181
3182 if (err == START_SUCCESS && aInfo == null) {
3183 // We couldn't find the specific class specified in the Intent.
3184 // Also the end of the line.
3185 err = START_CLASS_NOT_FOUND;
3186 }
3187
3188 ProcessRecord callerApp = null;
3189 if (err == START_SUCCESS && caller != null) {
3190 callerApp = getRecordForAppLocked(caller);
3191 if (callerApp != null) {
3192 callingPid = callerApp.pid;
3193 callingUid = callerApp.info.uid;
3194 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003195 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003196 + " (pid=" + callingPid + ") when starting: "
3197 + intent.toString());
3198 err = START_PERMISSION_DENIED;
3199 }
3200 }
3201
3202 if (err != START_SUCCESS) {
3203 if (resultRecord != null) {
3204 sendActivityResultLocked(-1,
3205 resultRecord, resultWho, requestCode,
3206 Activity.RESULT_CANCELED, null);
3207 }
3208 return err;
3209 }
3210
3211 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3212 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3213 if (perm != PackageManager.PERMISSION_GRANTED) {
3214 if (resultRecord != null) {
3215 sendActivityResultLocked(-1,
3216 resultRecord, resultWho, requestCode,
3217 Activity.RESULT_CANCELED, null);
3218 }
3219 String msg = "Permission Denial: starting " + intent.toString()
3220 + " from " + callerApp + " (pid=" + callingPid
3221 + ", uid=" + callingUid + ")"
3222 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003223 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003224 throw new SecurityException(msg);
3225 }
3226
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003227 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003228 boolean abort = false;
3229 try {
3230 // The Intent we give to the watcher has the extra data
3231 // stripped off, since it can contain private information.
3232 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003233 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234 aInfo.applicationInfo.packageName);
3235 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003236 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 }
3238
3239 if (abort) {
3240 if (resultRecord != null) {
3241 sendActivityResultLocked(-1,
3242 resultRecord, resultWho, requestCode,
3243 Activity.RESULT_CANCELED, null);
3244 }
3245 // We pretend to the caller that it was really started, but
3246 // they will just get a cancel result.
3247 return START_SUCCESS;
3248 }
3249 }
3250
3251 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3252 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003253 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003254
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003255 if (mResumedActivity == null
3256 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3257 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3258 PendingActivityLaunch pal = new PendingActivityLaunch();
3259 pal.r = r;
3260 pal.sourceRecord = sourceRecord;
3261 pal.grantedUriPermissions = grantedUriPermissions;
3262 pal.grantedMode = grantedMode;
3263 pal.onlyIfNeeded = onlyIfNeeded;
3264 mPendingActivityLaunches.add(pal);
3265 return START_SWITCHES_CANCELED;
3266 }
3267 }
3268
3269 if (mDidAppSwitch) {
3270 // This is the second allowed switch since we stopped switches,
3271 // so now just generally allow switches. Use case: user presses
3272 // home (switches disabled, switch to home, mDidAppSwitch now true);
3273 // user taps a home icon (coming from home so allowed, we hit here
3274 // and now allow anyone to switch again).
3275 mAppSwitchesAllowedTime = 0;
3276 } else {
3277 mDidAppSwitch = true;
3278 }
3279
3280 doPendingActivityLaunchesLocked(false);
3281
3282 return startActivityUncheckedLocked(r, sourceRecord,
3283 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3284 }
3285
3286 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3287 final int N = mPendingActivityLaunches.size();
3288 if (N <= 0) {
3289 return;
3290 }
3291 for (int i=0; i<N; i++) {
3292 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3293 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3294 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3295 doResume && i == (N-1));
3296 }
3297 mPendingActivityLaunches.clear();
3298 }
3299
3300 private final int startActivityUncheckedLocked(HistoryRecord r,
3301 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3302 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3303 final Intent intent = r.intent;
3304 final int callingUid = r.launchedFromUid;
3305
3306 int launchFlags = intent.getFlags();
3307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 // We'll invoke onUserLeaving before onPause only if the launching
3309 // activity did not explicitly state that this is an automated launch.
3310 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003311 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 "startActivity() => mUserLeaving=" + mUserLeaving);
3313
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003314 // If the caller has asked not to resume at this point, we make note
3315 // of this in the record so that we can skip it when trying to find
3316 // the top running activity.
3317 if (!doResume) {
3318 r.delayedResume = true;
3319 }
3320
3321 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3322 != 0 ? r : null;
3323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 // If the onlyIfNeeded flag is set, then we can do this if the activity
3325 // being launched is the same as the one making the call... or, as
3326 // a special case, if we do not know the caller then we count the
3327 // current top activity as the caller.
3328 if (onlyIfNeeded) {
3329 HistoryRecord checkedCaller = sourceRecord;
3330 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003331 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 }
3333 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3334 // Caller is not the same as launcher, so always needed.
3335 onlyIfNeeded = false;
3336 }
3337 }
3338
3339 if (grantedUriPermissions != null && callingUid > 0) {
3340 for (int i=0; i<grantedUriPermissions.length; i++) {
3341 grantUriPermissionLocked(callingUid, r.packageName,
3342 grantedUriPermissions[i], grantedMode, r);
3343 }
3344 }
3345
3346 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3347 intent, r);
3348
3349 if (sourceRecord == null) {
3350 // This activity is not being started from another... in this
3351 // case we -always- start a new task.
3352 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003353 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 -08003354 + intent);
3355 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3356 }
3357 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3358 // The original activity who is starting us is running as a single
3359 // instance... this new activity it is starting must go on its
3360 // own task.
3361 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3362 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3363 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3364 // The activity being started is a single instance... it always
3365 // gets launched into its own task.
3366 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3367 }
3368
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003369 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 // For whatever reason this activity is being launched into a new
3371 // task... yet the caller has requested a result back. Well, that
3372 // is pretty messed up, so instead immediately send back a cancel
3373 // and let the new task continue launched as normal without a
3374 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003375 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003376 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003377 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003378 Activity.RESULT_CANCELED, null);
3379 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003380 }
3381
3382 boolean addingToTask = false;
3383 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3384 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3385 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3386 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3387 // If bring to front is requested, and no result is requested, and
3388 // we can find a task that was started with this same
3389 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003390 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 // See if there is a task to bring to the front. If this is
3392 // a SINGLE_INSTANCE activity, there can be one and only one
3393 // instance of it in the history, and it is always in its own
3394 // unique task, so we do a special search.
3395 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3396 ? findTaskLocked(intent, r.info)
3397 : findActivityLocked(intent, r.info);
3398 if (taskTop != null) {
3399 if (taskTop.task.intent == null) {
3400 // This task was started because of movement of
3401 // the activity based on affinity... now that we
3402 // are actually launching it, we can assign the
3403 // base intent.
3404 taskTop.task.setIntent(intent, r.info);
3405 }
3406 // If the target task is not in the front, then we need
3407 // to bring it to the front... except... well, with
3408 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3409 // to have the same behavior as if a new instance was
3410 // being started, which means not bringing it to the front
3411 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003412 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003413 if (curTop.task != taskTop.task) {
3414 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3415 boolean callerAtFront = sourceRecord == null
3416 || curTop.task == sourceRecord.task;
3417 if (callerAtFront) {
3418 // We really do want to push this one into the
3419 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003420 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 }
3422 }
3423 // If the caller has requested that the target task be
3424 // reset, then do so.
3425 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3426 taskTop = resetTaskIfNeededLocked(taskTop, r);
3427 }
3428 if (onlyIfNeeded) {
3429 // We don't need to start a new activity, and
3430 // the client said not to do anything if that
3431 // is the case, so this is it! And for paranoia, make
3432 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003433 if (doResume) {
3434 resumeTopActivityLocked(null);
3435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003436 return START_RETURN_INTENT_TO_CALLER;
3437 }
3438 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3439 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3440 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3441 // In this situation we want to remove all activities
3442 // from the task up to the one being started. In most
3443 // cases this means we are resetting the task to its
3444 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003445 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003446 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003447 if (top != null) {
3448 if (top.frontOfTask) {
3449 // Activity aliases may mean we use different
3450 // intents for the top activity, so make sure
3451 // the task now has the identity of the new
3452 // intent.
3453 top.task.setIntent(r.intent, r.info);
3454 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003455 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 deliverNewIntentLocked(top, r.intent);
3457 } else {
3458 // A special case: we need to
3459 // start the activity because it is not currently
3460 // running, and the caller has asked to clear the
3461 // current task to have this activity at the top.
3462 addingToTask = true;
3463 // Now pretend like this activity is being started
3464 // by the top of its task, so it is put in the
3465 // right place.
3466 sourceRecord = taskTop;
3467 }
3468 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3469 // In this case the top activity on the task is the
3470 // same as the one being launched, so we take that
3471 // as a request to bring the task to the foreground.
3472 // If the top activity in the task is the root
3473 // activity, deliver this new intent to it if it
3474 // desires.
3475 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3476 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003477 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 if (taskTop.frontOfTask) {
3479 taskTop.task.setIntent(r.intent, r.info);
3480 }
3481 deliverNewIntentLocked(taskTop, r.intent);
3482 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3483 // In this case we are launching the root activity
3484 // of the task, but with a different intent. We
3485 // should start a new instance on top.
3486 addingToTask = true;
3487 sourceRecord = taskTop;
3488 }
3489 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3490 // In this case an activity is being launched in to an
3491 // existing task, without resetting that task. This
3492 // is typically the situation of launching an activity
3493 // from a notification or shortcut. We want to place
3494 // the new activity on top of the current task.
3495 addingToTask = true;
3496 sourceRecord = taskTop;
3497 } else if (!taskTop.task.rootWasReset) {
3498 // In this case we are launching in to an existing task
3499 // that has not yet been started from its front door.
3500 // The current task has been brought to the front.
3501 // Ideally, we'd probably like to place this new task
3502 // at the bottom of its stack, but that's a little hard
3503 // to do with the current organization of the code so
3504 // for now we'll just drop it.
3505 taskTop.task.setIntent(r.intent, r.info);
3506 }
3507 if (!addingToTask) {
3508 // We didn't do anything... but it was needed (a.k.a., client
3509 // don't use that intent!) And for paranoia, make
3510 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003511 if (doResume) {
3512 resumeTopActivityLocked(null);
3513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 return START_TASK_TO_FRONT;
3515 }
3516 }
3517 }
3518 }
3519
3520 //String uri = r.intent.toURI();
3521 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003522 //Slog.i(TAG, "Given intent: " + r.intent);
3523 //Slog.i(TAG, "URI is: " + uri);
3524 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003525
3526 if (r.packageName != null) {
3527 // If the activity being launched is the same as the one currently
3528 // at the top, then we need to check if it should only be launched
3529 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003530 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3531 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003532 if (top.realActivity.equals(r.realActivity)) {
3533 if (top.app != null && top.app.thread != null) {
3534 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3535 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3536 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003537 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538 // For paranoia, make sure we have correctly
3539 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003540 if (doResume) {
3541 resumeTopActivityLocked(null);
3542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 if (onlyIfNeeded) {
3544 // We don't need to start a new activity, and
3545 // the client said not to do anything if that
3546 // is the case, so this is it!
3547 return START_RETURN_INTENT_TO_CALLER;
3548 }
3549 deliverNewIntentLocked(top, r.intent);
3550 return START_DELIVERED_TO_TOP;
3551 }
3552 }
3553 }
3554 }
3555
3556 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003557 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003558 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003559 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003560 Activity.RESULT_CANCELED, null);
3561 }
3562 return START_CLASS_NOT_FOUND;
3563 }
3564
3565 boolean newTask = false;
3566
3567 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003568 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003569 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3570 // todo: should do better management of integers.
3571 mCurTask++;
3572 if (mCurTask <= 0) {
3573 mCurTask = 1;
3574 }
3575 r.task = new TaskRecord(mCurTask, r.info, intent,
3576 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003577 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 + " in new task " + r.task);
3579 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003580 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581
3582 } else if (sourceRecord != null) {
3583 if (!addingToTask &&
3584 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3585 // In this case, we are adding the activity to an existing
3586 // task, but the caller has asked to clear that task if the
3587 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003588 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003589 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003591 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003592 deliverNewIntentLocked(top, r.intent);
3593 // For paranoia, make sure we have correctly
3594 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003595 if (doResume) {
3596 resumeTopActivityLocked(null);
3597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003598 return START_DELIVERED_TO_TOP;
3599 }
3600 } else if (!addingToTask &&
3601 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3602 // In this case, we are launching an activity in our own task
3603 // that may already be running somewhere in the history, and
3604 // we want to shuffle it to the front of the stack if so.
3605 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3606 if (where >= 0) {
3607 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003608 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003610 if (doResume) {
3611 resumeTopActivityLocked(null);
3612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 return START_DELIVERED_TO_TOP;
3614 }
3615 }
3616 // An existing activity is starting this new activity, so we want
3617 // to keep the new one in the same task as the one that is starting
3618 // it.
3619 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003620 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 + " in existing task " + r.task);
3622
3623 } else {
3624 // This not being started from an existing activity, and not part
3625 // of a new task... just put it in the top task, though these days
3626 // this case should never happen.
3627 final int N = mHistory.size();
3628 HistoryRecord prev =
3629 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3630 r.task = prev != null
3631 ? prev.task
3632 : new TaskRecord(mCurTask, r.info, intent,
3633 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003634 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003635 + " in new guessed " + r.task);
3636 }
3637 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003638 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003639 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003640 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003641 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 return START_SUCCESS;
3643 }
3644
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003645 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3646 long thisTime, long totalTime) {
3647 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3648 WaitResult w = mWaitingActivityLaunched.get(i);
3649 w.timeout = timeout;
3650 if (r != null) {
3651 w.who = new ComponentName(r.info.packageName, r.info.name);
3652 }
3653 w.thisTime = thisTime;
3654 w.totalTime = totalTime;
3655 }
3656 notify();
3657 }
3658
3659 void reportActivityVisibleLocked(HistoryRecord r) {
3660 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3661 WaitResult w = mWaitingActivityVisible.get(i);
3662 w.timeout = false;
3663 if (r != null) {
3664 w.who = new ComponentName(r.info.packageName, r.info.name);
3665 }
3666 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3667 w.thisTime = w.totalTime;
3668 }
3669 notify();
3670 }
3671
3672 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3674 int grantedMode, IBinder resultTo,
3675 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003676 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003677 // Refuse possible leaked file descriptors
3678 if (intent != null && intent.hasFileDescriptors()) {
3679 throw new IllegalArgumentException("File descriptors passed in Intent");
3680 }
3681
The Android Open Source Project4df24232009-03-05 14:34:35 -08003682 final boolean componentSpecified = intent.getComponent() != null;
3683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 // Don't modify the client's object!
3685 intent = new Intent(intent);
3686
3687 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 ActivityInfo aInfo;
3689 try {
3690 ResolveInfo rInfo =
3691 ActivityThread.getPackageManager().resolveIntent(
3692 intent, resolvedType,
3693 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003694 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 aInfo = rInfo != null ? rInfo.activityInfo : null;
3696 } catch (RemoteException e) {
3697 aInfo = null;
3698 }
3699
3700 if (aInfo != null) {
3701 // Store the found target back into the intent, because now that
3702 // we have it we never want to do this again. For example, if the
3703 // user navigates back to this point in the history, we should
3704 // always restart the exact same activity.
3705 intent.setComponent(new ComponentName(
3706 aInfo.applicationInfo.packageName, aInfo.name));
3707
3708 // Don't debug things in the system process
3709 if (debug) {
3710 if (!aInfo.processName.equals("system")) {
3711 setDebugApp(aInfo.processName, true, false);
3712 }
3713 }
3714 }
3715
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003716 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003717 int callingPid;
3718 int callingUid;
3719 if (caller == null) {
3720 callingPid = Binder.getCallingPid();
3721 callingUid = Binder.getCallingUid();
3722 } else {
3723 callingPid = callingUid = -1;
3724 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003725
3726 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003727 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3728 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003730 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003732 int res = startActivityLocked(caller, intent, resolvedType,
3733 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003734 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003735 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003736
Dianne Hackborne2522462010-03-29 18:41:30 -07003737 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003738 // If the caller also wants to switch to a new configuration,
3739 // do so now. This allows a clean switch, as we are waiting
3740 // for the current activity to pause (so we will not destroy
3741 // it), and have not yet started the next activity.
3742 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3743 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003744 mConfigWillChange = false;
3745 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3746 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003747 updateConfigurationLocked(config, null);
3748 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003751
3752 if (outResult != null) {
3753 outResult.result = res;
3754 if (res == IActivityManager.START_SUCCESS) {
3755 mWaitingActivityLaunched.add(outResult);
3756 do {
3757 try {
3758 wait();
3759 } catch (InterruptedException e) {
3760 }
3761 } while (!outResult.timeout && outResult.who == null);
3762 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3763 HistoryRecord r = this.topRunningActivityLocked(null);
3764 if (r.nowVisible) {
3765 outResult.timeout = false;
3766 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3767 outResult.totalTime = 0;
3768 outResult.thisTime = 0;
3769 } else {
3770 outResult.thisTime = SystemClock.uptimeMillis();
3771 mWaitingActivityVisible.add(outResult);
3772 do {
3773 try {
3774 wait();
3775 } catch (InterruptedException e) {
3776 }
3777 } while (!outResult.timeout && outResult.who == null);
3778 }
3779 }
3780 }
3781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782 return res;
3783 }
3784 }
3785
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003786 public final int startActivity(IApplicationThread caller,
3787 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3788 int grantedMode, IBinder resultTo,
3789 String resultWho, int requestCode, boolean onlyIfNeeded,
3790 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003791 return startActivityMayWait(caller, intent, resolvedType,
3792 grantedUriPermissions, grantedMode, resultTo, resultWho,
3793 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003794 }
3795
3796 public final WaitResult startActivityAndWait(IApplicationThread caller,
3797 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3798 int grantedMode, IBinder resultTo,
3799 String resultWho, int requestCode, boolean onlyIfNeeded,
3800 boolean debug) {
3801 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003802 startActivityMayWait(caller, intent, resolvedType,
3803 grantedUriPermissions, grantedMode, resultTo, resultWho,
3804 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003805 return res;
3806 }
3807
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003808 public final int startActivityWithConfig(IApplicationThread caller,
3809 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3810 int grantedMode, IBinder resultTo,
3811 String resultWho, int requestCode, boolean onlyIfNeeded,
3812 boolean debug, Configuration config) {
3813 return startActivityMayWait(caller, intent, resolvedType,
3814 grantedUriPermissions, grantedMode, resultTo, resultWho,
3815 requestCode, onlyIfNeeded, debug, null, config);
3816 }
3817
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003818 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003819 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003820 IBinder resultTo, String resultWho, int requestCode,
3821 int flagsMask, int flagsValues) {
3822 // Refuse possible leaked file descriptors
3823 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3824 throw new IllegalArgumentException("File descriptors passed in Intent");
3825 }
3826
3827 IIntentSender sender = intent.getTarget();
3828 if (!(sender instanceof PendingIntentRecord)) {
3829 throw new IllegalArgumentException("Bad PendingIntent object");
3830 }
3831
3832 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003833
3834 synchronized (this) {
3835 // If this is coming from the currently resumed activity, it is
3836 // effectively saying that app switches are allowed at this point.
3837 if (mResumedActivity != null
3838 && mResumedActivity.info.applicationInfo.uid ==
3839 Binder.getCallingUid()) {
3840 mAppSwitchesAllowedTime = 0;
3841 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003842 }
3843
3844 return pir.sendInner(0, fillInIntent, resolvedType,
3845 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3846 }
3847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003848 public boolean startNextMatchingActivity(IBinder callingActivity,
3849 Intent intent) {
3850 // Refuse possible leaked file descriptors
3851 if (intent != null && intent.hasFileDescriptors() == true) {
3852 throw new IllegalArgumentException("File descriptors passed in Intent");
3853 }
3854
3855 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003856 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003857 if (index < 0) {
3858 return false;
3859 }
3860 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3861 if (r.app == null || r.app.thread == null) {
3862 // The caller is not running... d'oh!
3863 return false;
3864 }
3865 intent = new Intent(intent);
3866 // The caller is not allowed to change the data.
3867 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3868 // And we are resetting to find the next component...
3869 intent.setComponent(null);
3870
3871 ActivityInfo aInfo = null;
3872 try {
3873 List<ResolveInfo> resolves =
3874 ActivityThread.getPackageManager().queryIntentActivities(
3875 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003876 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877
3878 // Look for the original activity in the list...
3879 final int N = resolves != null ? resolves.size() : 0;
3880 for (int i=0; i<N; i++) {
3881 ResolveInfo rInfo = resolves.get(i);
3882 if (rInfo.activityInfo.packageName.equals(r.packageName)
3883 && rInfo.activityInfo.name.equals(r.info.name)) {
3884 // We found the current one... the next matching is
3885 // after it.
3886 i++;
3887 if (i<N) {
3888 aInfo = resolves.get(i).activityInfo;
3889 }
3890 break;
3891 }
3892 }
3893 } catch (RemoteException e) {
3894 }
3895
3896 if (aInfo == null) {
3897 // Nobody who is next!
3898 return false;
3899 }
3900
3901 intent.setComponent(new ComponentName(
3902 aInfo.applicationInfo.packageName, aInfo.name));
3903 intent.setFlags(intent.getFlags()&~(
3904 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3905 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3906 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3907 Intent.FLAG_ACTIVITY_NEW_TASK));
3908
3909 // Okay now we need to start the new activity, replacing the
3910 // currently running activity. This is a little tricky because
3911 // we want to start the new one as if the current one is finished,
3912 // but not finish the current one first so that there is no flicker.
3913 // And thus...
3914 final boolean wasFinishing = r.finishing;
3915 r.finishing = true;
3916
3917 // Propagate reply information over to the new activity.
3918 final HistoryRecord resultTo = r.resultTo;
3919 final String resultWho = r.resultWho;
3920 final int requestCode = r.requestCode;
3921 r.resultTo = null;
3922 if (resultTo != null) {
3923 resultTo.removeResultsLocked(r, resultWho, requestCode);
3924 }
3925
3926 final long origId = Binder.clearCallingIdentity();
3927 // XXX we are not dealing with propagating grantedUriPermissions...
3928 // those are not yet exposed to user code, so there is no need.
3929 int res = startActivityLocked(r.app.thread, intent,
3930 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003931 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 Binder.restoreCallingIdentity(origId);
3933
3934 r.finishing = wasFinishing;
3935 if (res != START_SUCCESS) {
3936 return false;
3937 }
3938 return true;
3939 }
3940 }
3941
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003942 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 Intent intent, String resolvedType, IBinder resultTo,
3944 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003945
3946 // This is so super not safe, that only the system (or okay root)
3947 // can do it.
3948 final int callingUid = Binder.getCallingUid();
3949 if (callingUid != 0 && callingUid != Process.myUid()) {
3950 throw new SecurityException(
3951 "startActivityInPackage only available to the system");
3952 }
3953
The Android Open Source Project4df24232009-03-05 14:34:35 -08003954 final boolean componentSpecified = intent.getComponent() != null;
3955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003956 // Don't modify the client's object!
3957 intent = new Intent(intent);
3958
3959 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 ActivityInfo aInfo;
3961 try {
3962 ResolveInfo rInfo =
3963 ActivityThread.getPackageManager().resolveIntent(
3964 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003965 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 aInfo = rInfo != null ? rInfo.activityInfo : null;
3967 } catch (RemoteException e) {
3968 aInfo = null;
3969 }
3970
3971 if (aInfo != null) {
3972 // Store the found target back into the intent, because now that
3973 // we have it we never want to do this again. For example, if the
3974 // user navigates back to this point in the history, we should
3975 // always restart the exact same activity.
3976 intent.setComponent(new ComponentName(
3977 aInfo.applicationInfo.packageName, aInfo.name));
3978 }
3979
3980 synchronized(this) {
3981 return startActivityLocked(null, intent, resolvedType,
3982 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003983 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003984 }
3985 }
3986
Josh Bartel7f208742010-02-25 11:01:44 -06003987 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 // Remove any existing entries that are the same kind of task.
3989 int N = mRecentTasks.size();
3990 for (int i=0; i<N; i++) {
3991 TaskRecord tr = mRecentTasks.get(i);
3992 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3993 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3994 mRecentTasks.remove(i);
3995 i--;
3996 N--;
3997 if (task.intent == null) {
3998 // If the new recent task we are adding is not fully
3999 // specified, then replace it with the existing recent task.
4000 task = tr;
4001 }
4002 }
4003 }
4004 if (N >= MAX_RECENT_TASKS) {
4005 mRecentTasks.remove(N-1);
4006 }
4007 mRecentTasks.add(0, task);
4008 }
4009
4010 public void setRequestedOrientation(IBinder token,
4011 int requestedOrientation) {
4012 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004013 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004014 if (index < 0) {
4015 return;
4016 }
4017 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4018 final long origId = Binder.clearCallingIdentity();
4019 mWindowManager.setAppOrientation(r, requestedOrientation);
4020 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07004021 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 r.mayFreezeScreenLocked(r.app) ? r : null);
4023 if (config != null) {
4024 r.frozenBeforeDestroy = true;
4025 if (!updateConfigurationLocked(config, r)) {
4026 resumeTopActivityLocked(null);
4027 }
4028 }
4029 Binder.restoreCallingIdentity(origId);
4030 }
4031 }
4032
4033 public int getRequestedOrientation(IBinder token) {
4034 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004035 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004036 if (index < 0) {
4037 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4038 }
4039 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4040 return mWindowManager.getAppOrientation(r);
4041 }
4042 }
4043
4044 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004045 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004046 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4047 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4048 if (!r.finishing) {
4049 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4050 "no-history");
4051 }
4052 } else if (r.app != null && r.app.thread != null) {
4053 if (mFocusedActivity == r) {
4054 setFocusedActivityLocked(topRunningActivityLocked(null));
4055 }
4056 r.resumeKeyDispatchingLocked();
4057 try {
4058 r.stopped = false;
4059 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004060 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061 TAG, "Stopping visible=" + r.visible + " for " + r);
4062 if (!r.visible) {
4063 mWindowManager.setAppVisibility(r, false);
4064 }
4065 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4066 } catch (Exception e) {
4067 // Maybe just ignore exceptions here... if the process
4068 // has crashed, our death notification will clean things
4069 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004070 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004071 // Just in case, assume it to be stopped.
4072 r.stopped = true;
4073 r.state = ActivityState.STOPPED;
4074 if (r.configDestroy) {
4075 destroyActivityLocked(r, true);
4076 }
4077 }
4078 }
4079 }
4080
4081 /**
4082 * @return Returns true if the activity is being finished, false if for
4083 * some reason it is being left as-is.
4084 */
4085 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4086 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004087 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 TAG, "Finishing activity: token=" + token
4089 + ", result=" + resultCode + ", data=" + resultData);
4090
Dianne Hackborn75b03852009-06-12 15:43:26 -07004091 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004092 if (index < 0) {
4093 return false;
4094 }
4095 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4096
4097 // Is this the last activity left?
4098 boolean lastActivity = true;
4099 for (int i=mHistory.size()-1; i>=0; i--) {
4100 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4101 if (!p.finishing && p != r) {
4102 lastActivity = false;
4103 break;
4104 }
4105 }
4106
4107 // If this is the last activity, but it is the home activity, then
4108 // just don't finish it.
4109 if (lastActivity) {
4110 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4111 return false;
4112 }
4113 }
4114
4115 finishActivityLocked(r, index, resultCode, resultData, reason);
4116 return true;
4117 }
4118
4119 /**
4120 * @return Returns true if this activity has been removed from the history
4121 * list, or false if it is still in the list and will be removed later.
4122 */
4123 private final boolean finishActivityLocked(HistoryRecord r, int index,
4124 int resultCode, Intent resultData, String reason) {
4125 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004126 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 return false;
4128 }
4129
4130 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004131 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 System.identityHashCode(r),
4133 r.task.taskId, r.shortComponentName, reason);
4134 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004135 if (index < (mHistory.size()-1)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004136 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4137 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004138 if (r.frontOfTask) {
4139 // The next activity is now the front of the task.
4140 next.frontOfTask = true;
4141 }
4142 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4143 // If the caller asked that this activity (and all above it)
4144 // be cleared when the task is reset, don't lose that information,
4145 // but propagate it up to the next activity.
4146 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004148 }
4149 }
4150
4151 r.pauseKeyDispatchingLocked();
4152 if (mFocusedActivity == r) {
4153 setFocusedActivityLocked(topRunningActivityLocked(null));
4154 }
4155
4156 // send the result
4157 HistoryRecord resultTo = r.resultTo;
4158 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004159 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004160 + " who=" + r.resultWho + " req=" + r.requestCode
4161 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 if (r.info.applicationInfo.uid > 0) {
4163 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4164 r.packageName, resultData, r);
4165 }
4166 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4167 resultData);
4168 r.resultTo = null;
4169 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004170 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171
4172 // Make sure this HistoryRecord is not holding on to other resources,
4173 // because clients have remote IPC references to this object so we
4174 // can't assume that will go away and want to avoid circular IPC refs.
4175 r.results = null;
4176 r.pendingResults = null;
4177 r.newIntents = null;
4178 r.icicle = null;
4179
4180 if (mPendingThumbnails.size() > 0) {
4181 // There are clients waiting to receive thumbnails so, in case
4182 // this is an activity that someone is waiting for, add it
4183 // to the pending list so we can correctly update the clients.
4184 mCancelledThumbnails.add(r);
4185 }
4186
4187 if (mResumedActivity == r) {
4188 boolean endTask = index <= 0
4189 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004190 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004191 "Prepare close transition: finishing " + r);
4192 mWindowManager.prepareAppTransition(endTask
4193 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4194 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4195
4196 // Tell window manager to prepare for this one to be removed.
4197 mWindowManager.setAppVisibility(r, false);
4198
4199 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004200 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4201 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 startPausingLocked(false, false);
4203 }
4204
4205 } else if (r.state != ActivityState.PAUSING) {
4206 // If the activity is PAUSING, we will complete the finish once
4207 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004208 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004209 return finishCurrentActivityLocked(r, index,
4210 FINISH_AFTER_PAUSE) == null;
4211 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004212 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004213 }
4214
4215 return false;
4216 }
4217
4218 private static final int FINISH_IMMEDIATELY = 0;
4219 private static final int FINISH_AFTER_PAUSE = 1;
4220 private static final int FINISH_AFTER_VISIBLE = 2;
4221
4222 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4223 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004224 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 if (index < 0) {
4226 return null;
4227 }
4228
4229 return finishCurrentActivityLocked(r, index, mode);
4230 }
4231
4232 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4233 int index, int mode) {
4234 // First things first: if this activity is currently visible,
4235 // and the resumed activity is not yet visible, then hold off on
4236 // finishing until the resumed one becomes visible.
4237 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4238 if (!mStoppingActivities.contains(r)) {
4239 mStoppingActivities.add(r);
4240 if (mStoppingActivities.size() > 3) {
4241 // If we already have a few activities waiting to stop,
4242 // then give up on things going idle and start clearing
4243 // them out.
4244 Message msg = Message.obtain();
4245 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4246 mHandler.sendMessage(msg);
4247 }
4248 }
4249 r.state = ActivityState.STOPPING;
4250 updateOomAdjLocked();
4251 return r;
4252 }
4253
4254 // make sure the record is cleaned out of other places.
4255 mStoppingActivities.remove(r);
4256 mWaitingVisibleActivities.remove(r);
4257 if (mResumedActivity == r) {
4258 mResumedActivity = null;
4259 }
4260 final ActivityState prevState = r.state;
4261 r.state = ActivityState.FINISHING;
4262
4263 if (mode == FINISH_IMMEDIATELY
4264 || prevState == ActivityState.STOPPED
4265 || prevState == ActivityState.INITIALIZING) {
4266 // If this activity is already stopped, we can just finish
4267 // it right now.
4268 return destroyActivityLocked(r, true) ? null : r;
4269 } else {
4270 // Need to go through the full pause cycle to get this
4271 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004272 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004273 mFinishingActivities.add(r);
4274 resumeTopActivityLocked(null);
4275 }
4276 return r;
4277 }
4278
4279 /**
4280 * This is the internal entry point for handling Activity.finish().
4281 *
4282 * @param token The Binder token referencing the Activity we want to finish.
4283 * @param resultCode Result code, if any, from this Activity.
4284 * @param resultData Result data (Intent), if any, from this Activity.
4285 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004286 * @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 -08004287 */
4288 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4289 // Refuse possible leaked file descriptors
4290 if (resultData != null && resultData.hasFileDescriptors() == true) {
4291 throw new IllegalArgumentException("File descriptors passed in Intent");
4292 }
4293
4294 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004295 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004296 // Find the first activity that is not finishing.
4297 HistoryRecord next = topRunningActivityLocked(token, 0);
4298 if (next != null) {
4299 // ask watcher if this is allowed
4300 boolean resumeOK = true;
4301 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004302 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004304 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004305 }
4306
4307 if (!resumeOK) {
4308 return false;
4309 }
4310 }
4311 }
4312 final long origId = Binder.clearCallingIdentity();
4313 boolean res = requestFinishActivityLocked(token, resultCode,
4314 resultData, "app-request");
4315 Binder.restoreCallingIdentity(origId);
4316 return res;
4317 }
4318 }
4319
4320 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4321 String resultWho, int requestCode, int resultCode, Intent data) {
4322
4323 if (callingUid > 0) {
4324 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4325 data, r);
4326 }
4327
Joe Onorato8a9b2202010-02-26 18:56:32 -08004328 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004329 + " : who=" + resultWho + " req=" + requestCode
4330 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004331 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4332 try {
4333 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4334 list.add(new ResultInfo(resultWho, requestCode,
4335 resultCode, data));
4336 r.app.thread.scheduleSendResult(r, list);
4337 return;
4338 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004339 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 }
4341 }
4342
4343 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4344 }
4345
4346 public final void finishSubActivity(IBinder token, String resultWho,
4347 int requestCode) {
4348 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004349 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 if (index < 0) {
4351 return;
4352 }
4353 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4354
4355 final long origId = Binder.clearCallingIdentity();
4356
4357 int i;
4358 for (i=mHistory.size()-1; i>=0; i--) {
4359 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4360 if (r.resultTo == self && r.requestCode == requestCode) {
4361 if ((r.resultWho == null && resultWho == null) ||
4362 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4363 finishActivityLocked(r, i,
4364 Activity.RESULT_CANCELED, null, "request-sub");
4365 }
4366 }
4367 }
4368
4369 Binder.restoreCallingIdentity(origId);
4370 }
4371 }
4372
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004373 public boolean willActivityBeVisible(IBinder token) {
4374 synchronized(this) {
4375 int i;
4376 for (i=mHistory.size()-1; i>=0; i--) {
4377 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4378 if (r == token) {
4379 return true;
4380 }
4381 if (r.fullscreen && !r.finishing) {
4382 return false;
4383 }
4384 }
4385 return true;
4386 }
4387 }
4388
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004389 public void overridePendingTransition(IBinder token, String packageName,
4390 int enterAnim, int exitAnim) {
4391 synchronized(this) {
4392 int index = indexOfTokenLocked(token);
4393 if (index < 0) {
4394 return;
4395 }
4396 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4397
4398 final long origId = Binder.clearCallingIdentity();
4399
4400 if (self.state == ActivityState.RESUMED
4401 || self.state == ActivityState.PAUSING) {
4402 mWindowManager.overridePendingAppTransition(packageName,
4403 enterAnim, exitAnim);
4404 }
4405
4406 Binder.restoreCallingIdentity(origId);
4407 }
4408 }
4409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 /**
4411 * Perform clean-up of service connections in an activity record.
4412 */
4413 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4414 // Throw away any services that have been bound by this activity.
4415 if (r.connections != null) {
4416 Iterator<ConnectionRecord> it = r.connections.iterator();
4417 while (it.hasNext()) {
4418 ConnectionRecord c = it.next();
4419 removeConnectionLocked(c, null, r);
4420 }
4421 r.connections = null;
4422 }
4423 }
4424
4425 /**
4426 * Perform the common clean-up of an activity record. This is called both
4427 * as part of destroyActivityLocked() (when destroying the client-side
4428 * representation) and cleaning things up as a result of its hosting
4429 * processing going away, in which case there is no remaining client-side
4430 * state to destroy so only the cleanup here is needed.
4431 */
4432 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4433 if (mResumedActivity == r) {
4434 mResumedActivity = null;
4435 }
4436 if (mFocusedActivity == r) {
4437 mFocusedActivity = null;
4438 }
4439
4440 r.configDestroy = false;
4441 r.frozenBeforeDestroy = false;
4442
4443 // Make sure this record is no longer in the pending finishes list.
4444 // This could happen, for example, if we are trimming activities
4445 // down to the max limit while they are still waiting to finish.
4446 mFinishingActivities.remove(r);
4447 mWaitingVisibleActivities.remove(r);
4448
4449 // Remove any pending results.
4450 if (r.finishing && r.pendingResults != null) {
4451 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4452 PendingIntentRecord rec = apr.get();
4453 if (rec != null) {
4454 cancelIntentSenderLocked(rec, false);
4455 }
4456 }
4457 r.pendingResults = null;
4458 }
4459
4460 if (cleanServices) {
4461 cleanUpActivityServicesLocked(r);
4462 }
4463
4464 if (mPendingThumbnails.size() > 0) {
4465 // There are clients waiting to receive thumbnails so, in case
4466 // this is an activity that someone is waiting for, add it
4467 // to the pending list so we can correctly update the clients.
4468 mCancelledThumbnails.add(r);
4469 }
4470
4471 // Get rid of any pending idle timeouts.
4472 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4473 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4474 }
4475
4476 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4477 if (r.state != ActivityState.DESTROYED) {
4478 mHistory.remove(r);
4479 r.inHistory = false;
4480 r.state = ActivityState.DESTROYED;
4481 mWindowManager.removeAppToken(r);
4482 if (VALIDATE_TOKENS) {
4483 mWindowManager.validateAppTokens(mHistory);
4484 }
4485 cleanUpActivityServicesLocked(r);
4486 removeActivityUriPermissionsLocked(r);
4487 }
4488 }
4489
4490 /**
4491 * Destroy the current CLIENT SIDE instance of an activity. This may be
4492 * called both when actually finishing an activity, or when performing
4493 * a configuration switch where we destroy the current client-side object
4494 * but then create a new client-side object for this same HistoryRecord.
4495 */
4496 private final boolean destroyActivityLocked(HistoryRecord r,
4497 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004498 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004499 TAG, "Removing activity: token=" + r
4500 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004501 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 System.identityHashCode(r),
4503 r.task.taskId, r.shortComponentName);
4504
4505 boolean removedFromHistory = false;
4506
4507 cleanUpActivityLocked(r, false);
4508
Dianne Hackborn03abb812010-01-04 18:43:19 -08004509 final boolean hadApp = r.app != null;
4510
4511 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 if (removeFromApp) {
4513 int idx = r.app.activities.indexOf(r);
4514 if (idx >= 0) {
4515 r.app.activities.remove(idx);
4516 }
4517 if (r.persistent) {
4518 decPersistentCountLocked(r.app);
4519 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004520 if (r.app.activities.size() == 0) {
4521 // No longer have activities, so update location in
4522 // LRU list.
4523 updateLruProcessLocked(r.app, true, false);
4524 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004525 }
4526
4527 boolean skipDestroy = false;
4528
4529 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004530 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4532 r.configChangeFlags);
4533 } catch (Exception e) {
4534 // We can just ignore exceptions here... if the process
4535 // has crashed, our death notification will clean things
4536 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004537 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004538 if (r.finishing) {
4539 removeActivityFromHistoryLocked(r);
4540 removedFromHistory = true;
4541 skipDestroy = true;
4542 }
4543 }
4544
4545 r.app = null;
4546 r.nowVisible = false;
4547
4548 if (r.finishing && !skipDestroy) {
4549 r.state = ActivityState.DESTROYING;
4550 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4551 msg.obj = r;
4552 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4553 } else {
4554 r.state = ActivityState.DESTROYED;
4555 }
4556 } else {
4557 // remove this record from the history.
4558 if (r.finishing) {
4559 removeActivityFromHistoryLocked(r);
4560 removedFromHistory = true;
4561 } else {
4562 r.state = ActivityState.DESTROYED;
4563 }
4564 }
4565
4566 r.configChangeFlags = 0;
4567
Dianne Hackborn03abb812010-01-04 18:43:19 -08004568 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004569 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004570 }
4571
4572 return removedFromHistory;
4573 }
4574
Dianne Hackborn03abb812010-01-04 18:43:19 -08004575 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004577 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004578 TAG, "Removing app " + app + " from list " + list
4579 + " with " + i + " entries");
4580 while (i > 0) {
4581 i--;
4582 HistoryRecord r = (HistoryRecord)list.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) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004586 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004587 list.remove(i);
4588 }
4589 }
4590 }
4591
4592 /**
4593 * Main function for removing an existing process from the activity manager
4594 * as a result of that process going away. Clears out all connections
4595 * to the process.
4596 */
4597 private final void handleAppDiedLocked(ProcessRecord app,
4598 boolean restarting) {
4599 cleanUpApplicationRecordLocked(app, restarting, -1);
4600 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004601 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 }
4603
4604 // Just in case...
4605 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004606 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 mPausingActivity = null;
4608 }
4609 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4610 mLastPausedActivity = null;
4611 }
4612
4613 // Remove this application's activities from active lists.
4614 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4615 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4616 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4617 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4618
4619 boolean atTop = true;
4620 boolean hasVisibleActivities = false;
4621
4622 // Clean out the history list.
4623 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004624 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 TAG, "Removing app " + app + " from history with " + i + " entries");
4626 while (i > 0) {
4627 i--;
4628 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004629 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4631 if (r.app == app) {
4632 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004633 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634 TAG, "Removing this entry! frozen=" + r.haveState
4635 + " finishing=" + r.finishing);
4636 mHistory.remove(i);
4637
4638 r.inHistory = false;
4639 mWindowManager.removeAppToken(r);
4640 if (VALIDATE_TOKENS) {
4641 mWindowManager.validateAppTokens(mHistory);
4642 }
4643 removeActivityUriPermissionsLocked(r);
4644
4645 } else {
4646 // We have the current state for this activity, so
4647 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004648 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004649 TAG, "Keeping entry, setting app to null");
4650 if (r.visible) {
4651 hasVisibleActivities = true;
4652 }
4653 r.app = null;
4654 r.nowVisible = false;
4655 if (!r.haveState) {
4656 r.icicle = null;
4657 }
4658 }
4659
4660 cleanUpActivityLocked(r, true);
4661 r.state = ActivityState.STOPPED;
4662 }
4663 atTop = false;
4664 }
4665
4666 app.activities.clear();
4667
4668 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004669 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 + " running instrumentation " + app.instrumentationClass);
4671 Bundle info = new Bundle();
4672 info.putString("shortMsg", "Process crashed.");
4673 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4674 }
4675
4676 if (!restarting) {
4677 if (!resumeTopActivityLocked(null)) {
4678 // If there was nothing to resume, and we are not already
4679 // restarting this process, but there is a visible activity that
4680 // is hosted by the process... then make sure all visible
4681 // activities are running, taking care of restarting this
4682 // process.
4683 if (hasVisibleActivities) {
4684 ensureActivitiesVisibleLocked(null, 0);
4685 }
4686 }
4687 }
4688 }
4689
4690 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4691 IBinder threadBinder = thread.asBinder();
4692
4693 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004694 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4695 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004696 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4697 return i;
4698 }
4699 }
4700 return -1;
4701 }
4702
4703 private final ProcessRecord getRecordForAppLocked(
4704 IApplicationThread thread) {
4705 if (thread == null) {
4706 return null;
4707 }
4708
4709 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004710 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 }
4712
4713 private final void appDiedLocked(ProcessRecord app, int pid,
4714 IApplicationThread thread) {
4715
4716 mProcDeaths[0]++;
4717
Magnus Edlund7bb25812010-02-24 15:45:06 +01004718 // Clean up already done if the process has been re-started.
4719 if (app.pid == pid && app.thread != null &&
4720 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07004721 if (!app.killedBackground) {
4722 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
4723 + ") has died.");
4724 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08004725 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004726 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 TAG, "Dying app: " + app + ", pid: " + pid
4728 + ", thread: " + thread.asBinder());
4729 boolean doLowMem = app.instrumentationClass == null;
4730 handleAppDiedLocked(app, false);
4731
4732 if (doLowMem) {
4733 // If there are no longer any background processes running,
4734 // and the app that died was not running instrumentation,
4735 // then tell everyone we are now low on memory.
4736 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004737 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4738 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4740 haveBg = true;
4741 break;
4742 }
4743 }
4744
4745 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004746 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004747 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004748 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004749 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4750 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004751 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004752 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4753 // The low memory report is overriding any current
4754 // state for a GC request. Make sure to do
4755 // visible/foreground processes first.
4756 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4757 rec.lastRequestedGc = 0;
4758 } else {
4759 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004760 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004761 rec.reportLowMemory = true;
4762 rec.lastLowMemory = now;
4763 mProcessesToGc.remove(rec);
4764 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 }
4766 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004767 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004768 }
4769 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004770 } else if (app.pid != pid) {
4771 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004772 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004773 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004774 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004775 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004776 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 + thread.asBinder());
4778 }
4779 }
4780
Dan Egnor42471dd2010-01-07 17:25:22 -08004781 /**
4782 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07004783 * @param clearTraces causes the dump file to be erased prior to the new
4784 * traces being written, if true; when false, the new traces will be
4785 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08004786 * @param pids of dalvik VM processes to dump stack traces for
4787 * @return file containing stack traces, or null if no dump file is configured
4788 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07004789 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004790 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4791 if (tracesPath == null || tracesPath.length() == 0) {
4792 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004793 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004794
4795 File tracesFile = new File(tracesPath);
4796 try {
4797 File tracesDir = tracesFile.getParentFile();
4798 if (!tracesDir.exists()) tracesFile.mkdirs();
4799 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4800
Christopher Tate6ee412d2010-05-28 12:01:56 -07004801 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08004802 tracesFile.createNewFile();
4803 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4804 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004805 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004806 return null;
4807 }
4808
4809 // Use a FileObserver to detect when traces finish writing.
4810 // The order of traces is considered important to maintain for legibility.
4811 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4812 public synchronized void onEvent(int event, String path) { notify(); }
4813 };
4814
4815 try {
4816 observer.startWatching();
4817 int num = pids.size();
4818 for (int i = 0; i < num; i++) {
4819 synchronized (observer) {
4820 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4821 observer.wait(200); // Wait for write-close, give up after 200msec
4822 }
4823 }
4824 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004825 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004826 } finally {
4827 observer.stopWatching();
4828 }
4829
4830 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004831 }
4832
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004833 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08004834 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004835 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004836
4837 synchronized (this) {
4838 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4839 if (mShuttingDown) {
4840 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
4841 return;
4842 } else if (app.notResponding) {
4843 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
4844 return;
4845 } else if (app.crashing) {
4846 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
4847 return;
4848 }
4849
4850 // In case we come through here for the same app before completing
4851 // this one, mark as anring now so we will bail out.
4852 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08004853
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004854 // Log the ANR to the event log.
4855 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4856 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08004857
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004858 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4859 pids.add(app.pid);
4860
4861 int parentPid = app.pid;
4862 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4863 if (parentPid != app.pid) pids.add(parentPid);
4864
4865 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08004866
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004867 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4868 ProcessRecord r = mLruProcesses.get(i);
4869 if (r != null && r.thread != null) {
4870 int pid = r.pid;
4871 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
4872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004873 }
4874 }
4875
Christopher Tate6ee412d2010-05-28 12:01:56 -07004876 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08004877
4878 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004879 StringBuilder info = mStringBuilder;
4880 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004881 info.append("ANR in ").append(app.processName);
4882 if (activity != null && activity.shortComponentName != null) {
4883 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004884 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004885 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004887 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004888 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004889 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004890 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892
Dan Egnor42471dd2010-01-07 17:25:22 -08004893 String cpuInfo = null;
4894 if (MONITOR_CPU_USAGE) {
4895 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004896 synchronized (mProcessStatsThread) {
4897 cpuInfo = mProcessStats.printCurrentState();
4898 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004899 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004900 }
4901
Joe Onorato8a9b2202010-02-26 18:56:32 -08004902 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004903 if (tracesFile == null) {
4904 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4905 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4906 }
4907
4908 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4909
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004910 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004911 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004912 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4913 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004914 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004915 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4916 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004917 }
4918 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004919 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004920 }
4921 }
4922
Dan Egnor42471dd2010-01-07 17:25:22 -08004923 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4924 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4925 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004926
4927 synchronized (this) {
4928 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4929 Process.killProcess(app.pid);
4930 return;
4931 }
4932
4933 // Set the app's notResponding state, and look up the errorReportReceiver
4934 makeAppNotRespondingLocked(app,
4935 activity != null ? activity.shortComponentName : null,
4936 annotation != null ? "ANR " + annotation : "ANR",
4937 info.toString());
4938
4939 // Bring up the infamous App Not Responding dialog
4940 Message msg = Message.obtain();
4941 HashMap map = new HashMap();
4942 msg.what = SHOW_NOT_RESPONDING_MSG;
4943 msg.obj = map;
4944 map.put("app", app);
4945 if (activity != null) {
4946 map.put("activity", activity);
4947 }
4948
4949 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08004950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951 }
4952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004953 private final void decPersistentCountLocked(ProcessRecord app)
4954 {
4955 app.persistentActivities--;
4956 if (app.persistentActivities > 0) {
4957 // Still more of 'em...
4958 return;
4959 }
4960 if (app.persistent) {
4961 // Ah, but the application itself is persistent. Whatever!
4962 return;
4963 }
4964
4965 // App is no longer persistent... make sure it and the ones
4966 // following it in the LRU list have the correc oom_adj.
4967 updateOomAdjLocked();
4968 }
4969
4970 public void setPersistent(IBinder token, boolean isPersistent) {
4971 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4972 != PackageManager.PERMISSION_GRANTED) {
4973 String msg = "Permission Denial: setPersistent() from pid="
4974 + Binder.getCallingPid()
4975 + ", uid=" + Binder.getCallingUid()
4976 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004977 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004978 throw new SecurityException(msg);
4979 }
4980
4981 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004982 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004983 if (index < 0) {
4984 return;
4985 }
4986 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4987 ProcessRecord app = r.app;
4988
Joe Onorato8a9b2202010-02-26 18:56:32 -08004989 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 TAG, "Setting persistence " + isPersistent + ": " + r);
4991
4992 if (isPersistent) {
4993 if (r.persistent) {
4994 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004995 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 return;
4997 }
4998 r.persistent = true;
4999 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005000 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 if (app.persistentActivities > 1) {
5002 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005003 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 return;
5005 }
5006 if (app.persistent) {
5007 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005008 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005009 return;
5010 }
5011
5012 // App is now persistent... make sure it and the ones
5013 // following it now have the correct oom_adj.
5014 final long origId = Binder.clearCallingIdentity();
5015 updateOomAdjLocked();
5016 Binder.restoreCallingIdentity(origId);
5017
5018 } else {
5019 if (!r.persistent) {
5020 // Okay okay, I heard you already!
5021 return;
5022 }
5023 r.persistent = false;
5024 final long origId = Binder.clearCallingIdentity();
5025 decPersistentCountLocked(app);
5026 Binder.restoreCallingIdentity(origId);
5027
5028 }
5029 }
5030 }
5031
5032 public boolean clearApplicationUserData(final String packageName,
5033 final IPackageDataObserver observer) {
5034 int uid = Binder.getCallingUid();
5035 int pid = Binder.getCallingPid();
5036 long callingId = Binder.clearCallingIdentity();
5037 try {
5038 IPackageManager pm = ActivityThread.getPackageManager();
5039 int pkgUid = -1;
5040 synchronized(this) {
5041 try {
5042 pkgUid = pm.getPackageUid(packageName);
5043 } catch (RemoteException e) {
5044 }
5045 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005046 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005047 return false;
5048 }
5049 if (uid == pkgUid || checkComponentPermission(
5050 android.Manifest.permission.CLEAR_APP_USER_DATA,
5051 pid, uid, -1)
5052 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005053 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005054 } else {
5055 throw new SecurityException(pid+" does not have permission:"+
5056 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5057 "for process:"+packageName);
5058 }
5059 }
5060
5061 try {
5062 //clear application user data
5063 pm.clearApplicationUserData(packageName, observer);
5064 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5065 Uri.fromParts("package", packageName, null));
5066 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005067 synchronized (this) {
5068 broadcastIntentLocked(null, null, intent,
5069 null, null, 0, null, null, null,
5070 false, false, MY_PID, Process.SYSTEM_UID);
5071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005072 } catch (RemoteException e) {
5073 }
5074 } finally {
5075 Binder.restoreCallingIdentity(callingId);
5076 }
5077 return true;
5078 }
5079
Dianne Hackborn03abb812010-01-04 18:43:19 -08005080 public void killBackgroundProcesses(final String packageName) {
5081 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5082 != PackageManager.PERMISSION_GRANTED &&
5083 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5084 != PackageManager.PERMISSION_GRANTED) {
5085 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005086 + Binder.getCallingPid()
5087 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005088 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005089 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 throw new SecurityException(msg);
5091 }
5092
5093 long callingId = Binder.clearCallingIdentity();
5094 try {
5095 IPackageManager pm = ActivityThread.getPackageManager();
5096 int pkgUid = -1;
5097 synchronized(this) {
5098 try {
5099 pkgUid = pm.getPackageUid(packageName);
5100 } catch (RemoteException e) {
5101 }
5102 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005103 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005104 return;
5105 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005106 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005107 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005108 }
5109 } finally {
5110 Binder.restoreCallingIdentity(callingId);
5111 }
5112 }
5113
5114 public void forceStopPackage(final String packageName) {
5115 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5116 != PackageManager.PERMISSION_GRANTED) {
5117 String msg = "Permission Denial: forceStopPackage() from pid="
5118 + Binder.getCallingPid()
5119 + ", uid=" + Binder.getCallingUid()
5120 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005121 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005122 throw new SecurityException(msg);
5123 }
5124
5125 long callingId = Binder.clearCallingIdentity();
5126 try {
5127 IPackageManager pm = ActivityThread.getPackageManager();
5128 int pkgUid = -1;
5129 synchronized(this) {
5130 try {
5131 pkgUid = pm.getPackageUid(packageName);
5132 } catch (RemoteException e) {
5133 }
5134 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005135 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005136 return;
5137 }
5138 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 }
5140 } finally {
5141 Binder.restoreCallingIdentity(callingId);
5142 }
5143 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005144
5145 /*
5146 * The pkg name and uid have to be specified.
5147 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5148 */
5149 public void killApplicationWithUid(String pkg, int uid) {
5150 if (pkg == null) {
5151 return;
5152 }
5153 // Make sure the uid is valid.
5154 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005155 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005156 return;
5157 }
5158 int callerUid = Binder.getCallingUid();
5159 // Only the system server can kill an application
5160 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005161 // Post an aysnc message to kill the application
5162 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5163 msg.arg1 = uid;
5164 msg.arg2 = 0;
5165 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005166 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005167 } else {
5168 throw new SecurityException(callerUid + " cannot kill pkg: " +
5169 pkg);
5170 }
5171 }
5172
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005173 public void closeSystemDialogs(String reason) {
5174 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5175 if (reason != null) {
5176 intent.putExtra("reason", reason);
5177 }
5178
5179 final int uid = Binder.getCallingUid();
5180 final long origId = Binder.clearCallingIdentity();
5181 synchronized (this) {
5182 int i = mWatchers.beginBroadcast();
5183 while (i > 0) {
5184 i--;
5185 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5186 if (w != null) {
5187 try {
5188 w.closingSystemDialogs(reason);
5189 } catch (RemoteException e) {
5190 }
5191 }
5192 }
5193 mWatchers.finishBroadcast();
5194
Dianne Hackbornffa42482009-09-23 22:20:11 -07005195 mWindowManager.closeSystemDialogs(reason);
5196
5197 for (i=mHistory.size()-1; i>=0; i--) {
5198 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5199 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5200 finishActivityLocked(r, i,
5201 Activity.RESULT_CANCELED, null, "close-sys");
5202 }
5203 }
5204
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005205 broadcastIntentLocked(null, null, intent, null,
5206 null, 0, null, null, null, false, false, -1, uid);
5207 }
5208 Binder.restoreCallingIdentity(origId);
5209 }
5210
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005211 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005212 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005213 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5214 for (int i=pids.length-1; i>=0; i--) {
5215 infos[i] = new Debug.MemoryInfo();
5216 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005217 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005218 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005219 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005220
5221 public void killApplicationProcess(String processName, int uid) {
5222 if (processName == null) {
5223 return;
5224 }
5225
5226 int callerUid = Binder.getCallingUid();
5227 // Only the system server can kill an application
5228 if (callerUid == Process.SYSTEM_UID) {
5229 synchronized (this) {
5230 ProcessRecord app = getProcessRecordLocked(processName, uid);
5231 if (app != null) {
5232 try {
5233 app.thread.scheduleSuicide();
5234 } catch (RemoteException e) {
5235 // If the other end already died, then our work here is done.
5236 }
5237 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005238 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005239 + processName + " / " + uid);
5240 }
5241 }
5242 } else {
5243 throw new SecurityException(callerUid + " cannot kill app process: " +
5244 processName);
5245 }
5246 }
5247
Dianne Hackborn03abb812010-01-04 18:43:19 -08005248 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005249 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005250 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5251 Uri.fromParts("package", packageName, null));
5252 intent.putExtra(Intent.EXTRA_UID, uid);
5253 broadcastIntentLocked(null, null, intent,
5254 null, null, 0, null, null, null,
5255 false, false, MY_PID, Process.SYSTEM_UID);
5256 }
5257
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005258 private final boolean killPackageProcessesLocked(String packageName, int uid,
5259 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005260 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005261
Dianne Hackborn03abb812010-01-04 18:43:19 -08005262 // Remove all processes this package may have touched: all with the
5263 // same UID (except for the system or root user), and all whose name
5264 // matches the package name.
5265 final String procNamePrefix = packageName + ":";
5266 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5267 final int NA = apps.size();
5268 for (int ia=0; ia<NA; ia++) {
5269 ProcessRecord app = apps.valueAt(ia);
5270 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005271 if (doit) {
5272 procs.add(app);
5273 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005274 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5275 || app.processName.equals(packageName)
5276 || app.processName.startsWith(procNamePrefix)) {
5277 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005278 if (!doit) {
5279 return true;
5280 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005281 app.removed = true;
5282 procs.add(app);
5283 }
5284 }
5285 }
5286 }
5287
5288 int N = procs.size();
5289 for (int i=0; i<N; i++) {
5290 removeProcessLocked(procs.get(i), callerWillRestart);
5291 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005292 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005293 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005294
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005295 private final boolean forceStopPackageLocked(String name, int uid,
5296 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005297 int i, N;
5298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 if (uid < 0) {
5300 try {
5301 uid = ActivityThread.getPackageManager().getPackageUid(name);
5302 } catch (RemoteException e) {
5303 }
5304 }
5305
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005306 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005307 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005308
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005309 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5310 while (badApps.hasNext()) {
5311 SparseArray<Long> ba = badApps.next();
5312 if (ba.get(uid) != null) {
5313 badApps.remove();
5314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005315 }
5316 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005317
5318 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5319 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320
5321 for (i=mHistory.size()-1; i>=0; i--) {
5322 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5323 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005324 if (!doit) {
5325 return true;
5326 }
5327 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005328 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 if (r.app != null) {
5330 r.app.removed = true;
5331 }
5332 r.app = null;
5333 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5334 }
5335 }
5336
5337 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5338 for (ServiceRecord service : mServices.values()) {
5339 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005340 if (!doit) {
5341 return true;
5342 }
5343 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005344 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 if (service.app != null) {
5346 service.app.removed = true;
5347 }
5348 service.app = null;
5349 services.add(service);
5350 }
5351 }
5352
5353 N = services.size();
5354 for (i=0; i<N; i++) {
5355 bringDownServiceLocked(services.get(i), true);
5356 }
5357
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005358 if (doit) {
5359 if (purgeCache) {
5360 AttributeCache ac = AttributeCache.instance();
5361 if (ac != null) {
5362 ac.removePackage(name);
5363 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005364 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005365 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005366 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005367
5368 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005369 }
5370
5371 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5372 final String name = app.processName;
5373 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005374 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 TAG, "Force removing process " + app + " (" + name
5376 + "/" + uid + ")");
5377
5378 mProcessNames.remove(name, uid);
5379 boolean needRestart = false;
5380 if (app.pid > 0 && app.pid != MY_PID) {
5381 int pid = app.pid;
5382 synchronized (mPidsSelfLocked) {
5383 mPidsSelfLocked.remove(pid);
5384 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5385 }
5386 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005387 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 Process.killProcess(pid);
5389
5390 if (app.persistent) {
5391 if (!callerWillRestart) {
5392 addAppLocked(app.info);
5393 } else {
5394 needRestart = true;
5395 }
5396 }
5397 } else {
5398 mRemovedProcesses.add(app);
5399 }
5400
5401 return needRestart;
5402 }
5403
5404 private final void processStartTimedOutLocked(ProcessRecord app) {
5405 final int pid = app.pid;
5406 boolean gone = false;
5407 synchronized (mPidsSelfLocked) {
5408 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5409 if (knownApp != null && knownApp.thread == null) {
5410 mPidsSelfLocked.remove(pid);
5411 gone = true;
5412 }
5413 }
5414
5415 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005416 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005417 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005418 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005419 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005420 // Take care of any launching providers waiting for this process.
5421 checkAppInLaunchingProvidersLocked(app, true);
5422 // Take care of any services that are waiting for the process.
5423 for (int i=0; i<mPendingServices.size(); i++) {
5424 ServiceRecord sr = mPendingServices.get(i);
5425 if (app.info.uid == sr.appInfo.uid
5426 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005427 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005428 mPendingServices.remove(i);
5429 i--;
5430 bringDownServiceLocked(sr, true);
5431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005432 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005433 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005434 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005435 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005436 try {
5437 IBackupManager bm = IBackupManager.Stub.asInterface(
5438 ServiceManager.getService(Context.BACKUP_SERVICE));
5439 bm.agentDisconnected(app.info.packageName);
5440 } catch (RemoteException e) {
5441 // Can't happen; the backup manager is local
5442 }
5443 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005444 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005445 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005446 mPendingBroadcast = null;
5447 scheduleBroadcastsLocked();
5448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005450 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 }
5452 }
5453
5454 private final boolean attachApplicationLocked(IApplicationThread thread,
5455 int pid) {
5456
5457 // Find the application record that is being attached... either via
5458 // the pid if we are running in multiple processes, or just pull the
5459 // next app record if we are emulating process with anonymous threads.
5460 ProcessRecord app;
5461 if (pid != MY_PID && pid >= 0) {
5462 synchronized (mPidsSelfLocked) {
5463 app = mPidsSelfLocked.get(pid);
5464 }
5465 } else if (mStartingProcesses.size() > 0) {
5466 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005467 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005468 } else {
5469 app = null;
5470 }
5471
5472 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005473 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005475 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005476 if (pid > 0 && pid != MY_PID) {
5477 Process.killProcess(pid);
5478 } else {
5479 try {
5480 thread.scheduleExit();
5481 } catch (Exception e) {
5482 // Ignore exceptions.
5483 }
5484 }
5485 return false;
5486 }
5487
5488 // If this application record is still attached to a previous
5489 // process, clean it up now.
5490 if (app.thread != null) {
5491 handleAppDiedLocked(app, true);
5492 }
5493
5494 // Tell the process all about itself.
5495
Joe Onorato8a9b2202010-02-26 18:56:32 -08005496 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005497 TAG, "Binding process pid " + pid + " to record " + app);
5498
5499 String processName = app.processName;
5500 try {
5501 thread.asBinder().linkToDeath(new AppDeathRecipient(
5502 app, pid, thread), 0);
5503 } catch (RemoteException e) {
5504 app.resetPackageList();
5505 startProcessLocked(app, "link fail", processName);
5506 return false;
5507 }
5508
Doug Zongker2bec3d42009-12-04 12:52:44 -08005509 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510
5511 app.thread = thread;
5512 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005513 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5514 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005515 app.forcingToForeground = null;
5516 app.foregroundServices = false;
5517 app.debugging = false;
5518
5519 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5520
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005521 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5522 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005523
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005524 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005525 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005526 }
5527
Joe Onorato8a9b2202010-02-26 18:56:32 -08005528 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005529 TAG, "New app record " + app
5530 + " thread=" + thread.asBinder() + " pid=" + pid);
5531 try {
5532 int testMode = IApplicationThread.DEBUG_OFF;
5533 if (mDebugApp != null && mDebugApp.equals(processName)) {
5534 testMode = mWaitForDebugger
5535 ? IApplicationThread.DEBUG_WAIT
5536 : IApplicationThread.DEBUG_ON;
5537 app.debugging = true;
5538 if (mDebugTransient) {
5539 mDebugApp = mOrigDebugApp;
5540 mWaitForDebugger = mOrigWaitForDebugger;
5541 }
5542 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005543
Christopher Tate181fafa2009-05-14 11:12:14 -07005544 // If the app is being launched for restore or full backup, set it up specially
5545 boolean isRestrictedBackupMode = false;
5546 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5547 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5548 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5549 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005550
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005551 ensurePackageDexOpt(app.instrumentationInfo != null
5552 ? app.instrumentationInfo.packageName
5553 : app.info.packageName);
5554 if (app.instrumentationClass != null) {
5555 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005556 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005557 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005558 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005559 thread.bindApplication(processName, app.instrumentationInfo != null
5560 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005561 app.instrumentationClass, app.instrumentationProfileFile,
5562 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005563 isRestrictedBackupMode || !normalMode,
5564 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005565 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005566 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 } catch (Exception e) {
5568 // todo: Yikes! What should we do? For now we will try to
5569 // start another process, but that could easily get us in
5570 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005571 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005572
5573 app.resetPackageList();
5574 startProcessLocked(app, "bind fail", processName);
5575 return false;
5576 }
5577
5578 // Remove this record from the list of starting applications.
5579 mPersistentStartingProcesses.remove(app);
5580 mProcessesOnHold.remove(app);
5581
5582 boolean badApp = false;
5583 boolean didSomething = false;
5584
5585 // See if the top visible activity is waiting to run in this process...
5586 HistoryRecord hr = topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07005587 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005588 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5589 && processName.equals(hr.processName)) {
5590 try {
5591 if (realStartActivityLocked(hr, app, true, true)) {
5592 didSomething = true;
5593 }
5594 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005595 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005596 + hr.intent.getComponent().flattenToShortString(), e);
5597 badApp = true;
5598 }
5599 } else {
5600 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5601 }
5602 }
5603
5604 // Find any services that should be running in this process...
5605 if (!badApp && mPendingServices.size() > 0) {
5606 ServiceRecord sr = null;
5607 try {
5608 for (int i=0; i<mPendingServices.size(); i++) {
5609 sr = mPendingServices.get(i);
5610 if (app.info.uid != sr.appInfo.uid
5611 || !processName.equals(sr.processName)) {
5612 continue;
5613 }
5614
5615 mPendingServices.remove(i);
5616 i--;
5617 realStartServiceLocked(sr, app);
5618 didSomething = true;
5619 }
5620 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005621 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 + sr.shortName, e);
5623 badApp = true;
5624 }
5625 }
5626
5627 // Check if the next broadcast receiver is in this process...
5628 BroadcastRecord br = mPendingBroadcast;
5629 if (!badApp && br != null && br.curApp == app) {
5630 try {
5631 mPendingBroadcast = null;
5632 processCurBroadcastLocked(br, app);
5633 didSomething = true;
5634 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005635 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 + br.curComponent.flattenToShortString(), e);
5637 badApp = true;
5638 logBroadcastReceiverDiscard(br);
5639 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5640 br.resultExtras, br.resultAbort, true);
5641 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005642 // We need to reset the state if we fails to start the receiver.
5643 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005644 }
5645 }
5646
Christopher Tate181fafa2009-05-14 11:12:14 -07005647 // Check whether the next backup agent is in this process...
5648 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005649 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005650 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005651 try {
5652 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5653 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005654 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005655 e.printStackTrace();
5656 }
5657 }
5658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005659 if (badApp) {
5660 // todo: Also need to kill application to deal with all
5661 // kinds of exceptions.
5662 handleAppDiedLocked(app, false);
5663 return false;
5664 }
5665
5666 if (!didSomething) {
5667 updateOomAdjLocked();
5668 }
5669
5670 return true;
5671 }
5672
5673 public final void attachApplication(IApplicationThread thread) {
5674 synchronized (this) {
5675 int callingPid = Binder.getCallingPid();
5676 final long origId = Binder.clearCallingIdentity();
5677 attachApplicationLocked(thread, callingPid);
5678 Binder.restoreCallingIdentity(origId);
5679 }
5680 }
5681
Dianne Hackborne88846e2009-09-30 21:34:25 -07005682 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005683 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005684 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005685 Binder.restoreCallingIdentity(origId);
5686 }
5687
5688 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5689 boolean remove) {
5690 int N = mStoppingActivities.size();
5691 if (N <= 0) return null;
5692
5693 ArrayList<HistoryRecord> stops = null;
5694
5695 final boolean nowVisible = mResumedActivity != null
5696 && mResumedActivity.nowVisible
5697 && !mResumedActivity.waitingVisible;
5698 for (int i=0; i<N; i++) {
5699 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005700 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 + nowVisible + " waitingVisible=" + s.waitingVisible
5702 + " finishing=" + s.finishing);
5703 if (s.waitingVisible && nowVisible) {
5704 mWaitingVisibleActivities.remove(s);
5705 s.waitingVisible = false;
5706 if (s.finishing) {
5707 // If this activity is finishing, it is sitting on top of
5708 // everyone else but we now know it is no longer needed...
5709 // so get rid of it. Otherwise, we need to go through the
5710 // normal flow and hide it once we determine that it is
5711 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005712 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005713 mWindowManager.setAppVisibility(s, false);
5714 }
5715 }
5716 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005717 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005718 if (stops == null) {
5719 stops = new ArrayList<HistoryRecord>();
5720 }
5721 stops.add(s);
5722 mStoppingActivities.remove(i);
5723 N--;
5724 i--;
5725 }
5726 }
5727
5728 return stops;
5729 }
5730
5731 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005732 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005733 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005734 mWindowManager.enableScreenAfterBoot();
5735 }
5736
Dianne Hackborne88846e2009-09-30 21:34:25 -07005737 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5738 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005739 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005740
5741 ArrayList<HistoryRecord> stops = null;
5742 ArrayList<HistoryRecord> finishes = null;
5743 ArrayList<HistoryRecord> thumbnails = null;
5744 int NS = 0;
5745 int NF = 0;
5746 int NT = 0;
5747 IApplicationThread sendThumbnail = null;
5748 boolean booting = false;
5749 boolean enableScreen = false;
5750
5751 synchronized (this) {
5752 if (token != null) {
5753 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5754 }
5755
5756 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005757 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 if (index >= 0) {
5759 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5760
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005761 if (fromTimeout) {
5762 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5763 }
5764
Dianne Hackborne88846e2009-09-30 21:34:25 -07005765 // This is a hack to semi-deal with a race condition
5766 // in the client where it can be constructed with a
5767 // newer configuration from when we asked it to launch.
5768 // We'll update with whatever configuration it now says
5769 // it used to launch.
5770 if (config != null) {
5771 r.configuration = config;
5772 }
5773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005774 // No longer need to keep the device awake.
5775 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5776 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5777 mLaunchingActivity.release();
5778 }
5779
5780 // We are now idle. If someone is waiting for a thumbnail from
5781 // us, we can now deliver.
5782 r.idle = true;
5783 scheduleAppGcsLocked();
5784 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5785 sendThumbnail = r.app.thread;
5786 r.thumbnailNeeded = false;
5787 }
5788
5789 // If this activity is fullscreen, set up to hide those under it.
5790
Joe Onorato8a9b2202010-02-26 18:56:32 -08005791 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005792 ensureActivitiesVisibleLocked(null, 0);
5793
Joe Onorato8a9b2202010-02-26 18:56:32 -08005794 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005795 if (!mBooted && !fromTimeout) {
5796 mBooted = true;
5797 enableScreen = true;
5798 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005799
5800 } else if (fromTimeout) {
5801 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005802 }
5803
5804 // Atomically retrieve all of the other things to do.
5805 stops = processStoppingActivitiesLocked(true);
5806 NS = stops != null ? stops.size() : 0;
5807 if ((NF=mFinishingActivities.size()) > 0) {
5808 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5809 mFinishingActivities.clear();
5810 }
5811 if ((NT=mCancelledThumbnails.size()) > 0) {
5812 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5813 mCancelledThumbnails.clear();
5814 }
5815
5816 booting = mBooting;
5817 mBooting = false;
5818 }
5819
5820 int i;
5821
5822 // Send thumbnail if requested.
5823 if (sendThumbnail != null) {
5824 try {
5825 sendThumbnail.requestThumbnail(token);
5826 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005827 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 sendPendingThumbnail(null, token, null, null, true);
5829 }
5830 }
5831
5832 // Stop any activities that are scheduled to do so but have been
5833 // waiting for the next one to start.
5834 for (i=0; i<NS; i++) {
5835 HistoryRecord r = (HistoryRecord)stops.get(i);
5836 synchronized (this) {
5837 if (r.finishing) {
5838 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5839 } else {
5840 stopActivityLocked(r);
5841 }
5842 }
5843 }
5844
5845 // Finish any activities that are scheduled to do so but have been
5846 // waiting for the next one to start.
5847 for (i=0; i<NF; i++) {
5848 HistoryRecord r = (HistoryRecord)finishes.get(i);
5849 synchronized (this) {
5850 destroyActivityLocked(r, true);
5851 }
5852 }
5853
5854 // Report back to any thumbnail receivers.
5855 for (i=0; i<NT; i++) {
5856 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5857 sendPendingThumbnail(r, null, null, null, true);
5858 }
5859
5860 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005861 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 }
5863
5864 trimApplications();
5865 //dump();
5866 //mWindowManager.dump();
5867
5868 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005869 enableScreenAfterBoot();
5870 }
5871 }
5872
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005873 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005874 IntentFilter pkgFilter = new IntentFilter();
5875 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5876 pkgFilter.addDataScheme("package");
5877 mContext.registerReceiver(new BroadcastReceiver() {
5878 @Override
5879 public void onReceive(Context context, Intent intent) {
5880 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5881 if (pkgs != null) {
5882 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07005883 synchronized (ActivityManagerService.this) {
5884 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5885 setResultCode(Activity.RESULT_OK);
5886 return;
5887 }
5888 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005889 }
5890 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005891 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005892 }, pkgFilter);
5893
5894 synchronized (this) {
5895 // Ensure that any processes we had put on hold are now started
5896 // up.
5897 final int NP = mProcessesOnHold.size();
5898 if (NP > 0) {
5899 ArrayList<ProcessRecord> procs =
5900 new ArrayList<ProcessRecord>(mProcessesOnHold);
5901 for (int ip=0; ip<NP; ip++) {
5902 this.startProcessLocked(procs.get(ip), "on-hold", null);
5903 }
5904 }
5905
5906 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5907 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005908 broadcastIntentLocked(null, null,
5909 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5910 null, null, 0, null, null,
5911 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5912 false, false, MY_PID, Process.SYSTEM_UID);
5913 }
5914 }
5915 }
5916
5917 final void ensureBootCompleted() {
5918 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005919 boolean enableScreen;
5920 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005921 booting = mBooting;
5922 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005923 enableScreen = !mBooted;
5924 mBooted = true;
5925 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005926
5927 if (booting) {
5928 finishBooting();
5929 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005930
5931 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005932 enableScreenAfterBoot();
5933 }
5934 }
5935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005936 public final void activityPaused(IBinder token, Bundle icicle) {
5937 // Refuse possible leaked file descriptors
5938 if (icicle != null && icicle.hasFileDescriptors()) {
5939 throw new IllegalArgumentException("File descriptors passed in Bundle");
5940 }
5941
5942 final long origId = Binder.clearCallingIdentity();
5943 activityPaused(token, icicle, false);
5944 Binder.restoreCallingIdentity(origId);
5945 }
5946
5947 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005948 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005949 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5950 + ", timeout=" + timeout);
5951
5952 HistoryRecord r = null;
5953
5954 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005955 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005956 if (index >= 0) {
5957 r = (HistoryRecord)mHistory.get(index);
5958 if (!timeout) {
5959 r.icicle = icicle;
5960 r.haveState = true;
5961 }
5962 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5963 if (mPausingActivity == r) {
5964 r.state = ActivityState.PAUSED;
5965 completePauseLocked();
5966 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005967 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 System.identityHashCode(r), r.shortComponentName,
5969 mPausingActivity != null
5970 ? mPausingActivity.shortComponentName : "(none)");
5971 }
5972 }
5973 }
5974 }
5975
5976 public final void activityStopped(IBinder token, Bitmap thumbnail,
5977 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005978 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 TAG, "Activity stopped: token=" + token);
5980
5981 HistoryRecord r = null;
5982
5983 final long origId = Binder.clearCallingIdentity();
5984
5985 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005986 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987 if (index >= 0) {
5988 r = (HistoryRecord)mHistory.get(index);
5989 r.thumbnail = thumbnail;
5990 r.description = description;
5991 r.stopped = true;
5992 r.state = ActivityState.STOPPED;
5993 if (!r.finishing) {
5994 if (r.configDestroy) {
5995 destroyActivityLocked(r, true);
5996 resumeTopActivityLocked(null);
5997 }
5998 }
5999 }
6000 }
6001
6002 if (r != null) {
6003 sendPendingThumbnail(r, null, null, null, false);
6004 }
6005
6006 trimApplications();
6007
6008 Binder.restoreCallingIdentity(origId);
6009 }
6010
6011 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006012 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006013 synchronized (this) {
6014 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
6015
Dianne Hackborn75b03852009-06-12 15:43:26 -07006016 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006017 if (index >= 0) {
6018 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6019 if (r.state == ActivityState.DESTROYING) {
6020 final long origId = Binder.clearCallingIdentity();
6021 removeActivityFromHistoryLocked(r);
6022 Binder.restoreCallingIdentity(origId);
6023 }
6024 }
6025 }
6026 }
6027
6028 public String getCallingPackage(IBinder token) {
6029 synchronized (this) {
6030 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07006031 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 }
6033 }
6034
6035 public ComponentName getCallingActivity(IBinder token) {
6036 synchronized (this) {
6037 HistoryRecord r = getCallingRecordLocked(token);
6038 return r != null ? r.intent.getComponent() : null;
6039 }
6040 }
6041
6042 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006043 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006044 if (index >= 0) {
6045 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6046 if (r != null) {
6047 return r.resultTo;
6048 }
6049 }
6050 return null;
6051 }
6052
6053 public ComponentName getActivityClassForToken(IBinder token) {
6054 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006055 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 if (index >= 0) {
6057 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6058 return r.intent.getComponent();
6059 }
6060 return null;
6061 }
6062 }
6063
6064 public String getPackageForToken(IBinder token) {
6065 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006066 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006067 if (index >= 0) {
6068 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6069 return r.packageName;
6070 }
6071 return null;
6072 }
6073 }
6074
6075 public IIntentSender getIntentSender(int type,
6076 String packageName, IBinder token, String resultWho,
6077 int requestCode, Intent intent, String resolvedType, int flags) {
6078 // Refuse possible leaked file descriptors
6079 if (intent != null && intent.hasFileDescriptors() == true) {
6080 throw new IllegalArgumentException("File descriptors passed in Intent");
6081 }
6082
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006083 if (type == INTENT_SENDER_BROADCAST) {
6084 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6085 throw new IllegalArgumentException(
6086 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6087 }
6088 }
6089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 synchronized(this) {
6091 int callingUid = Binder.getCallingUid();
6092 try {
6093 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6094 Process.supportsProcesses()) {
6095 int uid = ActivityThread.getPackageManager()
6096 .getPackageUid(packageName);
6097 if (uid != Binder.getCallingUid()) {
6098 String msg = "Permission Denial: getIntentSender() from pid="
6099 + Binder.getCallingPid()
6100 + ", uid=" + Binder.getCallingUid()
6101 + ", (need uid=" + uid + ")"
6102 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006103 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006104 throw new SecurityException(msg);
6105 }
6106 }
6107 } catch (RemoteException e) {
6108 throw new SecurityException(e);
6109 }
6110 HistoryRecord activity = null;
6111 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006112 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006113 if (index < 0) {
6114 return null;
6115 }
6116 activity = (HistoryRecord)mHistory.get(index);
6117 if (activity.finishing) {
6118 return null;
6119 }
6120 }
6121
6122 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6123 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6124 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6125 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6126 |PendingIntent.FLAG_UPDATE_CURRENT);
6127
6128 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6129 type, packageName, activity, resultWho,
6130 requestCode, intent, resolvedType, flags);
6131 WeakReference<PendingIntentRecord> ref;
6132 ref = mIntentSenderRecords.get(key);
6133 PendingIntentRecord rec = ref != null ? ref.get() : null;
6134 if (rec != null) {
6135 if (!cancelCurrent) {
6136 if (updateCurrent) {
6137 rec.key.requestIntent.replaceExtras(intent);
6138 }
6139 return rec;
6140 }
6141 rec.canceled = true;
6142 mIntentSenderRecords.remove(key);
6143 }
6144 if (noCreate) {
6145 return rec;
6146 }
6147 rec = new PendingIntentRecord(this, key, callingUid);
6148 mIntentSenderRecords.put(key, rec.ref);
6149 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6150 if (activity.pendingResults == null) {
6151 activity.pendingResults
6152 = new HashSet<WeakReference<PendingIntentRecord>>();
6153 }
6154 activity.pendingResults.add(rec.ref);
6155 }
6156 return rec;
6157 }
6158 }
6159
6160 public void cancelIntentSender(IIntentSender sender) {
6161 if (!(sender instanceof PendingIntentRecord)) {
6162 return;
6163 }
6164 synchronized(this) {
6165 PendingIntentRecord rec = (PendingIntentRecord)sender;
6166 try {
6167 int uid = ActivityThread.getPackageManager()
6168 .getPackageUid(rec.key.packageName);
6169 if (uid != Binder.getCallingUid()) {
6170 String msg = "Permission Denial: cancelIntentSender() from pid="
6171 + Binder.getCallingPid()
6172 + ", uid=" + Binder.getCallingUid()
6173 + " is not allowed to cancel packges "
6174 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006175 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006176 throw new SecurityException(msg);
6177 }
6178 } catch (RemoteException e) {
6179 throw new SecurityException(e);
6180 }
6181 cancelIntentSenderLocked(rec, true);
6182 }
6183 }
6184
6185 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6186 rec.canceled = true;
6187 mIntentSenderRecords.remove(rec.key);
6188 if (cleanActivity && rec.key.activity != null) {
6189 rec.key.activity.pendingResults.remove(rec.ref);
6190 }
6191 }
6192
6193 public String getPackageForIntentSender(IIntentSender pendingResult) {
6194 if (!(pendingResult instanceof PendingIntentRecord)) {
6195 return null;
6196 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006197 try {
6198 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6199 return res.key.packageName;
6200 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006201 }
6202 return null;
6203 }
6204
6205 public void setProcessLimit(int max) {
6206 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6207 "setProcessLimit()");
6208 mProcessLimit = max;
6209 }
6210
6211 public int getProcessLimit() {
6212 return mProcessLimit;
6213 }
6214
6215 void foregroundTokenDied(ForegroundToken token) {
6216 synchronized (ActivityManagerService.this) {
6217 synchronized (mPidsSelfLocked) {
6218 ForegroundToken cur
6219 = mForegroundProcesses.get(token.pid);
6220 if (cur != token) {
6221 return;
6222 }
6223 mForegroundProcesses.remove(token.pid);
6224 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6225 if (pr == null) {
6226 return;
6227 }
6228 pr.forcingToForeground = null;
6229 pr.foregroundServices = false;
6230 }
6231 updateOomAdjLocked();
6232 }
6233 }
6234
6235 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6236 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6237 "setProcessForeground()");
6238 synchronized(this) {
6239 boolean changed = false;
6240
6241 synchronized (mPidsSelfLocked) {
6242 ProcessRecord pr = mPidsSelfLocked.get(pid);
6243 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006244 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006245 return;
6246 }
6247 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6248 if (oldToken != null) {
6249 oldToken.token.unlinkToDeath(oldToken, 0);
6250 mForegroundProcesses.remove(pid);
6251 pr.forcingToForeground = null;
6252 changed = true;
6253 }
6254 if (isForeground && token != null) {
6255 ForegroundToken newToken = new ForegroundToken() {
6256 public void binderDied() {
6257 foregroundTokenDied(this);
6258 }
6259 };
6260 newToken.pid = pid;
6261 newToken.token = token;
6262 try {
6263 token.linkToDeath(newToken, 0);
6264 mForegroundProcesses.put(pid, newToken);
6265 pr.forcingToForeground = token;
6266 changed = true;
6267 } catch (RemoteException e) {
6268 // If the process died while doing this, we will later
6269 // do the cleanup with the process death link.
6270 }
6271 }
6272 }
6273
6274 if (changed) {
6275 updateOomAdjLocked();
6276 }
6277 }
6278 }
6279
6280 // =========================================================
6281 // PERMISSIONS
6282 // =========================================================
6283
6284 static class PermissionController extends IPermissionController.Stub {
6285 ActivityManagerService mActivityManagerService;
6286 PermissionController(ActivityManagerService activityManagerService) {
6287 mActivityManagerService = activityManagerService;
6288 }
6289
6290 public boolean checkPermission(String permission, int pid, int uid) {
6291 return mActivityManagerService.checkPermission(permission, pid,
6292 uid) == PackageManager.PERMISSION_GRANTED;
6293 }
6294 }
6295
6296 /**
6297 * This can be called with or without the global lock held.
6298 */
6299 int checkComponentPermission(String permission, int pid, int uid,
6300 int reqUid) {
6301 // We might be performing an operation on behalf of an indirect binder
6302 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6303 // client identity accordingly before proceeding.
6304 Identity tlsIdentity = sCallerIdentity.get();
6305 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006306 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006307 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6308 uid = tlsIdentity.uid;
6309 pid = tlsIdentity.pid;
6310 }
6311
6312 // Root, system server and our own process get to do everything.
6313 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6314 !Process.supportsProcesses()) {
6315 return PackageManager.PERMISSION_GRANTED;
6316 }
6317 // If the target requires a specific UID, always fail for others.
6318 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006319 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006320 return PackageManager.PERMISSION_DENIED;
6321 }
6322 if (permission == null) {
6323 return PackageManager.PERMISSION_GRANTED;
6324 }
6325 try {
6326 return ActivityThread.getPackageManager()
6327 .checkUidPermission(permission, uid);
6328 } catch (RemoteException e) {
6329 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006330 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 }
6332 return PackageManager.PERMISSION_DENIED;
6333 }
6334
6335 /**
6336 * As the only public entry point for permissions checking, this method
6337 * can enforce the semantic that requesting a check on a null global
6338 * permission is automatically denied. (Internally a null permission
6339 * string is used when calling {@link #checkComponentPermission} in cases
6340 * when only uid-based security is needed.)
6341 *
6342 * This can be called with or without the global lock held.
6343 */
6344 public int checkPermission(String permission, int pid, int uid) {
6345 if (permission == null) {
6346 return PackageManager.PERMISSION_DENIED;
6347 }
6348 return checkComponentPermission(permission, pid, uid, -1);
6349 }
6350
6351 /**
6352 * Binder IPC calls go through the public entry point.
6353 * This can be called with or without the global lock held.
6354 */
6355 int checkCallingPermission(String permission) {
6356 return checkPermission(permission,
6357 Binder.getCallingPid(),
6358 Binder.getCallingUid());
6359 }
6360
6361 /**
6362 * This can be called with or without the global lock held.
6363 */
6364 void enforceCallingPermission(String permission, String func) {
6365 if (checkCallingPermission(permission)
6366 == PackageManager.PERMISSION_GRANTED) {
6367 return;
6368 }
6369
6370 String msg = "Permission Denial: " + func + " from pid="
6371 + Binder.getCallingPid()
6372 + ", uid=" + Binder.getCallingUid()
6373 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006374 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 throw new SecurityException(msg);
6376 }
6377
6378 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6379 ProviderInfo pi, int uid, int modeFlags) {
6380 try {
6381 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6382 if ((pi.readPermission != null) &&
6383 (pm.checkUidPermission(pi.readPermission, uid)
6384 != PackageManager.PERMISSION_GRANTED)) {
6385 return false;
6386 }
6387 }
6388 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6389 if ((pi.writePermission != null) &&
6390 (pm.checkUidPermission(pi.writePermission, uid)
6391 != PackageManager.PERMISSION_GRANTED)) {
6392 return false;
6393 }
6394 }
6395 return true;
6396 } catch (RemoteException e) {
6397 return false;
6398 }
6399 }
6400
6401 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6402 int modeFlags) {
6403 // Root gets to do everything.
6404 if (uid == 0 || !Process.supportsProcesses()) {
6405 return true;
6406 }
6407 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6408 if (perms == null) return false;
6409 UriPermission perm = perms.get(uri);
6410 if (perm == null) return false;
6411 return (modeFlags&perm.modeFlags) == modeFlags;
6412 }
6413
6414 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6415 // Another redirected-binder-call permissions check as in
6416 // {@link checkComponentPermission}.
6417 Identity tlsIdentity = sCallerIdentity.get();
6418 if (tlsIdentity != null) {
6419 uid = tlsIdentity.uid;
6420 pid = tlsIdentity.pid;
6421 }
6422
6423 // Our own process gets to do everything.
6424 if (pid == MY_PID) {
6425 return PackageManager.PERMISSION_GRANTED;
6426 }
6427 synchronized(this) {
6428 return checkUriPermissionLocked(uri, uid, modeFlags)
6429 ? PackageManager.PERMISSION_GRANTED
6430 : PackageManager.PERMISSION_DENIED;
6431 }
6432 }
6433
6434 private void grantUriPermissionLocked(int callingUid,
6435 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6436 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6437 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6438 if (modeFlags == 0) {
6439 return;
6440 }
6441
Joe Onorato8a9b2202010-02-26 18:56:32 -08006442 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006443 "Requested grant " + targetPkg + " permission to " + uri);
6444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 final IPackageManager pm = ActivityThread.getPackageManager();
6446
6447 // If this is not a content: uri, we can't do anything with it.
6448 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006449 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006450 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 return;
6452 }
6453
6454 String name = uri.getAuthority();
6455 ProviderInfo pi = null;
6456 ContentProviderRecord cpr
6457 = (ContentProviderRecord)mProvidersByName.get(name);
6458 if (cpr != null) {
6459 pi = cpr.info;
6460 } else {
6461 try {
6462 pi = pm.resolveContentProvider(name,
6463 PackageManager.GET_URI_PERMISSION_PATTERNS);
6464 } catch (RemoteException ex) {
6465 }
6466 }
6467 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006468 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006469 return;
6470 }
6471
6472 int targetUid;
6473 try {
6474 targetUid = pm.getPackageUid(targetPkg);
6475 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006476 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006477 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006478 return;
6479 }
6480 } catch (RemoteException ex) {
6481 return;
6482 }
6483
6484 // First... does the target actually need this permission?
6485 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6486 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006487 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006488 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006489 return;
6490 }
6491
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006492 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 if (!pi.grantUriPermissions) {
6494 throw new SecurityException("Provider " + pi.packageName
6495 + "/" + pi.name
6496 + " does not allow granting of Uri permissions (uri "
6497 + uri + ")");
6498 }
6499 if (pi.uriPermissionPatterns != null) {
6500 final int N = pi.uriPermissionPatterns.length;
6501 boolean allowed = false;
6502 for (int i=0; i<N; i++) {
6503 if (pi.uriPermissionPatterns[i] != null
6504 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6505 allowed = true;
6506 break;
6507 }
6508 }
6509 if (!allowed) {
6510 throw new SecurityException("Provider " + pi.packageName
6511 + "/" + pi.name
6512 + " does not allow granting of permission to path of Uri "
6513 + uri);
6514 }
6515 }
6516
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006517 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006518 // this uri?
6519 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6520 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6521 throw new SecurityException("Uid " + callingUid
6522 + " does not have permission to uri " + uri);
6523 }
6524 }
6525
6526 // Okay! So here we are: the caller has the assumed permission
6527 // to the uri, and the target doesn't. Let's now give this to
6528 // the target.
6529
Joe Onorato8a9b2202010-02-26 18:56:32 -08006530 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006531 "Granting " + targetPkg + " permission to " + uri);
6532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006533 HashMap<Uri, UriPermission> targetUris
6534 = mGrantedUriPermissions.get(targetUid);
6535 if (targetUris == null) {
6536 targetUris = new HashMap<Uri, UriPermission>();
6537 mGrantedUriPermissions.put(targetUid, targetUris);
6538 }
6539
6540 UriPermission perm = targetUris.get(uri);
6541 if (perm == null) {
6542 perm = new UriPermission(targetUid, uri);
6543 targetUris.put(uri, perm);
6544
6545 }
6546 perm.modeFlags |= modeFlags;
6547 if (activity == null) {
6548 perm.globalModeFlags |= modeFlags;
6549 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6550 perm.readActivities.add(activity);
6551 if (activity.readUriPermissions == null) {
6552 activity.readUriPermissions = new HashSet<UriPermission>();
6553 }
6554 activity.readUriPermissions.add(perm);
6555 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6556 perm.writeActivities.add(activity);
6557 if (activity.writeUriPermissions == null) {
6558 activity.writeUriPermissions = new HashSet<UriPermission>();
6559 }
6560 activity.writeUriPermissions.add(perm);
6561 }
6562 }
6563
6564 private void grantUriPermissionFromIntentLocked(int callingUid,
6565 String targetPkg, Intent intent, HistoryRecord activity) {
6566 if (intent == null) {
6567 return;
6568 }
6569 Uri data = intent.getData();
6570 if (data == null) {
6571 return;
6572 }
6573 grantUriPermissionLocked(callingUid, targetPkg, data,
6574 intent.getFlags(), activity);
6575 }
6576
6577 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6578 Uri uri, int modeFlags) {
6579 synchronized(this) {
6580 final ProcessRecord r = getRecordForAppLocked(caller);
6581 if (r == null) {
6582 throw new SecurityException("Unable to find app for caller "
6583 + caller
6584 + " when granting permission to uri " + uri);
6585 }
6586 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006587 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006588 return;
6589 }
6590 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006591 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006592 return;
6593 }
6594
6595 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6596 null);
6597 }
6598 }
6599
6600 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6601 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6602 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6603 HashMap<Uri, UriPermission> perms
6604 = mGrantedUriPermissions.get(perm.uid);
6605 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006606 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006607 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006608 perms.remove(perm.uri);
6609 if (perms.size() == 0) {
6610 mGrantedUriPermissions.remove(perm.uid);
6611 }
6612 }
6613 }
6614 }
6615
6616 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6617 if (activity.readUriPermissions != null) {
6618 for (UriPermission perm : activity.readUriPermissions) {
6619 perm.readActivities.remove(activity);
6620 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6621 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6622 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6623 removeUriPermissionIfNeededLocked(perm);
6624 }
6625 }
6626 }
6627 if (activity.writeUriPermissions != null) {
6628 for (UriPermission perm : activity.writeUriPermissions) {
6629 perm.writeActivities.remove(activity);
6630 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6631 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6632 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6633 removeUriPermissionIfNeededLocked(perm);
6634 }
6635 }
6636 }
6637 }
6638
6639 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6640 int modeFlags) {
6641 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6642 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6643 if (modeFlags == 0) {
6644 return;
6645 }
6646
Joe Onorato8a9b2202010-02-26 18:56:32 -08006647 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006648 "Revoking all granted permissions to " + uri);
6649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006650 final IPackageManager pm = ActivityThread.getPackageManager();
6651
6652 final String authority = uri.getAuthority();
6653 ProviderInfo pi = null;
6654 ContentProviderRecord cpr
6655 = (ContentProviderRecord)mProvidersByName.get(authority);
6656 if (cpr != null) {
6657 pi = cpr.info;
6658 } else {
6659 try {
6660 pi = pm.resolveContentProvider(authority,
6661 PackageManager.GET_URI_PERMISSION_PATTERNS);
6662 } catch (RemoteException ex) {
6663 }
6664 }
6665 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006666 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006667 return;
6668 }
6669
6670 // Does the caller have this permission on the URI?
6671 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6672 // Right now, if you are not the original owner of the permission,
6673 // you are not allowed to revoke it.
6674 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6675 throw new SecurityException("Uid " + callingUid
6676 + " does not have permission to uri " + uri);
6677 //}
6678 }
6679
6680 // Go through all of the permissions and remove any that match.
6681 final List<String> SEGMENTS = uri.getPathSegments();
6682 if (SEGMENTS != null) {
6683 final int NS = SEGMENTS.size();
6684 int N = mGrantedUriPermissions.size();
6685 for (int i=0; i<N; i++) {
6686 HashMap<Uri, UriPermission> perms
6687 = mGrantedUriPermissions.valueAt(i);
6688 Iterator<UriPermission> it = perms.values().iterator();
6689 toploop:
6690 while (it.hasNext()) {
6691 UriPermission perm = it.next();
6692 Uri targetUri = perm.uri;
6693 if (!authority.equals(targetUri.getAuthority())) {
6694 continue;
6695 }
6696 List<String> targetSegments = targetUri.getPathSegments();
6697 if (targetSegments == null) {
6698 continue;
6699 }
6700 if (targetSegments.size() < NS) {
6701 continue;
6702 }
6703 for (int j=0; j<NS; j++) {
6704 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6705 continue toploop;
6706 }
6707 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006708 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006709 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006710 perm.clearModes(modeFlags);
6711 if (perm.modeFlags == 0) {
6712 it.remove();
6713 }
6714 }
6715 if (perms.size() == 0) {
6716 mGrantedUriPermissions.remove(
6717 mGrantedUriPermissions.keyAt(i));
6718 N--;
6719 i--;
6720 }
6721 }
6722 }
6723 }
6724
6725 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6726 int modeFlags) {
6727 synchronized(this) {
6728 final ProcessRecord r = getRecordForAppLocked(caller);
6729 if (r == null) {
6730 throw new SecurityException("Unable to find app for caller "
6731 + caller
6732 + " when revoking permission to uri " + uri);
6733 }
6734 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006735 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006736 return;
6737 }
6738
6739 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6740 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6741 if (modeFlags == 0) {
6742 return;
6743 }
6744
6745 final IPackageManager pm = ActivityThread.getPackageManager();
6746
6747 final String authority = uri.getAuthority();
6748 ProviderInfo pi = null;
6749 ContentProviderRecord cpr
6750 = (ContentProviderRecord)mProvidersByName.get(authority);
6751 if (cpr != null) {
6752 pi = cpr.info;
6753 } else {
6754 try {
6755 pi = pm.resolveContentProvider(authority,
6756 PackageManager.GET_URI_PERMISSION_PATTERNS);
6757 } catch (RemoteException ex) {
6758 }
6759 }
6760 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006761 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006762 return;
6763 }
6764
6765 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6766 }
6767 }
6768
6769 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6770 synchronized (this) {
6771 ProcessRecord app =
6772 who != null ? getRecordForAppLocked(who) : null;
6773 if (app == null) return;
6774
6775 Message msg = Message.obtain();
6776 msg.what = WAIT_FOR_DEBUGGER_MSG;
6777 msg.obj = app;
6778 msg.arg1 = waiting ? 1 : 0;
6779 mHandler.sendMessage(msg);
6780 }
6781 }
6782
6783 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6784 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006785 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006787 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006788 }
6789
6790 // =========================================================
6791 // TASK MANAGEMENT
6792 // =========================================================
6793
6794 public List getTasks(int maxNum, int flags,
6795 IThumbnailReceiver receiver) {
6796 ArrayList list = new ArrayList();
6797
6798 PendingThumbnailsRecord pending = null;
6799 IApplicationThread topThumbnail = null;
6800 HistoryRecord topRecord = null;
6801
6802 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006803 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006804 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6805 + ", receiver=" + receiver);
6806
6807 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6808 != PackageManager.PERMISSION_GRANTED) {
6809 if (receiver != null) {
6810 // If the caller wants to wait for pending thumbnails,
6811 // it ain't gonna get them.
6812 try {
6813 receiver.finished();
6814 } catch (RemoteException ex) {
6815 }
6816 }
6817 String msg = "Permission Denial: getTasks() from pid="
6818 + Binder.getCallingPid()
6819 + ", uid=" + Binder.getCallingUid()
6820 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006821 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006822 throw new SecurityException(msg);
6823 }
6824
6825 int pos = mHistory.size()-1;
6826 HistoryRecord next =
6827 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6828 HistoryRecord top = null;
6829 CharSequence topDescription = null;
6830 TaskRecord curTask = null;
6831 int numActivities = 0;
6832 int numRunning = 0;
6833 while (pos >= 0 && maxNum > 0) {
6834 final HistoryRecord r = next;
6835 pos--;
6836 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6837
6838 // Initialize state for next task if needed.
6839 if (top == null ||
6840 (top.state == ActivityState.INITIALIZING
6841 && top.task == r.task)) {
6842 top = r;
6843 topDescription = r.description;
6844 curTask = r.task;
6845 numActivities = numRunning = 0;
6846 }
6847
6848 // Add 'r' into the current task.
6849 numActivities++;
6850 if (r.app != null && r.app.thread != null) {
6851 numRunning++;
6852 }
6853 if (topDescription == null) {
6854 topDescription = r.description;
6855 }
6856
Joe Onorato8a9b2202010-02-26 18:56:32 -08006857 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006858 TAG, r.intent.getComponent().flattenToShortString()
6859 + ": task=" + r.task);
6860
6861 // If the next one is a different task, generate a new
6862 // TaskInfo entry for what we have.
6863 if (next == null || next.task != curTask) {
6864 ActivityManager.RunningTaskInfo ci
6865 = new ActivityManager.RunningTaskInfo();
6866 ci.id = curTask.taskId;
6867 ci.baseActivity = r.intent.getComponent();
6868 ci.topActivity = top.intent.getComponent();
6869 ci.thumbnail = top.thumbnail;
6870 ci.description = topDescription;
6871 ci.numActivities = numActivities;
6872 ci.numRunning = numRunning;
6873 //System.out.println(
6874 // "#" + maxNum + ": " + " descr=" + ci.description);
6875 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006876 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006877 TAG, "State=" + top.state + "Idle=" + top.idle
6878 + " app=" + top.app
6879 + " thr=" + (top.app != null ? top.app.thread : null));
6880 if (top.state == ActivityState.RESUMED
6881 || top.state == ActivityState.PAUSING) {
6882 if (top.idle && top.app != null
6883 && top.app.thread != null) {
6884 topRecord = top;
6885 topThumbnail = top.app.thread;
6886 } else {
6887 top.thumbnailNeeded = true;
6888 }
6889 }
6890 if (pending == null) {
6891 pending = new PendingThumbnailsRecord(receiver);
6892 }
6893 pending.pendingRecords.add(top);
6894 }
6895 list.add(ci);
6896 maxNum--;
6897 top = null;
6898 }
6899 }
6900
6901 if (pending != null) {
6902 mPendingThumbnails.add(pending);
6903 }
6904 }
6905
Joe Onorato8a9b2202010-02-26 18:56:32 -08006906 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006907
6908 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006909 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006910 try {
6911 topThumbnail.requestThumbnail(topRecord);
6912 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006913 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006914 sendPendingThumbnail(null, topRecord, null, null, true);
6915 }
6916 }
6917
6918 if (pending == null && receiver != null) {
6919 // In this case all thumbnails were available and the client
6920 // is being asked to be told when the remaining ones come in...
6921 // which is unusually, since the top-most currently running
6922 // activity should never have a canned thumbnail! Oh well.
6923 try {
6924 receiver.finished();
6925 } catch (RemoteException ex) {
6926 }
6927 }
6928
6929 return list;
6930 }
6931
6932 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6933 int flags) {
6934 synchronized (this) {
6935 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6936 "getRecentTasks()");
6937
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006938 IPackageManager pm = ActivityThread.getPackageManager();
6939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006940 final int N = mRecentTasks.size();
6941 ArrayList<ActivityManager.RecentTaskInfo> res
6942 = new ArrayList<ActivityManager.RecentTaskInfo>(
6943 maxNum < N ? maxNum : N);
6944 for (int i=0; i<N && maxNum > 0; i++) {
6945 TaskRecord tr = mRecentTasks.get(i);
6946 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6947 || (tr.intent == null)
6948 || ((tr.intent.getFlags()
6949 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6950 ActivityManager.RecentTaskInfo rti
6951 = new ActivityManager.RecentTaskInfo();
6952 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6953 rti.baseIntent = new Intent(
6954 tr.intent != null ? tr.intent : tr.affinityIntent);
6955 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006956
6957 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
6958 // Check whether this activity is currently available.
6959 try {
6960 if (rti.origActivity != null) {
6961 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
6962 continue;
6963 }
6964 } else if (rti.baseIntent != null) {
6965 if (pm.queryIntentActivities(rti.baseIntent,
6966 null, 0) == null) {
6967 continue;
6968 }
6969 }
6970 } catch (RemoteException e) {
6971 // Will never happen.
6972 }
6973 }
6974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006975 res.add(rti);
6976 maxNum--;
6977 }
6978 }
6979 return res;
6980 }
6981 }
6982
6983 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6984 int j;
6985 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6986 TaskRecord jt = startTask;
6987
6988 // First look backwards
6989 for (j=startIndex-1; j>=0; j--) {
6990 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6991 if (r.task != jt) {
6992 jt = r.task;
6993 if (affinity.equals(jt.affinity)) {
6994 return j;
6995 }
6996 }
6997 }
6998
6999 // Now look forwards
7000 final int N = mHistory.size();
7001 jt = startTask;
7002 for (j=startIndex+1; j<N; j++) {
7003 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7004 if (r.task != jt) {
7005 if (affinity.equals(jt.affinity)) {
7006 return j;
7007 }
7008 jt = r.task;
7009 }
7010 }
7011
7012 // Might it be at the top?
7013 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
7014 return N-1;
7015 }
7016
7017 return -1;
7018 }
7019
7020 /**
7021 * Perform a reset of the given task, if needed as part of launching it.
7022 * Returns the new HistoryRecord at the top of the task.
7023 */
7024 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
7025 HistoryRecord newActivity) {
7026 boolean forceReset = (newActivity.info.flags
7027 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
7028 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
7029 if ((newActivity.info.flags
7030 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
7031 forceReset = true;
7032 }
7033 }
7034
7035 final TaskRecord task = taskTop.task;
7036
7037 // We are going to move through the history list so that we can look
7038 // at each activity 'target' with 'below' either the interesting
7039 // activity immediately below it in the stack or null.
7040 HistoryRecord target = null;
7041 int targetI = 0;
7042 int taskTopI = -1;
7043 int replyChainEnd = -1;
7044 int lastReparentPos = -1;
7045 for (int i=mHistory.size()-1; i>=-1; i--) {
7046 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
7047
7048 if (below != null && below.finishing) {
7049 continue;
7050 }
7051 if (target == null) {
7052 target = below;
7053 targetI = i;
7054 // If we were in the middle of a reply chain before this
7055 // task, it doesn't appear like the root of the chain wants
7056 // anything interesting, so drop it.
7057 replyChainEnd = -1;
7058 continue;
7059 }
7060
7061 final int flags = target.info.flags;
7062
7063 final boolean finishOnTaskLaunch =
7064 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7065 final boolean allowTaskReparenting =
7066 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7067
7068 if (target.task == task) {
7069 // We are inside of the task being reset... we'll either
7070 // finish this activity, push it out for another task,
7071 // or leave it as-is. We only do this
7072 // for activities that are not the root of the task (since
7073 // if we finish the root, we may no longer have the task!).
7074 if (taskTopI < 0) {
7075 taskTopI = targetI;
7076 }
7077 if (below != null && below.task == task) {
7078 final boolean clearWhenTaskReset =
7079 (target.intent.getFlags()
7080 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007081 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007082 // If this activity is sending a reply to a previous
7083 // activity, we can't do anything with it now until
7084 // we reach the start of the reply chain.
7085 // XXX note that we are assuming the result is always
7086 // to the previous activity, which is almost always
7087 // the case but we really shouldn't count on.
7088 if (replyChainEnd < 0) {
7089 replyChainEnd = targetI;
7090 }
Ed Heyl73798232009-03-24 21:32:21 -07007091 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 && target.taskAffinity != null
7093 && !target.taskAffinity.equals(task.affinity)) {
7094 // If this activity has an affinity for another
7095 // task, then we need to move it out of here. We will
7096 // move it as far out of the way as possible, to the
7097 // bottom of the activity stack. This also keeps it
7098 // correctly ordered with any activities we previously
7099 // moved.
7100 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7101 if (target.taskAffinity != null
7102 && target.taskAffinity.equals(p.task.affinity)) {
7103 // If the activity currently at the bottom has the
7104 // same task affinity as the one we are moving,
7105 // then merge it into the same task.
7106 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007107 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007108 + " out to bottom task " + p.task);
7109 } else {
7110 mCurTask++;
7111 if (mCurTask <= 0) {
7112 mCurTask = 1;
7113 }
7114 target.task = new TaskRecord(mCurTask, target.info, null,
7115 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7116 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007117 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007118 + " out to new task " + target.task);
7119 }
7120 mWindowManager.setAppGroupId(target, task.taskId);
7121 if (replyChainEnd < 0) {
7122 replyChainEnd = targetI;
7123 }
7124 int dstPos = 0;
7125 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7126 p = (HistoryRecord)mHistory.get(srcPos);
7127 if (p.finishing) {
7128 continue;
7129 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007130 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007131 + " out to target's task " + target.task);
7132 task.numActivities--;
7133 p.task = target.task;
7134 target.task.numActivities++;
7135 mHistory.remove(srcPos);
7136 mHistory.add(dstPos, p);
7137 mWindowManager.moveAppToken(dstPos, p);
7138 mWindowManager.setAppGroupId(p, p.task.taskId);
7139 dstPos++;
7140 if (VALIDATE_TOKENS) {
7141 mWindowManager.validateAppTokens(mHistory);
7142 }
7143 i++;
7144 }
7145 if (taskTop == p) {
7146 taskTop = below;
7147 }
7148 if (taskTopI == replyChainEnd) {
7149 taskTopI = -1;
7150 }
7151 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007152 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007153 } else if (forceReset || finishOnTaskLaunch
7154 || clearWhenTaskReset) {
7155 // If the activity should just be removed -- either
7156 // because it asks for it, or the task should be
7157 // cleared -- then finish it and anything that is
7158 // part of its reply chain.
7159 if (clearWhenTaskReset) {
7160 // In this case, we want to finish this activity
7161 // and everything above it, so be sneaky and pretend
7162 // like these are all in the reply chain.
7163 replyChainEnd = targetI+1;
7164 while (replyChainEnd < mHistory.size() &&
7165 ((HistoryRecord)mHistory.get(
7166 replyChainEnd)).task == task) {
7167 replyChainEnd++;
7168 }
7169 replyChainEnd--;
7170 } else if (replyChainEnd < 0) {
7171 replyChainEnd = targetI;
7172 }
7173 HistoryRecord p = null;
7174 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7175 p = (HistoryRecord)mHistory.get(srcPos);
7176 if (p.finishing) {
7177 continue;
7178 }
7179 if (finishActivityLocked(p, srcPos,
7180 Activity.RESULT_CANCELED, null, "reset")) {
7181 replyChainEnd--;
7182 srcPos--;
7183 }
7184 }
7185 if (taskTop == p) {
7186 taskTop = below;
7187 }
7188 if (taskTopI == replyChainEnd) {
7189 taskTopI = -1;
7190 }
7191 replyChainEnd = -1;
7192 } else {
7193 // If we were in the middle of a chain, well the
7194 // activity that started it all doesn't want anything
7195 // special, so leave it all as-is.
7196 replyChainEnd = -1;
7197 }
7198 } else {
7199 // Reached the bottom of the task -- any reply chain
7200 // should be left as-is.
7201 replyChainEnd = -1;
7202 }
7203
7204 } else if (target.resultTo != null) {
7205 // If this activity is sending a reply to a previous
7206 // activity, we can't do anything with it now until
7207 // we reach the start of the reply chain.
7208 // XXX note that we are assuming the result is always
7209 // to the previous activity, which is almost always
7210 // the case but we really shouldn't count on.
7211 if (replyChainEnd < 0) {
7212 replyChainEnd = targetI;
7213 }
7214
7215 } else if (taskTopI >= 0 && allowTaskReparenting
7216 && task.affinity != null
7217 && task.affinity.equals(target.taskAffinity)) {
7218 // We are inside of another task... if this activity has
7219 // an affinity for our task, then either remove it if we are
7220 // clearing or move it over to our task. Note that
7221 // we currently punt on the case where we are resetting a
7222 // task that is not at the top but who has activities above
7223 // with an affinity to it... this is really not a normal
7224 // case, and we will need to later pull that task to the front
7225 // and usually at that point we will do the reset and pick
7226 // up those remaining activities. (This only happens if
7227 // someone starts an activity in a new task from an activity
7228 // in a task that is not currently on top.)
7229 if (forceReset || finishOnTaskLaunch) {
7230 if (replyChainEnd < 0) {
7231 replyChainEnd = targetI;
7232 }
7233 HistoryRecord p = null;
7234 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7235 p = (HistoryRecord)mHistory.get(srcPos);
7236 if (p.finishing) {
7237 continue;
7238 }
7239 if (finishActivityLocked(p, srcPos,
7240 Activity.RESULT_CANCELED, null, "reset")) {
7241 taskTopI--;
7242 lastReparentPos--;
7243 replyChainEnd--;
7244 srcPos--;
7245 }
7246 }
7247 replyChainEnd = -1;
7248 } else {
7249 if (replyChainEnd < 0) {
7250 replyChainEnd = targetI;
7251 }
7252 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7253 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7254 if (p.finishing) {
7255 continue;
7256 }
7257 if (lastReparentPos < 0) {
7258 lastReparentPos = taskTopI;
7259 taskTop = p;
7260 } else {
7261 lastReparentPos--;
7262 }
7263 mHistory.remove(srcPos);
7264 p.task.numActivities--;
7265 p.task = task;
7266 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007267 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007268 + " in to resetting task " + task);
7269 task.numActivities++;
7270 mWindowManager.moveAppToken(lastReparentPos, p);
7271 mWindowManager.setAppGroupId(p, p.task.taskId);
7272 if (VALIDATE_TOKENS) {
7273 mWindowManager.validateAppTokens(mHistory);
7274 }
7275 }
7276 replyChainEnd = -1;
7277
7278 // Now we've moved it in to place... but what if this is
7279 // a singleTop activity and we have put it on top of another
7280 // instance of the same activity? Then we drop the instance
7281 // below so it remains singleTop.
7282 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7283 for (int j=lastReparentPos-1; j>=0; j--) {
7284 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7285 if (p.finishing) {
7286 continue;
7287 }
7288 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7289 if (finishActivityLocked(p, j,
7290 Activity.RESULT_CANCELED, null, "replace")) {
7291 taskTopI--;
7292 lastReparentPos--;
7293 }
7294 }
7295 }
7296 }
7297 }
7298 }
7299
7300 target = below;
7301 targetI = i;
7302 }
7303
7304 return taskTop;
7305 }
7306
7307 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007308 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007309 */
7310 public void moveTaskToFront(int task) {
7311 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7312 "moveTaskToFront()");
7313
7314 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007315 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7316 Binder.getCallingUid(), "Task to front")) {
7317 return;
7318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007319 final long origId = Binder.clearCallingIdentity();
7320 try {
7321 int N = mRecentTasks.size();
7322 for (int i=0; i<N; i++) {
7323 TaskRecord tr = mRecentTasks.get(i);
7324 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007325 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 return;
7327 }
7328 }
7329 for (int i=mHistory.size()-1; i>=0; i--) {
7330 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7331 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007332 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007333 return;
7334 }
7335 }
7336 } finally {
7337 Binder.restoreCallingIdentity(origId);
7338 }
7339 }
7340 }
7341
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007342 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007343 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007344
7345 final int task = tr.taskId;
7346 int top = mHistory.size()-1;
7347
7348 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7349 // nothing to do!
7350 return;
7351 }
7352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 ArrayList moved = new ArrayList();
7354
7355 // Applying the affinities may have removed entries from the history,
7356 // so get the size again.
7357 top = mHistory.size()-1;
7358 int pos = top;
7359
7360 // Shift all activities with this task up to the top
7361 // of the stack, keeping them in the same internal order.
7362 while (pos >= 0) {
7363 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007364 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7366 boolean first = true;
7367 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007368 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 mHistory.remove(pos);
7370 mHistory.add(top, r);
7371 moved.add(0, r);
7372 top--;
7373 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007374 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007375 first = false;
7376 }
7377 }
7378 pos--;
7379 }
7380
Joe Onorato8a9b2202010-02-26 18:56:32 -08007381 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007382 "Prepare to front transition: task=" + tr);
7383 if (reason != null &&
7384 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7385 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7386 HistoryRecord r = topRunningActivityLocked(null);
7387 if (r != null) {
7388 mNoAnimActivities.add(r);
7389 }
7390 } else {
7391 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7392 }
7393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007394 mWindowManager.moveAppTokensToTop(moved);
7395 if (VALIDATE_TOKENS) {
7396 mWindowManager.validateAppTokens(mHistory);
7397 }
7398
Josh Bartel7f208742010-02-25 11:01:44 -06007399 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007400 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 }
7402
Josh Bartel7f208742010-02-25 11:01:44 -06007403 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007404 resumeTopActivityLocked(null);
7405 }
7406
7407 public void moveTaskToBack(int task) {
7408 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7409 "moveTaskToBack()");
7410
7411 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007412 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7413 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7414 Binder.getCallingUid(), "Task to back")) {
7415 return;
7416 }
7417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007418 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007419 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007420 Binder.restoreCallingIdentity(origId);
7421 }
7422 }
7423
7424 /**
7425 * Moves an activity, and all of the other activities within the same task, to the bottom
7426 * of the history stack. The activity's order within the task is unchanged.
7427 *
7428 * @param token A reference to the activity we wish to move
7429 * @param nonRoot If false then this only works if the activity is the root
7430 * of a task; if true it will work for any activity in a task.
7431 * @return Returns true if the move completed, false if not.
7432 */
7433 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7434 synchronized(this) {
7435 final long origId = Binder.clearCallingIdentity();
7436 int taskId = getTaskForActivityLocked(token, !nonRoot);
7437 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007438 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007439 }
7440 Binder.restoreCallingIdentity(origId);
7441 }
7442 return false;
7443 }
7444
7445 /**
7446 * Worker method for rearranging history stack. Implements the function of moving all
7447 * activities for a specific task (gathering them if disjoint) into a single group at the
7448 * bottom of the stack.
7449 *
7450 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7451 * to premeptively cancel the move.
7452 *
7453 * @param task The taskId to collect and move to the bottom.
7454 * @return Returns true if the move completed, false if not.
7455 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007456 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007457 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458
7459 // If we have a watcher, preflight the move before committing to it. First check
7460 // for *other* available tasks, but if none are available, then try again allowing the
7461 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007462 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007463 HistoryRecord next = topRunningActivityLocked(null, task);
7464 if (next == null) {
7465 next = topRunningActivityLocked(null, 0);
7466 }
7467 if (next != null) {
7468 // ask watcher if this is allowed
7469 boolean moveOK = true;
7470 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007471 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007472 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007473 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007474 }
7475 if (!moveOK) {
7476 return false;
7477 }
7478 }
7479 }
7480
7481 ArrayList moved = new ArrayList();
7482
Joe Onorato8a9b2202010-02-26 18:56:32 -08007483 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007484 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007485
7486 final int N = mHistory.size();
7487 int bottom = 0;
7488 int pos = 0;
7489
7490 // Shift all activities with this task down to the bottom
7491 // of the stack, keeping them in the same internal order.
7492 while (pos < N) {
7493 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007494 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7496 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007497 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007498 mHistory.remove(pos);
7499 mHistory.add(bottom, r);
7500 moved.add(r);
7501 bottom++;
7502 }
7503 pos++;
7504 }
7505
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007506 if (reason != null &&
7507 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7508 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7509 HistoryRecord r = topRunningActivityLocked(null);
7510 if (r != null) {
7511 mNoAnimActivities.add(r);
7512 }
7513 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007514 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007516 mWindowManager.moveAppTokensToBottom(moved);
7517 if (VALIDATE_TOKENS) {
7518 mWindowManager.validateAppTokens(mHistory);
7519 }
7520
Josh Bartel7f208742010-02-25 11:01:44 -06007521 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007522 return true;
7523 }
7524
7525 public void moveTaskBackwards(int task) {
7526 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7527 "moveTaskBackwards()");
7528
7529 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007530 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7531 Binder.getCallingUid(), "Task backwards")) {
7532 return;
7533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534 final long origId = Binder.clearCallingIdentity();
7535 moveTaskBackwardsLocked(task);
7536 Binder.restoreCallingIdentity(origId);
7537 }
7538 }
7539
7540 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007541 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542 }
7543
7544 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7545 synchronized(this) {
7546 return getTaskForActivityLocked(token, onlyRoot);
7547 }
7548 }
7549
7550 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7551 final int N = mHistory.size();
7552 TaskRecord lastTask = null;
7553 for (int i=0; i<N; i++) {
7554 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7555 if (r == token) {
7556 if (!onlyRoot || lastTask != r.task) {
7557 return r.task.taskId;
7558 }
7559 return -1;
7560 }
7561 lastTask = r.task;
7562 }
7563
7564 return -1;
7565 }
7566
7567 /**
7568 * Returns the top activity in any existing task matching the given
7569 * Intent. Returns null if no such task is found.
7570 */
7571 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7572 ComponentName cls = intent.getComponent();
7573 if (info.targetActivity != null) {
7574 cls = new ComponentName(info.packageName, info.targetActivity);
7575 }
7576
7577 TaskRecord cp = null;
7578
7579 final int N = mHistory.size();
7580 for (int i=(N-1); i>=0; i--) {
7581 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7582 if (!r.finishing && r.task != cp
7583 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7584 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007585 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586 // + "/aff=" + r.task.affinity + " to new cls="
7587 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7588 if (r.task.affinity != null) {
7589 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007590 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 return r;
7592 }
7593 } else if (r.task.intent != null
7594 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007595 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007596 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007597 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007598 return r;
7599 } else if (r.task.affinityIntent != null
7600 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007601 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007602 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007603 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007604 return r;
7605 }
7606 }
7607 }
7608
7609 return null;
7610 }
7611
7612 /**
7613 * Returns the first activity (starting from the top of the stack) that
7614 * is the same as the given activity. Returns null if no such activity
7615 * is found.
7616 */
7617 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7618 ComponentName cls = intent.getComponent();
7619 if (info.targetActivity != null) {
7620 cls = new ComponentName(info.packageName, info.targetActivity);
7621 }
7622
7623 final int N = mHistory.size();
7624 for (int i=(N-1); i>=0; i--) {
7625 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7626 if (!r.finishing) {
7627 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007628 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007629 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007630 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 return r;
7632 }
7633 }
7634 }
7635
7636 return null;
7637 }
7638
7639 public void finishOtherInstances(IBinder token, ComponentName className) {
7640 synchronized(this) {
7641 final long origId = Binder.clearCallingIdentity();
7642
7643 int N = mHistory.size();
7644 TaskRecord lastTask = null;
7645 for (int i=0; i<N; i++) {
7646 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7647 if (r.realActivity.equals(className)
7648 && r != token && lastTask != r.task) {
7649 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7650 null, "others")) {
7651 i--;
7652 N--;
7653 }
7654 }
7655 lastTask = r.task;
7656 }
7657
7658 Binder.restoreCallingIdentity(origId);
7659 }
7660 }
7661
7662 // =========================================================
7663 // THUMBNAILS
7664 // =========================================================
7665
7666 public void reportThumbnail(IBinder token,
7667 Bitmap thumbnail, CharSequence description) {
7668 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7669 final long origId = Binder.clearCallingIdentity();
7670 sendPendingThumbnail(null, token, thumbnail, description, true);
7671 Binder.restoreCallingIdentity(origId);
7672 }
7673
7674 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7675 Bitmap thumbnail, CharSequence description, boolean always) {
7676 TaskRecord task = null;
7677 ArrayList receivers = null;
7678
7679 //System.out.println("Send pending thumbnail: " + r);
7680
7681 synchronized(this) {
7682 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007683 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684 if (index < 0) {
7685 return;
7686 }
7687 r = (HistoryRecord)mHistory.get(index);
7688 }
7689 if (thumbnail == null) {
7690 thumbnail = r.thumbnail;
7691 description = r.description;
7692 }
7693 if (thumbnail == null && !always) {
7694 // If there is no thumbnail, and this entry is not actually
7695 // going away, then abort for now and pick up the next
7696 // thumbnail we get.
7697 return;
7698 }
7699 task = r.task;
7700
7701 int N = mPendingThumbnails.size();
7702 int i=0;
7703 while (i<N) {
7704 PendingThumbnailsRecord pr =
7705 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7706 //System.out.println("Looking in " + pr.pendingRecords);
7707 if (pr.pendingRecords.remove(r)) {
7708 if (receivers == null) {
7709 receivers = new ArrayList();
7710 }
7711 receivers.add(pr);
7712 if (pr.pendingRecords.size() == 0) {
7713 pr.finished = true;
7714 mPendingThumbnails.remove(i);
7715 N--;
7716 continue;
7717 }
7718 }
7719 i++;
7720 }
7721 }
7722
7723 if (receivers != null) {
7724 final int N = receivers.size();
7725 for (int i=0; i<N; i++) {
7726 try {
7727 PendingThumbnailsRecord pr =
7728 (PendingThumbnailsRecord)receivers.get(i);
7729 pr.receiver.newThumbnail(
7730 task != null ? task.taskId : -1, thumbnail, description);
7731 if (pr.finished) {
7732 pr.receiver.finished();
7733 }
7734 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007735 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007736 }
7737 }
7738 }
7739 }
7740
7741 // =========================================================
7742 // CONTENT PROVIDERS
7743 // =========================================================
7744
7745 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7746 List providers = null;
7747 try {
7748 providers = ActivityThread.getPackageManager().
7749 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007750 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751 } catch (RemoteException ex) {
7752 }
7753 if (providers != null) {
7754 final int N = providers.size();
7755 for (int i=0; i<N; i++) {
7756 ProviderInfo cpi =
7757 (ProviderInfo)providers.get(i);
7758 ContentProviderRecord cpr =
7759 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7760 if (cpr == null) {
7761 cpr = new ContentProviderRecord(cpi, app.info);
7762 mProvidersByClass.put(cpi.name, cpr);
7763 }
7764 app.pubProviders.put(cpi.name, cpr);
7765 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007766 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007767 }
7768 }
7769 return providers;
7770 }
7771
7772 private final String checkContentProviderPermissionLocked(
7773 ProviderInfo cpi, ProcessRecord r, int mode) {
7774 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7775 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7776 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7777 cpi.exported ? -1 : cpi.applicationInfo.uid)
7778 == PackageManager.PERMISSION_GRANTED
7779 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7780 return null;
7781 }
7782 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7783 cpi.exported ? -1 : cpi.applicationInfo.uid)
7784 == PackageManager.PERMISSION_GRANTED) {
7785 return null;
7786 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007787
7788 PathPermission[] pps = cpi.pathPermissions;
7789 if (pps != null) {
7790 int i = pps.length;
7791 while (i > 0) {
7792 i--;
7793 PathPermission pp = pps[i];
7794 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7795 cpi.exported ? -1 : cpi.applicationInfo.uid)
7796 == PackageManager.PERMISSION_GRANTED
7797 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7798 return null;
7799 }
7800 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7801 cpi.exported ? -1 : cpi.applicationInfo.uid)
7802 == PackageManager.PERMISSION_GRANTED) {
7803 return null;
7804 }
7805 }
7806 }
7807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808 String msg = "Permission Denial: opening provider " + cpi.name
7809 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7810 + ", uid=" + callingUid + ") requires "
7811 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007812 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007813 return msg;
7814 }
7815
7816 private final ContentProviderHolder getContentProviderImpl(
7817 IApplicationThread caller, String name) {
7818 ContentProviderRecord cpr;
7819 ProviderInfo cpi = null;
7820
7821 synchronized(this) {
7822 ProcessRecord r = null;
7823 if (caller != null) {
7824 r = getRecordForAppLocked(caller);
7825 if (r == null) {
7826 throw new SecurityException(
7827 "Unable to find app for caller " + caller
7828 + " (pid=" + Binder.getCallingPid()
7829 + ") when getting content provider " + name);
7830 }
7831 }
7832
7833 // First check if this content provider has been published...
7834 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7835 if (cpr != null) {
7836 cpi = cpr.info;
7837 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7838 return new ContentProviderHolder(cpi,
7839 cpi.readPermission != null
7840 ? cpi.readPermission : cpi.writePermission);
7841 }
7842
7843 if (r != null && cpr.canRunHere(r)) {
7844 // This provider has been published or is in the process
7845 // of being published... but it is also allowed to run
7846 // in the caller's process, so don't make a connection
7847 // and just let the caller instantiate its own instance.
7848 if (cpr.provider != null) {
7849 // don't give caller the provider object, it needs
7850 // to make its own.
7851 cpr = new ContentProviderRecord(cpr);
7852 }
7853 return cpr;
7854 }
7855
7856 final long origId = Binder.clearCallingIdentity();
7857
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007858 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007859 // return it right away.
7860 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007861 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007862 "Adding provider requested by "
7863 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007864 + cpr.info.processName);
7865 Integer cnt = r.conProviders.get(cpr);
7866 if (cnt == null) {
7867 r.conProviders.put(cpr, new Integer(1));
7868 } else {
7869 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7870 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007871 cpr.clients.add(r);
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07007872 if (cpr.app != null && r.setAdj >= VISIBLE_APP_ADJ) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07007873 // If this is a visible app accessing the provider,
7874 // make sure to count it as being accessed and thus
7875 // back up on the LRU list. This is good because
7876 // content providers are often expensive to start.
7877 updateLruProcessLocked(cpr.app, false, true);
7878 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07007879 } else {
7880 cpr.externals++;
7881 }
7882
7883 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007884 updateOomAdjLocked(cpr.app);
7885 }
7886
7887 Binder.restoreCallingIdentity(origId);
7888
7889 } else {
7890 try {
7891 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007892 resolveContentProvider(name,
7893 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007894 } catch (RemoteException ex) {
7895 }
7896 if (cpi == null) {
7897 return null;
7898 }
7899
7900 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7901 return new ContentProviderHolder(cpi,
7902 cpi.readPermission != null
7903 ? cpi.readPermission : cpi.writePermission);
7904 }
7905
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007906 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7907 && !cpi.processName.equals("system")) {
7908 // If this content provider does not run in the system
7909 // process, and the system is not yet ready to run other
7910 // processes, then fail fast instead of hanging.
7911 throw new IllegalArgumentException(
7912 "Attempt to launch content provider before system ready");
7913 }
7914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7916 final boolean firstClass = cpr == null;
7917 if (firstClass) {
7918 try {
7919 ApplicationInfo ai =
7920 ActivityThread.getPackageManager().
7921 getApplicationInfo(
7922 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007923 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007924 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007925 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007926 + cpi.name);
7927 return null;
7928 }
7929 cpr = new ContentProviderRecord(cpi, ai);
7930 } catch (RemoteException ex) {
7931 // pm is in same process, this will never happen.
7932 }
7933 }
7934
7935 if (r != null && cpr.canRunHere(r)) {
7936 // If this is a multiprocess provider, then just return its
7937 // info and allow the caller to instantiate it. Only do
7938 // this if the provider is the same user as the caller's
7939 // process, or can run as root (so can be in any process).
7940 return cpr;
7941 }
7942
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007943 if (DEBUG_PROVIDER) {
7944 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007945 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007946 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007947 }
7948
7949 // This is single process, and our app is now connecting to it.
7950 // See if we are already in the process of launching this
7951 // provider.
7952 final int N = mLaunchingProviders.size();
7953 int i;
7954 for (i=0; i<N; i++) {
7955 if (mLaunchingProviders.get(i) == cpr) {
7956 break;
7957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007958 }
7959
7960 // If the provider is not already being launched, then get it
7961 // started.
7962 if (i >= N) {
7963 final long origId = Binder.clearCallingIdentity();
7964 ProcessRecord proc = startProcessLocked(cpi.processName,
7965 cpr.appInfo, false, 0, "content provider",
7966 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007967 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007968 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007969 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007970 + cpi.applicationInfo.packageName + "/"
7971 + cpi.applicationInfo.uid + " for provider "
7972 + name + ": process is bad");
7973 return null;
7974 }
7975 cpr.launchingApp = proc;
7976 mLaunchingProviders.add(cpr);
7977 Binder.restoreCallingIdentity(origId);
7978 }
7979
7980 // Make sure the provider is published (the same provider class
7981 // may be published under multiple names).
7982 if (firstClass) {
7983 mProvidersByClass.put(cpi.name, cpr);
7984 }
7985 mProvidersByName.put(name, cpr);
7986
7987 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007988 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007989 "Adding provider requested by "
7990 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007991 + cpr.info.processName);
7992 Integer cnt = r.conProviders.get(cpr);
7993 if (cnt == null) {
7994 r.conProviders.put(cpr, new Integer(1));
7995 } else {
7996 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007998 cpr.clients.add(r);
7999 } else {
8000 cpr.externals++;
8001 }
8002 }
8003 }
8004
8005 // Wait for the provider to be published...
8006 synchronized (cpr) {
8007 while (cpr.provider == null) {
8008 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008009 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008010 + cpi.applicationInfo.packageName + "/"
8011 + cpi.applicationInfo.uid + " for provider "
8012 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008013 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008014 cpi.applicationInfo.packageName,
8015 cpi.applicationInfo.uid, name);
8016 return null;
8017 }
8018 try {
8019 cpr.wait();
8020 } catch (InterruptedException ex) {
8021 }
8022 }
8023 }
8024 return cpr;
8025 }
8026
8027 public final ContentProviderHolder getContentProvider(
8028 IApplicationThread caller, String name) {
8029 if (caller == null) {
8030 String msg = "null IApplicationThread when getting content provider "
8031 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008032 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008033 throw new SecurityException(msg);
8034 }
8035
8036 return getContentProviderImpl(caller, name);
8037 }
8038
8039 private ContentProviderHolder getContentProviderExternal(String name) {
8040 return getContentProviderImpl(null, name);
8041 }
8042
8043 /**
8044 * Drop a content provider from a ProcessRecord's bookkeeping
8045 * @param cpr
8046 */
8047 public void removeContentProvider(IApplicationThread caller, String name) {
8048 synchronized (this) {
8049 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
8050 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008051 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008052 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008053 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008054 return;
8055 }
8056 final ProcessRecord r = getRecordForAppLocked(caller);
8057 if (r == null) {
8058 throw new SecurityException(
8059 "Unable to find app for caller " + caller +
8060 " when removing content provider " + name);
8061 }
8062 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008063 ContentProviderRecord localCpr = (ContentProviderRecord)
8064 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008065 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008066 + r.info.processName + " from process "
8067 + localCpr.appInfo.processName);
8068 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008070 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008071 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 return;
8073 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008074 Integer cnt = r.conProviders.get(localCpr);
8075 if (cnt == null || cnt.intValue() <= 1) {
8076 localCpr.clients.remove(r);
8077 r.conProviders.remove(localCpr);
8078 } else {
8079 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 }
8082 updateOomAdjLocked();
8083 }
8084 }
8085
8086 private void removeContentProviderExternal(String name) {
8087 synchronized (this) {
8088 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
8089 if(cpr == null) {
8090 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008091 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008092 return;
8093 }
8094
8095 //update content provider record entry info
8096 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
8097 localCpr.externals--;
8098 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008099 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008100 }
8101 updateOomAdjLocked();
8102 }
8103 }
8104
8105 public final void publishContentProviders(IApplicationThread caller,
8106 List<ContentProviderHolder> providers) {
8107 if (providers == null) {
8108 return;
8109 }
8110
8111 synchronized(this) {
8112 final ProcessRecord r = getRecordForAppLocked(caller);
8113 if (r == null) {
8114 throw new SecurityException(
8115 "Unable to find app for caller " + caller
8116 + " (pid=" + Binder.getCallingPid()
8117 + ") when publishing content providers");
8118 }
8119
8120 final long origId = Binder.clearCallingIdentity();
8121
8122 final int N = providers.size();
8123 for (int i=0; i<N; i++) {
8124 ContentProviderHolder src = providers.get(i);
8125 if (src == null || src.info == null || src.provider == null) {
8126 continue;
8127 }
8128 ContentProviderRecord dst =
8129 (ContentProviderRecord)r.pubProviders.get(src.info.name);
8130 if (dst != null) {
8131 mProvidersByClass.put(dst.info.name, dst);
8132 String names[] = dst.info.authority.split(";");
8133 for (int j = 0; j < names.length; j++) {
8134 mProvidersByName.put(names[j], dst);
8135 }
8136
8137 int NL = mLaunchingProviders.size();
8138 int j;
8139 for (j=0; j<NL; j++) {
8140 if (mLaunchingProviders.get(j) == dst) {
8141 mLaunchingProviders.remove(j);
8142 j--;
8143 NL--;
8144 }
8145 }
8146 synchronized (dst) {
8147 dst.provider = src.provider;
8148 dst.app = r;
8149 dst.notifyAll();
8150 }
8151 updateOomAdjLocked(r);
8152 }
8153 }
8154
8155 Binder.restoreCallingIdentity(origId);
8156 }
8157 }
8158
8159 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008160 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008161 synchronized (mSelf) {
8162 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8163 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008164 if (providers != null) {
8165 for (int i=providers.size()-1; i>=0; i--) {
8166 ProviderInfo pi = (ProviderInfo)providers.get(i);
8167 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8168 Slog.w(TAG, "Not installing system proc provider " + pi.name
8169 + ": not system .apk");
8170 providers.remove(i);
8171 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008172 }
8173 }
8174 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008175 if (providers != null) {
8176 mSystemThread.installSystemProviders(providers);
8177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 }
8179
8180 // =========================================================
8181 // GLOBAL MANAGEMENT
8182 // =========================================================
8183
8184 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8185 ApplicationInfo info, String customProcess) {
8186 String proc = customProcess != null ? customProcess : info.processName;
8187 BatteryStatsImpl.Uid.Proc ps = null;
8188 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8189 synchronized (stats) {
8190 ps = stats.getProcessStatsLocked(info.uid, proc);
8191 }
8192 return new ProcessRecord(ps, thread, info, proc);
8193 }
8194
8195 final ProcessRecord addAppLocked(ApplicationInfo info) {
8196 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8197
8198 if (app == null) {
8199 app = newProcessRecordLocked(null, info, null);
8200 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008201 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202 }
8203
8204 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8205 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8206 app.persistent = true;
8207 app.maxAdj = CORE_SERVER_ADJ;
8208 }
8209 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8210 mPersistentStartingProcesses.add(app);
8211 startProcessLocked(app, "added application", app.processName);
8212 }
8213
8214 return app;
8215 }
8216
8217 public void unhandledBack() {
8218 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8219 "unhandledBack()");
8220
8221 synchronized(this) {
8222 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008223 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008224 TAG, "Performing unhandledBack(): stack size = " + count);
8225 if (count > 1) {
8226 final long origId = Binder.clearCallingIdentity();
8227 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8228 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8229 Binder.restoreCallingIdentity(origId);
8230 }
8231 }
8232 }
8233
8234 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8235 String name = uri.getAuthority();
8236 ContentProviderHolder cph = getContentProviderExternal(name);
8237 ParcelFileDescriptor pfd = null;
8238 if (cph != null) {
8239 // We record the binder invoker's uid in thread-local storage before
8240 // going to the content provider to open the file. Later, in the code
8241 // that handles all permissions checks, we look for this uid and use
8242 // that rather than the Activity Manager's own uid. The effect is that
8243 // we do the check against the caller's permissions even though it looks
8244 // to the content provider like the Activity Manager itself is making
8245 // the request.
8246 sCallerIdentity.set(new Identity(
8247 Binder.getCallingPid(), Binder.getCallingUid()));
8248 try {
8249 pfd = cph.provider.openFile(uri, "r");
8250 } catch (FileNotFoundException e) {
8251 // do nothing; pfd will be returned null
8252 } finally {
8253 // Ensure that whatever happens, we clean up the identity state
8254 sCallerIdentity.remove();
8255 }
8256
8257 // We've got the fd now, so we're done with the provider.
8258 removeContentProviderExternal(name);
8259 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008260 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008261 }
8262 return pfd;
8263 }
8264
8265 public void goingToSleep() {
8266 synchronized(this) {
8267 mSleeping = true;
8268 mWindowManager.setEventDispatching(false);
8269
8270 if (mResumedActivity != null) {
8271 pauseIfSleepingLocked();
8272 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008273 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008274 }
8275 }
8276 }
8277
Dianne Hackborn55280a92009-05-07 15:53:46 -07008278 public boolean shutdown(int timeout) {
8279 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8280 != PackageManager.PERMISSION_GRANTED) {
8281 throw new SecurityException("Requires permission "
8282 + android.Manifest.permission.SHUTDOWN);
8283 }
8284
8285 boolean timedout = false;
8286
8287 synchronized(this) {
8288 mShuttingDown = true;
8289 mWindowManager.setEventDispatching(false);
8290
8291 if (mResumedActivity != null) {
8292 pauseIfSleepingLocked();
8293 final long endTime = System.currentTimeMillis() + timeout;
8294 while (mResumedActivity != null || mPausingActivity != null) {
8295 long delay = endTime - System.currentTimeMillis();
8296 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008297 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008298 timedout = true;
8299 break;
8300 }
8301 try {
8302 this.wait();
8303 } catch (InterruptedException e) {
8304 }
8305 }
8306 }
8307 }
8308
8309 mUsageStatsService.shutdown();
8310 mBatteryStatsService.shutdown();
8311
8312 return timedout;
8313 }
8314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008315 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008316 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008317 if (!mGoingToSleep.isHeld()) {
8318 mGoingToSleep.acquire();
8319 if (mLaunchingActivity.isHeld()) {
8320 mLaunchingActivity.release();
8321 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8322 }
8323 }
8324
8325 // If we are not currently pausing an activity, get the current
8326 // one to pause. If we are pausing one, we will just let that stuff
8327 // run and release the wake lock when all done.
8328 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008329 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8330 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008331 startPausingLocked(false, true);
8332 }
8333 }
8334 }
8335
8336 public void wakingUp() {
8337 synchronized(this) {
8338 if (mGoingToSleep.isHeld()) {
8339 mGoingToSleep.release();
8340 }
8341 mWindowManager.setEventDispatching(true);
8342 mSleeping = false;
8343 resumeTopActivityLocked(null);
8344 }
8345 }
8346
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008347 public void stopAppSwitches() {
8348 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8349 != PackageManager.PERMISSION_GRANTED) {
8350 throw new SecurityException("Requires permission "
8351 + android.Manifest.permission.STOP_APP_SWITCHES);
8352 }
8353
8354 synchronized(this) {
8355 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8356 + APP_SWITCH_DELAY_TIME;
8357 mDidAppSwitch = false;
8358 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8359 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8360 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8361 }
8362 }
8363
8364 public void resumeAppSwitches() {
8365 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8366 != PackageManager.PERMISSION_GRANTED) {
8367 throw new SecurityException("Requires permission "
8368 + android.Manifest.permission.STOP_APP_SWITCHES);
8369 }
8370
8371 synchronized(this) {
8372 // Note that we don't execute any pending app switches... we will
8373 // let those wait until either the timeout, or the next start
8374 // activity request.
8375 mAppSwitchesAllowedTime = 0;
8376 }
8377 }
8378
8379 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8380 String name) {
8381 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8382 return true;
8383 }
8384
8385 final int perm = checkComponentPermission(
8386 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8387 callingUid, -1);
8388 if (perm == PackageManager.PERMISSION_GRANTED) {
8389 return true;
8390 }
8391
Joe Onorato8a9b2202010-02-26 18:56:32 -08008392 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008393 return false;
8394 }
8395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008396 public void setDebugApp(String packageName, boolean waitForDebugger,
8397 boolean persistent) {
8398 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8399 "setDebugApp()");
8400
8401 // Note that this is not really thread safe if there are multiple
8402 // callers into it at the same time, but that's not a situation we
8403 // care about.
8404 if (persistent) {
8405 final ContentResolver resolver = mContext.getContentResolver();
8406 Settings.System.putString(
8407 resolver, Settings.System.DEBUG_APP,
8408 packageName);
8409 Settings.System.putInt(
8410 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8411 waitForDebugger ? 1 : 0);
8412 }
8413
8414 synchronized (this) {
8415 if (!persistent) {
8416 mOrigDebugApp = mDebugApp;
8417 mOrigWaitForDebugger = mWaitForDebugger;
8418 }
8419 mDebugApp = packageName;
8420 mWaitForDebugger = waitForDebugger;
8421 mDebugTransient = !persistent;
8422 if (packageName != null) {
8423 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008424 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 Binder.restoreCallingIdentity(origId);
8426 }
8427 }
8428 }
8429
8430 public void setAlwaysFinish(boolean enabled) {
8431 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8432 "setAlwaysFinish()");
8433
8434 Settings.System.putInt(
8435 mContext.getContentResolver(),
8436 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8437
8438 synchronized (this) {
8439 mAlwaysFinishActivities = enabled;
8440 }
8441 }
8442
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008443 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008444 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008445 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008446 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008447 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008448 }
8449 }
8450
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008451 public boolean isUserAMonkey() {
8452 // For now the fact that there is a controller implies
8453 // we have a monkey.
8454 synchronized (this) {
8455 return mController != null;
8456 }
8457 }
8458
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008459 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008460 synchronized (this) {
8461 mWatchers.register(watcher);
8462 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008463 }
8464
8465 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008466 synchronized (this) {
8467 mWatchers.unregister(watcher);
8468 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008469 }
8470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 public final void enterSafeMode() {
8472 synchronized(this) {
8473 // It only makes sense to do this before the system is ready
8474 // and started launching other packages.
8475 if (!mSystemReady) {
8476 try {
8477 ActivityThread.getPackageManager().enterSafeMode();
8478 } catch (RemoteException e) {
8479 }
8480
8481 View v = LayoutInflater.from(mContext).inflate(
8482 com.android.internal.R.layout.safe_mode, null);
8483 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8484 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8485 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8486 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8487 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8488 lp.format = v.getBackground().getOpacity();
8489 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8490 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8491 ((WindowManager)mContext.getSystemService(
8492 Context.WINDOW_SERVICE)).addView(v, lp);
8493 }
8494 }
8495 }
8496
8497 public void noteWakeupAlarm(IIntentSender sender) {
8498 if (!(sender instanceof PendingIntentRecord)) {
8499 return;
8500 }
8501 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8502 synchronized (stats) {
8503 if (mBatteryStatsService.isOnBattery()) {
8504 mBatteryStatsService.enforceCallingPermission();
8505 PendingIntentRecord rec = (PendingIntentRecord)sender;
8506 int MY_UID = Binder.getCallingUid();
8507 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8508 BatteryStatsImpl.Uid.Pkg pkg =
8509 stats.getPackageStatsLocked(uid, rec.key.packageName);
8510 pkg.incWakeupsLocked();
8511 }
8512 }
8513 }
8514
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008515 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008517 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008519 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 // XXX Note: don't acquire main activity lock here, because the window
8521 // manager calls in with its locks held.
8522
8523 boolean killed = false;
8524 synchronized (mPidsSelfLocked) {
8525 int[] types = new int[pids.length];
8526 int worstType = 0;
8527 for (int i=0; i<pids.length; i++) {
8528 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8529 if (proc != null) {
8530 int type = proc.setAdj;
8531 types[i] = type;
8532 if (type > worstType) {
8533 worstType = type;
8534 }
8535 }
8536 }
8537
8538 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8539 // then constrain it so we will kill all hidden procs.
8540 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8541 worstType = HIDDEN_APP_MIN_ADJ;
8542 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008543 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008544 for (int i=0; i<pids.length; i++) {
8545 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8546 if (proc == null) {
8547 continue;
8548 }
8549 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008550 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008551 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008552 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8553 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008555 proc.killedBackground = true;
8556 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008557 }
8558 }
8559 }
8560 return killed;
8561 }
8562
8563 public void reportPss(IApplicationThread caller, int pss) {
8564 Watchdog.PssRequestor req;
8565 String name;
8566 ProcessRecord callerApp;
8567 synchronized (this) {
8568 if (caller == null) {
8569 return;
8570 }
8571 callerApp = getRecordForAppLocked(caller);
8572 if (callerApp == null) {
8573 return;
8574 }
8575 callerApp.lastPss = pss;
8576 req = callerApp;
8577 name = callerApp.processName;
8578 }
8579 Watchdog.getInstance().reportPss(req, name, pss);
8580 if (!callerApp.persistent) {
8581 removeRequestedPss(callerApp);
8582 }
8583 }
8584
8585 public void requestPss(Runnable completeCallback) {
8586 ArrayList<ProcessRecord> procs;
8587 synchronized (this) {
8588 mRequestPssCallback = completeCallback;
8589 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008590 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8591 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008592 if (!proc.persistent) {
8593 mRequestPssList.add(proc);
8594 }
8595 }
8596 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8597 }
8598
8599 int oldPri = Process.getThreadPriority(Process.myTid());
8600 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8601 for (int i=procs.size()-1; i>=0; i--) {
8602 ProcessRecord proc = procs.get(i);
8603 proc.lastPss = 0;
8604 proc.requestPss();
8605 }
8606 Process.setThreadPriority(oldPri);
8607 }
8608
8609 void removeRequestedPss(ProcessRecord proc) {
8610 Runnable callback = null;
8611 synchronized (this) {
8612 if (mRequestPssList.remove(proc)) {
8613 if (mRequestPssList.size() == 0) {
8614 callback = mRequestPssCallback;
8615 mRequestPssCallback = null;
8616 }
8617 }
8618 }
8619
8620 if (callback != null) {
8621 callback.run();
8622 }
8623 }
8624
8625 public void collectPss(Watchdog.PssStats stats) {
8626 stats.mEmptyPss = 0;
8627 stats.mEmptyCount = 0;
8628 stats.mBackgroundPss = 0;
8629 stats.mBackgroundCount = 0;
8630 stats.mServicePss = 0;
8631 stats.mServiceCount = 0;
8632 stats.mVisiblePss = 0;
8633 stats.mVisibleCount = 0;
8634 stats.mForegroundPss = 0;
8635 stats.mForegroundCount = 0;
8636 stats.mNoPssCount = 0;
8637 synchronized (this) {
8638 int i;
8639 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8640 ? mProcDeaths.length : stats.mProcDeaths.length;
8641 int aggr = 0;
8642 for (i=0; i<NPD; i++) {
8643 aggr += mProcDeaths[i];
8644 stats.mProcDeaths[i] = aggr;
8645 }
8646 while (i<stats.mProcDeaths.length) {
8647 stats.mProcDeaths[i] = 0;
8648 i++;
8649 }
8650
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008651 for (i=mLruProcesses.size()-1; i>=0; i--) {
8652 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653 if (proc.persistent) {
8654 continue;
8655 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008656 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008657 if (proc.lastPss == 0) {
8658 stats.mNoPssCount++;
8659 continue;
8660 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008661 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8662 if (proc.empty) {
8663 stats.mEmptyPss += proc.lastPss;
8664 stats.mEmptyCount++;
8665 } else {
8666 stats.mBackgroundPss += proc.lastPss;
8667 stats.mBackgroundCount++;
8668 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8670 stats.mVisiblePss += proc.lastPss;
8671 stats.mVisibleCount++;
8672 } else {
8673 stats.mForegroundPss += proc.lastPss;
8674 stats.mForegroundCount++;
8675 }
8676 }
8677 }
8678 }
8679
8680 public final void startRunning(String pkg, String cls, String action,
8681 String data) {
8682 synchronized(this) {
8683 if (mStartRunning) {
8684 return;
8685 }
8686 mStartRunning = true;
8687 mTopComponent = pkg != null && cls != null
8688 ? new ComponentName(pkg, cls) : null;
8689 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8690 mTopData = data;
8691 if (!mSystemReady) {
8692 return;
8693 }
8694 }
8695
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008696 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008697 }
8698
8699 private void retrieveSettings() {
8700 final ContentResolver resolver = mContext.getContentResolver();
8701 String debugApp = Settings.System.getString(
8702 resolver, Settings.System.DEBUG_APP);
8703 boolean waitForDebugger = Settings.System.getInt(
8704 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8705 boolean alwaysFinishActivities = Settings.System.getInt(
8706 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8707
8708 Configuration configuration = new Configuration();
8709 Settings.System.getConfiguration(resolver, configuration);
8710
8711 synchronized (this) {
8712 mDebugApp = mOrigDebugApp = debugApp;
8713 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8714 mAlwaysFinishActivities = alwaysFinishActivities;
8715 // This happens before any activities are started, so we can
8716 // change mConfiguration in-place.
8717 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008718 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008719 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008720 }
8721 }
8722
8723 public boolean testIsSystemReady() {
8724 // no need to synchronize(this) just to read & return the value
8725 return mSystemReady;
8726 }
8727
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008728 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008729 // In the simulator, startRunning will never have been called, which
8730 // normally sets a few crucial variables. Do it here instead.
8731 if (!Process.supportsProcesses()) {
8732 mStartRunning = true;
8733 mTopAction = Intent.ACTION_MAIN;
8734 }
8735
8736 synchronized(this) {
8737 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008738 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008739 return;
8740 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008741
8742 // Check to see if there are any update receivers to run.
8743 if (!mDidUpdate) {
8744 if (mWaitingUpdate) {
8745 return;
8746 }
8747 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8748 List<ResolveInfo> ris = null;
8749 try {
8750 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8751 intent, null, 0);
8752 } catch (RemoteException e) {
8753 }
8754 if (ris != null) {
8755 for (int i=ris.size()-1; i>=0; i--) {
8756 if ((ris.get(i).activityInfo.applicationInfo.flags
8757 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8758 ris.remove(i);
8759 }
8760 }
8761 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8762 for (int i=0; i<ris.size(); i++) {
8763 ActivityInfo ai = ris.get(i).activityInfo;
8764 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8765 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008766 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008767 finisher = new IIntentReceiver.Stub() {
8768 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008769 String data, Bundle extras, boolean ordered,
8770 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008771 throws RemoteException {
8772 synchronized (ActivityManagerService.this) {
8773 mDidUpdate = true;
8774 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008775 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008776 }
8777 };
8778 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008779 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008780 broadcastIntentLocked(null, null, intent, null, finisher,
8781 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008782 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008783 mWaitingUpdate = true;
8784 }
8785 }
8786 }
8787 if (mWaitingUpdate) {
8788 return;
8789 }
8790 mDidUpdate = true;
8791 }
8792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008793 mSystemReady = true;
8794 if (!mStartRunning) {
8795 return;
8796 }
8797 }
8798
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008799 ArrayList<ProcessRecord> procsToKill = null;
8800 synchronized(mPidsSelfLocked) {
8801 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8802 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8803 if (!isAllowedWhileBooting(proc.info)){
8804 if (procsToKill == null) {
8805 procsToKill = new ArrayList<ProcessRecord>();
8806 }
8807 procsToKill.add(proc);
8808 }
8809 }
8810 }
8811
8812 if (procsToKill != null) {
8813 synchronized(this) {
8814 for (int i=procsToKill.size()-1; i>=0; i--) {
8815 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008816 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008817 removeProcessLocked(proc, true);
8818 }
8819 }
8820 }
8821
Joe Onorato8a9b2202010-02-26 18:56:32 -08008822 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008823 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008824 SystemClock.uptimeMillis());
8825
8826 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008827 // Make sure we have no pre-ready processes sitting around.
8828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008829 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8830 ResolveInfo ri = mContext.getPackageManager()
8831 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008832 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008833 CharSequence errorMsg = null;
8834 if (ri != null) {
8835 ActivityInfo ai = ri.activityInfo;
8836 ApplicationInfo app = ai.applicationInfo;
8837 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8838 mTopAction = Intent.ACTION_FACTORY_TEST;
8839 mTopData = null;
8840 mTopComponent = new ComponentName(app.packageName,
8841 ai.name);
8842 } else {
8843 errorMsg = mContext.getResources().getText(
8844 com.android.internal.R.string.factorytest_not_system);
8845 }
8846 } else {
8847 errorMsg = mContext.getResources().getText(
8848 com.android.internal.R.string.factorytest_no_action);
8849 }
8850 if (errorMsg != null) {
8851 mTopAction = null;
8852 mTopData = null;
8853 mTopComponent = null;
8854 Message msg = Message.obtain();
8855 msg.what = SHOW_FACTORY_ERROR_MSG;
8856 msg.getData().putCharSequence("msg", errorMsg);
8857 mHandler.sendMessage(msg);
8858 }
8859 }
8860 }
8861
8862 retrieveSettings();
8863
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008864 if (goingCallback != null) goingCallback.run();
8865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008866 synchronized (this) {
8867 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8868 try {
8869 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008870 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008871 if (apps != null) {
8872 int N = apps.size();
8873 int i;
8874 for (i=0; i<N; i++) {
8875 ApplicationInfo info
8876 = (ApplicationInfo)apps.get(i);
8877 if (info != null &&
8878 !info.packageName.equals("android")) {
8879 addAppLocked(info);
8880 }
8881 }
8882 }
8883 } catch (RemoteException ex) {
8884 // pm is in same process, this will never happen.
8885 }
8886 }
8887
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008888 // Start up initial activity.
8889 mBooting = true;
8890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008891 try {
8892 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8893 Message msg = Message.obtain();
8894 msg.what = SHOW_UID_ERROR_MSG;
8895 mHandler.sendMessage(msg);
8896 }
8897 } catch (RemoteException e) {
8898 }
8899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008900 resumeTopActivityLocked(null);
8901 }
8902 }
8903
Dan Egnorb7f03672009-12-09 16:22:32 -08008904 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008905 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008906 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008907 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008908 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008909 startAppProblemLocked(app);
8910 app.stopFreezingAllLocked();
8911 return handleAppCrashLocked(app);
8912 }
8913
Dan Egnorb7f03672009-12-09 16:22:32 -08008914 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008915 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008916 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008917 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008918 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8919 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008920 startAppProblemLocked(app);
8921 app.stopFreezingAllLocked();
8922 }
8923
8924 /**
8925 * Generate a process error record, suitable for attachment to a ProcessRecord.
8926 *
8927 * @param app The ProcessRecord in which the error occurred.
8928 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8929 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008930 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008931 * @param shortMsg Short message describing the crash.
8932 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008933 * @param stackTrace Full crash stack trace, may be null.
8934 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008935 * @return Returns a fully-formed AppErrorStateInfo record.
8936 */
8937 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008938 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008939 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008941 report.condition = condition;
8942 report.processName = app.processName;
8943 report.pid = app.pid;
8944 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008945 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008946 report.shortMsg = shortMsg;
8947 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008948 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008949
8950 return report;
8951 }
8952
Dan Egnor42471dd2010-01-07 17:25:22 -08008953 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008954 synchronized (this) {
8955 app.crashing = false;
8956 app.crashingReport = null;
8957 app.notResponding = false;
8958 app.notRespondingReport = null;
8959 if (app.anrDialog == fromDialog) {
8960 app.anrDialog = null;
8961 }
8962 if (app.waitDialog == fromDialog) {
8963 app.waitDialog = null;
8964 }
8965 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008966 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07008967 Slog.i(ActivityManagerService.TAG, "Killing "
8968 + app.processName + " (pid=" + app.pid + "): user's request");
8969 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
8970 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008971 Process.killProcess(app.pid);
8972 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 }
8974 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008975
Dan Egnorb7f03672009-12-09 16:22:32 -08008976 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008977 long now = SystemClock.uptimeMillis();
8978
8979 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8980 app.info.uid);
8981 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8982 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008983 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008985 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008986 app.info.processName, app.info.uid);
8987 killServicesLocked(app, false);
8988 for (int i=mHistory.size()-1; i>=0; i--) {
8989 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8990 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008991 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008992 + r.intent.getComponent().flattenToShortString());
8993 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8994 }
8995 }
8996 if (!app.persistent) {
8997 // We don't want to start this process again until the user
8998 // explicitly does so... but for persistent process, we really
8999 // need to keep it running. If a persistent process is actually
9000 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08009001 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009002 app.info.processName);
9003 mBadProcesses.put(app.info.processName, app.info.uid, now);
9004 app.bad = true;
9005 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
9006 app.removed = true;
9007 removeProcessLocked(app, false);
9008 return false;
9009 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009010 } else {
9011 HistoryRecord r = topRunningActivityLocked(null);
9012 if (r.app == app) {
9013 // If the top running activity is from this crashing
9014 // process, then terminate it to avoid getting in a loop.
9015 Slog.w(TAG, " Force finishing activity "
9016 + r.intent.getComponent().flattenToShortString());
9017 int index = indexOfTokenLocked(r);
9018 finishActivityLocked(r, index,
9019 Activity.RESULT_CANCELED, null, "crashed");
9020 // Also terminate an activities below it that aren't yet
9021 // stopped, to avoid a situation where one will get
9022 // re-start our crashing activity once it gets resumed again.
9023 index--;
9024 if (index >= 0) {
9025 r = (HistoryRecord)mHistory.get(index);
9026 if (r.state == ActivityState.RESUMED
9027 || r.state == ActivityState.PAUSING
9028 || r.state == ActivityState.PAUSED) {
9029 if (!r.isHomeActivity) {
9030 Slog.w(TAG, " Force finishing activity "
9031 + r.intent.getComponent().flattenToShortString());
9032 finishActivityLocked(r, index,
9033 Activity.RESULT_CANCELED, null, "crashed");
9034 }
9035 }
9036 }
9037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009038 }
9039
9040 // Bump up the crash count of any services currently running in the proc.
9041 if (app.services.size() != 0) {
9042 // Any services running in the application need to be placed
9043 // back in the pending list.
9044 Iterator it = app.services.iterator();
9045 while (it.hasNext()) {
9046 ServiceRecord sr = (ServiceRecord)it.next();
9047 sr.crashCount++;
9048 }
9049 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02009050
9051 // If the crashing process is what we consider to be the "home process" and it has been
9052 // replaced by a third-party app, clear the package preferred activities from packages
9053 // with a home activity running in the process to prevent a repeatedly crashing app
9054 // from blocking the user to manually clear the list.
9055 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
9056 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
9057 Iterator it = mHomeProcess.activities.iterator();
9058 while (it.hasNext()) {
9059 HistoryRecord r = (HistoryRecord)it.next();
9060 if (r.isHomeActivity) {
9061 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
9062 try {
9063 ActivityThread.getPackageManager()
9064 .clearPackagePreferredActivities(r.packageName);
9065 } catch (RemoteException c) {
9066 // pm is in same process, this will never happen.
9067 }
9068 }
9069 }
9070 }
9071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009072 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9073 return true;
9074 }
9075
9076 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009077 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9078 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009079 skipCurrentReceiverLocked(app);
9080 }
9081
9082 void skipCurrentReceiverLocked(ProcessRecord app) {
9083 boolean reschedule = false;
9084 BroadcastRecord r = app.curReceiver;
9085 if (r != null) {
9086 // The current broadcast is waiting for this app's receiver
9087 // to be finished. Looks like that's not going to happen, so
9088 // let the broadcast continue.
9089 logBroadcastReceiverDiscard(r);
9090 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9091 r.resultExtras, r.resultAbort, true);
9092 reschedule = true;
9093 }
9094 r = mPendingBroadcast;
9095 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009096 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009097 "skip & discard pending app " + r);
9098 logBroadcastReceiverDiscard(r);
9099 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9100 r.resultExtras, r.resultAbort, true);
9101 reschedule = true;
9102 }
9103 if (reschedule) {
9104 scheduleBroadcastsLocked();
9105 }
9106 }
9107
Dan Egnor60d87622009-12-16 16:32:58 -08009108 /**
9109 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9110 * The application process will exit immediately after this call returns.
9111 * @param app object of the crashing app, null for the system server
9112 * @param crashInfo describing the exception
9113 */
9114 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9115 ProcessRecord r = findAppProcess(app);
9116
9117 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9118 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009119 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009120 crashInfo.exceptionClassName,
9121 crashInfo.exceptionMessage,
9122 crashInfo.throwFileName,
9123 crashInfo.throwLineNumber);
9124
Dan Egnor42471dd2010-01-07 17:25:22 -08009125 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009126
9127 crashApplication(r, crashInfo);
9128 }
9129
9130 /**
9131 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9132 * @param app object of the crashing app, null for the system server
9133 * @param tag reported by the caller
9134 * @param crashInfo describing the context of the error
9135 * @return true if the process should exit immediately (WTF is fatal)
9136 */
9137 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009138 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009139 ProcessRecord r = findAppProcess(app);
9140
9141 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9142 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009143 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009144 tag, crashInfo.exceptionMessage);
9145
Dan Egnor42471dd2010-01-07 17:25:22 -08009146 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009147
Doug Zongker43866e02010-01-07 12:09:54 -08009148 if (Settings.Secure.getInt(mContext.getContentResolver(),
9149 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009150 crashApplication(r, crashInfo);
9151 return true;
9152 } else {
9153 return false;
9154 }
9155 }
9156
9157 /**
9158 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9159 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9160 */
9161 private ProcessRecord findAppProcess(IBinder app) {
9162 if (app == null) {
9163 return null;
9164 }
9165
9166 synchronized (this) {
9167 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9168 final int NA = apps.size();
9169 for (int ia=0; ia<NA; ia++) {
9170 ProcessRecord p = apps.valueAt(ia);
9171 if (p.thread != null && p.thread.asBinder() == app) {
9172 return p;
9173 }
9174 }
9175 }
9176
Joe Onorato8a9b2202010-02-26 18:56:32 -08009177 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009178 return null;
9179 }
9180 }
9181
9182 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009183 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009184 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009185 * @param process which caused the error, null means the system server
9186 * @param activity which triggered the error, null if unknown
9187 * @param parent activity related to the error, null if unknown
9188 * @param subject line related to the error, null if absent
9189 * @param report in long form describing the error, null if absent
9190 * @param logFile to include in the report, null if none
9191 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009192 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009193 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009194 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9195 final String report, final File logFile,
9196 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009197 // NOTE -- this must never acquire the ActivityManagerService lock,
9198 // otherwise the watchdog may be prevented from resetting the system.
9199
Dan Egnora455d192010-03-12 08:52:28 -08009200 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009201 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009202 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009203 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009204 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009205 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009206 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009207 }
9208
Dan Egnora455d192010-03-12 08:52:28 -08009209 final String dropboxTag = prefix + eventType;
9210 final DropBoxManager dbox = (DropBoxManager)
9211 mContext.getSystemService(Context.DROPBOX_SERVICE);
9212
9213 // Exit early if the dropbox isn't configured to accept this report type.
9214 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9215
9216 final StringBuilder sb = new StringBuilder(1024);
9217 if (process == null || process.pid == MY_PID) {
9218 sb.append("Process: system_server\n");
9219 } else {
9220 sb.append("Process: ").append(process.processName).append("\n");
9221 }
9222 if (process != null) {
9223 int flags = process.info.flags;
9224 IPackageManager pm = ActivityThread.getPackageManager();
9225 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9226 for (String pkg : process.pkgList) {
9227 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009228 try {
Dan Egnora455d192010-03-12 08:52:28 -08009229 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9230 if (pi != null) {
9231 sb.append(" v").append(pi.versionCode);
9232 if (pi.versionName != null) {
9233 sb.append(" (").append(pi.versionName).append(")");
9234 }
9235 }
9236 } catch (RemoteException e) {
9237 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009238 }
Dan Egnora455d192010-03-12 08:52:28 -08009239 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009240 }
Dan Egnora455d192010-03-12 08:52:28 -08009241 }
9242 if (activity != null) {
9243 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9244 }
9245 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9246 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9247 }
9248 if (parent != null && parent != activity) {
9249 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9250 }
9251 if (subject != null) {
9252 sb.append("Subject: ").append(subject).append("\n");
9253 }
9254 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02009255 if (Debug.isDebuggerConnected()) {
9256 sb.append("Debugger: Connected\n");
9257 }
Dan Egnora455d192010-03-12 08:52:28 -08009258 sb.append("\n");
9259
9260 // Do the rest in a worker thread to avoid blocking the caller on I/O
9261 // (After this point, we shouldn't access AMS internal data structures.)
9262 Thread worker = new Thread("Error dump: " + dropboxTag) {
9263 @Override
9264 public void run() {
9265 if (report != null) {
9266 sb.append(report);
9267 }
9268 if (logFile != null) {
9269 try {
9270 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9271 } catch (IOException e) {
9272 Slog.e(TAG, "Error reading " + logFile, e);
9273 }
9274 }
9275 if (crashInfo != null && crashInfo.stackTrace != null) {
9276 sb.append(crashInfo.stackTrace);
9277 }
9278
9279 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9280 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9281 if (lines > 0) {
9282 sb.append("\n");
9283
9284 // Merge several logcat streams, and take the last N lines
9285 InputStreamReader input = null;
9286 try {
9287 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9288 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9289 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9290
9291 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9292 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9293 input = new InputStreamReader(logcat.getInputStream());
9294
9295 int num;
9296 char[] buf = new char[8192];
9297 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9298 } catch (IOException e) {
9299 Slog.e(TAG, "Error running logcat", e);
9300 } finally {
9301 if (input != null) try { input.close(); } catch (IOException e) {}
9302 }
9303 }
9304
9305 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009306 }
Dan Egnora455d192010-03-12 08:52:28 -08009307 };
9308
9309 if (process == null || process.pid == MY_PID) {
9310 worker.run(); // We may be about to die -- need to run this synchronously
9311 } else {
9312 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009313 }
9314 }
9315
9316 /**
9317 * Bring up the "unexpected error" dialog box for a crashing app.
9318 * Deal with edge cases (intercepts from instrumented applications,
9319 * ActivityController, error intent receivers, that sort of thing).
9320 * @param r the application crashing
9321 * @param crashInfo describing the failure
9322 */
9323 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009324 long timeMillis = System.currentTimeMillis();
9325 String shortMsg = crashInfo.exceptionClassName;
9326 String longMsg = crashInfo.exceptionMessage;
9327 String stackTrace = crashInfo.stackTrace;
9328 if (shortMsg != null && longMsg != null) {
9329 longMsg = shortMsg + ": " + longMsg;
9330 } else if (shortMsg != null) {
9331 longMsg = shortMsg;
9332 }
9333
Dan Egnor60d87622009-12-16 16:32:58 -08009334 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009335 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009336 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009337 try {
9338 String name = r != null ? r.processName : null;
9339 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009340 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009341 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009342 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009343 + " at watcher's request");
9344 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009345 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009346 }
9347 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009348 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349 }
9350 }
9351
9352 final long origId = Binder.clearCallingIdentity();
9353
9354 // If this process is running instrumentation, finish it.
9355 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009356 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009357 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009358 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9359 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009360 Bundle info = new Bundle();
9361 info.putString("shortMsg", shortMsg);
9362 info.putString("longMsg", longMsg);
9363 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9364 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009365 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009366 }
9367
Dan Egnor60d87622009-12-16 16:32:58 -08009368 // If we can't identify the process or it's already exceeded its crash quota,
9369 // quit right away without showing a crash dialog.
9370 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009371 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009372 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009373 }
9374
9375 Message msg = Message.obtain();
9376 msg.what = SHOW_ERROR_MSG;
9377 HashMap data = new HashMap();
9378 data.put("result", result);
9379 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009380 msg.obj = data;
9381 mHandler.sendMessage(msg);
9382
9383 Binder.restoreCallingIdentity(origId);
9384 }
9385
9386 int res = result.get();
9387
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009388 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009389 synchronized (this) {
9390 if (r != null) {
9391 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9392 SystemClock.uptimeMillis());
9393 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009394 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009395 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009396 }
9397 }
9398
9399 if (appErrorIntent != null) {
9400 try {
9401 mContext.startActivity(appErrorIntent);
9402 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009403 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009406 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009407
9408 Intent createAppErrorIntentLocked(ProcessRecord r,
9409 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9410 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009411 if (report == null) {
9412 return null;
9413 }
9414 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9415 result.setComponent(r.errorReportReceiver);
9416 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9417 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9418 return result;
9419 }
9420
Dan Egnorb7f03672009-12-09 16:22:32 -08009421 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9422 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009423 if (r.errorReportReceiver == null) {
9424 return null;
9425 }
9426
9427 if (!r.crashing && !r.notResponding) {
9428 return null;
9429 }
9430
Dan Egnorb7f03672009-12-09 16:22:32 -08009431 ApplicationErrorReport report = new ApplicationErrorReport();
9432 report.packageName = r.info.packageName;
9433 report.installerPackageName = r.errorReportReceiver.getPackageName();
9434 report.processName = r.processName;
9435 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009436 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009437
Dan Egnorb7f03672009-12-09 16:22:32 -08009438 if (r.crashing) {
9439 report.type = ApplicationErrorReport.TYPE_CRASH;
9440 report.crashInfo = crashInfo;
9441 } else if (r.notResponding) {
9442 report.type = ApplicationErrorReport.TYPE_ANR;
9443 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009444
Dan Egnorb7f03672009-12-09 16:22:32 -08009445 report.anrInfo.activity = r.notRespondingReport.tag;
9446 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9447 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009448 }
9449
Dan Egnorb7f03672009-12-09 16:22:32 -08009450 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009451 }
9452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009453 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9454 // assume our apps are happy - lazy create the list
9455 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9456
9457 synchronized (this) {
9458
9459 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009460 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9461 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009462 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9463 // This one's in trouble, so we'll generate a report for it
9464 // crashes are higher priority (in case there's a crash *and* an anr)
9465 ActivityManager.ProcessErrorStateInfo report = null;
9466 if (app.crashing) {
9467 report = app.crashingReport;
9468 } else if (app.notResponding) {
9469 report = app.notRespondingReport;
9470 }
9471
9472 if (report != null) {
9473 if (errList == null) {
9474 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9475 }
9476 errList.add(report);
9477 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009478 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009479 " crashing = " + app.crashing +
9480 " notResponding = " + app.notResponding);
9481 }
9482 }
9483 }
9484 }
9485
9486 return errList;
9487 }
9488
9489 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9490 // Lazy instantiation of list
9491 List<ActivityManager.RunningAppProcessInfo> runList = null;
9492 synchronized (this) {
9493 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009494 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9495 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009496 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9497 // Generate process state info for running application
9498 ActivityManager.RunningAppProcessInfo currApp =
9499 new ActivityManager.RunningAppProcessInfo(app.processName,
9500 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009501 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009502 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009503 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009504 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9505 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9506 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009507 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9508 } else if (adj >= HOME_APP_ADJ) {
9509 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9510 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009511 } else if (adj >= SECONDARY_SERVER_ADJ) {
9512 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9513 } else if (adj >= VISIBLE_APP_ADJ) {
9514 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9515 } else {
9516 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9517 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009518 currApp.importanceReasonCode = app.adjTypeCode;
9519 if (app.adjSource instanceof ProcessRecord) {
9520 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9521 } else if (app.adjSource instanceof HistoryRecord) {
9522 HistoryRecord r = (HistoryRecord)app.adjSource;
9523 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9524 }
9525 if (app.adjTarget instanceof ComponentName) {
9526 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9527 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009528 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009529 // + " lru=" + currApp.lru);
9530 if (runList == null) {
9531 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9532 }
9533 runList.add(currApp);
9534 }
9535 }
9536 }
9537 return runList;
9538 }
9539
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009540 public List<ApplicationInfo> getRunningExternalApplications() {
9541 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9542 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9543 if (runningApps != null && runningApps.size() > 0) {
9544 Set<String> extList = new HashSet<String>();
9545 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9546 if (app.pkgList != null) {
9547 for (String pkg : app.pkgList) {
9548 extList.add(pkg);
9549 }
9550 }
9551 }
9552 IPackageManager pm = ActivityThread.getPackageManager();
9553 for (String pkg : extList) {
9554 try {
9555 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9556 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9557 retList.add(info);
9558 }
9559 } catch (RemoteException e) {
9560 }
9561 }
9562 }
9563 return retList;
9564 }
9565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009566 @Override
9567 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009568 if (checkCallingPermission(android.Manifest.permission.DUMP)
9569 != PackageManager.PERMISSION_GRANTED) {
9570 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9571 + Binder.getCallingPid()
9572 + ", uid=" + Binder.getCallingUid()
9573 + " without permission "
9574 + android.Manifest.permission.DUMP);
9575 return;
9576 }
9577
9578 boolean dumpAll = false;
9579
9580 int opti = 0;
9581 while (opti < args.length) {
9582 String opt = args[opti];
9583 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9584 break;
9585 }
9586 opti++;
9587 if ("-a".equals(opt)) {
9588 dumpAll = true;
9589 } else if ("-h".equals(opt)) {
9590 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009591 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009592 pw.println(" cmd may be one of:");
9593 pw.println(" activities: activity stack state");
9594 pw.println(" broadcasts: broadcast state");
9595 pw.println(" intents: pending intent state");
9596 pw.println(" processes: process state");
9597 pw.println(" providers: content provider state");
9598 pw.println(" services: service state");
9599 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009600 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009601 } else {
9602 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009603 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009604 }
9605
9606 // Is the caller requesting to dump a particular piece of data?
9607 if (opti < args.length) {
9608 String cmd = args[opti];
9609 opti++;
9610 if ("activities".equals(cmd) || "a".equals(cmd)) {
9611 synchronized (this) {
9612 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009613 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009614 return;
9615 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9616 synchronized (this) {
9617 dumpBroadcastsLocked(fd, pw, args, opti, true);
9618 }
9619 return;
9620 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9621 synchronized (this) {
9622 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9623 }
9624 return;
9625 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9626 synchronized (this) {
9627 dumpProcessesLocked(fd, pw, args, opti, true);
9628 }
9629 return;
9630 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9631 synchronized (this) {
9632 dumpProvidersLocked(fd, pw, args, opti, true);
9633 }
9634 return;
9635 } else if ("service".equals(cmd)) {
9636 dumpService(fd, pw, args, opti, true);
9637 return;
9638 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9639 synchronized (this) {
9640 dumpServicesLocked(fd, pw, args, opti, true);
9641 }
9642 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009644 }
9645
9646 // No piece of data specified, dump everything.
9647 synchronized (this) {
9648 boolean needSep;
9649 if (dumpAll) {
9650 pw.println("Providers in Current Activity Manager State:");
9651 }
9652 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9653 if (needSep) {
9654 pw.println(" ");
9655 }
9656 if (dumpAll) {
9657 pw.println("-------------------------------------------------------------------------------");
9658 pw.println("Broadcasts in Current Activity Manager State:");
9659 }
9660 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9661 if (needSep) {
9662 pw.println(" ");
9663 }
9664 if (dumpAll) {
9665 pw.println("-------------------------------------------------------------------------------");
9666 pw.println("Services in Current Activity Manager State:");
9667 }
9668 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9669 if (needSep) {
9670 pw.println(" ");
9671 }
9672 if (dumpAll) {
9673 pw.println("-------------------------------------------------------------------------------");
9674 pw.println("PendingIntents in Current Activity Manager State:");
9675 }
9676 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9677 if (needSep) {
9678 pw.println(" ");
9679 }
9680 if (dumpAll) {
9681 pw.println("-------------------------------------------------------------------------------");
9682 pw.println("Activities in Current Activity Manager State:");
9683 }
9684 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9685 if (needSep) {
9686 pw.println(" ");
9687 }
9688 if (dumpAll) {
9689 pw.println("-------------------------------------------------------------------------------");
9690 pw.println("Processes in Current Activity Manager State:");
9691 }
9692 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9693 }
9694 }
9695
9696 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9697 int opti, boolean dumpAll, boolean needHeader) {
9698 if (needHeader) {
9699 pw.println(" Activity stack:");
9700 }
9701 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9702 pw.println(" ");
9703 pw.println(" Running activities (most recent first):");
9704 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9705 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009706 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009707 pw.println(" Activities waiting for another to become visible:");
9708 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9709 }
9710 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009711 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009712 pw.println(" Activities waiting to stop:");
9713 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9714 }
9715 if (mFinishingActivities.size() > 0) {
9716 pw.println(" ");
9717 pw.println(" Activities waiting to finish:");
9718 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009720
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009721 pw.println(" ");
9722 pw.println(" mPausingActivity: " + mPausingActivity);
9723 pw.println(" mResumedActivity: " + mResumedActivity);
9724 pw.println(" mFocusedActivity: " + mFocusedActivity);
9725 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009726
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009727 if (dumpAll && mRecentTasks.size() > 0) {
9728 pw.println(" ");
9729 pw.println("Recent tasks in Current Activity Manager State:");
9730
9731 final int N = mRecentTasks.size();
9732 for (int i=0; i<N; i++) {
9733 TaskRecord tr = mRecentTasks.get(i);
9734 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9735 pw.println(tr);
9736 mRecentTasks.get(i).dump(pw, " ");
9737 }
9738 }
9739
9740 pw.println(" ");
9741 pw.println(" mCurTask: " + mCurTask);
9742
9743 return true;
9744 }
9745
9746 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9747 int opti, boolean dumpAll) {
9748 boolean needSep = false;
9749 int numPers = 0;
9750
9751 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009752 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9753 final int NA = procs.size();
9754 for (int ia=0; ia<NA; ia++) {
9755 if (!needSep) {
9756 pw.println(" All known processes:");
9757 needSep = true;
9758 }
9759 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009760 pw.print(r.persistent ? " *PERS*" : " *APP*");
9761 pw.print(" UID "); pw.print(procs.keyAt(ia));
9762 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009763 r.dump(pw, " ");
9764 if (r.persistent) {
9765 numPers++;
9766 }
9767 }
9768 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009769 }
9770
9771 if (mLruProcesses.size() > 0) {
9772 if (needSep) pw.println(" ");
9773 needSep = true;
9774 pw.println(" Running processes (most recent first):");
9775 dumpProcessList(pw, this, mLruProcesses, " ",
9776 "App ", "PERS", true);
9777 needSep = true;
9778 }
9779
9780 synchronized (mPidsSelfLocked) {
9781 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782 if (needSep) pw.println(" ");
9783 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009784 pw.println(" PID mappings:");
9785 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9786 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9787 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 }
9789 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009790 }
9791
9792 if (mForegroundProcesses.size() > 0) {
9793 if (needSep) pw.println(" ");
9794 needSep = true;
9795 pw.println(" Foreground Processes:");
9796 for (int i=0; i<mForegroundProcesses.size(); i++) {
9797 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9798 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009799 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009800 }
9801
9802 if (mPersistentStartingProcesses.size() > 0) {
9803 if (needSep) pw.println(" ");
9804 needSep = true;
9805 pw.println(" Persisent processes that are starting:");
9806 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9807 "Starting Norm", "Restarting PERS", false);
9808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009809
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009810 if (mStartingProcesses.size() > 0) {
9811 if (needSep) pw.println(" ");
9812 needSep = true;
9813 pw.println(" Processes that are starting:");
9814 dumpProcessList(pw, this, mStartingProcesses, " ",
9815 "Starting Norm", "Starting PERS", false);
9816 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009817
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009818 if (mRemovedProcesses.size() > 0) {
9819 if (needSep) pw.println(" ");
9820 needSep = true;
9821 pw.println(" Processes that are being removed:");
9822 dumpProcessList(pw, this, mRemovedProcesses, " ",
9823 "Removed Norm", "Removed PERS", false);
9824 }
9825
9826 if (mProcessesOnHold.size() > 0) {
9827 if (needSep) pw.println(" ");
9828 needSep = true;
9829 pw.println(" Processes that are on old until the system is ready:");
9830 dumpProcessList(pw, this, mProcessesOnHold, " ",
9831 "OnHold Norm", "OnHold PERS", false);
9832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009834 if (mProcessesToGc.size() > 0) {
9835 if (needSep) pw.println(" ");
9836 needSep = true;
9837 pw.println(" Processes that are waiting to GC:");
9838 long now = SystemClock.uptimeMillis();
9839 for (int i=0; i<mProcessesToGc.size(); i++) {
9840 ProcessRecord proc = mProcessesToGc.get(i);
9841 pw.print(" Process "); pw.println(proc);
9842 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9843 pw.print(", last gced=");
9844 pw.print(now-proc.lastRequestedGc);
9845 pw.print(" ms ago, last lowMem=");
9846 pw.print(now-proc.lastLowMemory);
9847 pw.println(" ms ago");
9848
9849 }
9850 }
9851
9852 if (mProcessCrashTimes.getMap().size() > 0) {
9853 if (needSep) pw.println(" ");
9854 needSep = true;
9855 pw.println(" Time since processes crashed:");
9856 long now = SystemClock.uptimeMillis();
9857 for (Map.Entry<String, SparseArray<Long>> procs
9858 : mProcessCrashTimes.getMap().entrySet()) {
9859 SparseArray<Long> uids = procs.getValue();
9860 final int N = uids.size();
9861 for (int i=0; i<N; i++) {
9862 pw.print(" Process "); pw.print(procs.getKey());
9863 pw.print(" uid "); pw.print(uids.keyAt(i));
9864 pw.print(": last crashed ");
9865 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009866 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009867 }
9868 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009869 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009870
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009871 if (mBadProcesses.getMap().size() > 0) {
9872 if (needSep) pw.println(" ");
9873 needSep = true;
9874 pw.println(" Bad processes:");
9875 for (Map.Entry<String, SparseArray<Long>> procs
9876 : mBadProcesses.getMap().entrySet()) {
9877 SparseArray<Long> uids = procs.getValue();
9878 final int N = uids.size();
9879 for (int i=0; i<N; i++) {
9880 pw.print(" Bad process "); pw.print(procs.getKey());
9881 pw.print(" uid "); pw.print(uids.keyAt(i));
9882 pw.print(": crashed at time ");
9883 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 }
9885 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009887
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009888 pw.println(" ");
9889 pw.println(" mHomeProcess: " + mHomeProcess);
9890 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07009891 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009892 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9893 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9894 || mOrigWaitForDebugger) {
9895 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9896 + " mDebugTransient=" + mDebugTransient
9897 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9898 }
9899 if (mAlwaysFinishActivities || mController != null) {
9900 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9901 + " mController=" + mController);
9902 }
9903 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009904 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 pw.println(" mStartRunning=" + mStartRunning
9906 + " mSystemReady=" + mSystemReady
9907 + " mBooting=" + mBooting
9908 + " mBooted=" + mBooted
9909 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009910 pw.println(" mGoingToSleep=" + mGoingToSleep);
9911 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07009912 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009913 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009914
9915 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009916 }
9917
9918 /**
9919 * There are three ways to call this:
9920 * - no service specified: dump all the services
9921 * - a flattened component name that matched an existing service was specified as the
9922 * first arg: dump that one service
9923 * - the first arg isn't the flattened component name of an existing service:
9924 * dump all services whose component contains the first arg as a substring
9925 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009926 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9927 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009928 String[] newArgs;
9929 String componentNameString;
9930 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009931 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009932 componentNameString = null;
9933 newArgs = EMPTY_STRING_ARRAY;
9934 r = null;
9935 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009936 componentNameString = args[opti];
9937 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009938 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9939 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009940 newArgs = new String[args.length - opti];
9941 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009942 }
9943
9944 if (r != null) {
9945 dumpService(fd, pw, r, newArgs);
9946 } else {
9947 for (ServiceRecord r1 : mServices.values()) {
9948 if (componentNameString == null
9949 || r1.name.flattenToString().contains(componentNameString)) {
9950 dumpService(fd, pw, r1, newArgs);
9951 }
9952 }
9953 }
9954 }
9955
9956 /**
9957 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9958 * there is a thread associated with the service.
9959 */
9960 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9961 pw.println(" Service " + r.name.flattenToString());
9962 if (r.app != null && r.app.thread != null) {
9963 try {
9964 // flush anything that is already in the PrintWriter since the thread is going
9965 // to write to the file descriptor directly
9966 pw.flush();
9967 r.app.thread.dumpService(fd, r, args);
9968 pw.print("\n");
9969 } catch (RemoteException e) {
9970 pw.println("got a RemoteException while dumping the service");
9971 }
9972 }
9973 }
9974
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009975 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9976 int opti, boolean dumpAll) {
9977 boolean needSep = false;
9978
9979 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009980 if (mRegisteredReceivers.size() > 0) {
9981 pw.println(" ");
9982 pw.println(" Registered Receivers:");
9983 Iterator it = mRegisteredReceivers.values().iterator();
9984 while (it.hasNext()) {
9985 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009986 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009987 r.dump(pw, " ");
9988 }
9989 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009991 pw.println(" ");
9992 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009993 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009994 needSep = true;
9995 }
9996
9997 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9998 || mPendingBroadcast != null) {
9999 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010001 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010003 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10004 pw.println(" Broadcast #" + i + ":");
10005 mParallelBroadcasts.get(i).dump(pw, " ");
10006 }
10007 if (mOrderedBroadcasts.size() > 0) {
10008 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010009 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010010 }
10011 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10012 pw.println(" Serialized Broadcast #" + i + ":");
10013 mOrderedBroadcasts.get(i).dump(pw, " ");
10014 }
10015 pw.println(" ");
10016 pw.println(" Pending broadcast:");
10017 if (mPendingBroadcast != null) {
10018 mPendingBroadcast.dump(pw, " ");
10019 } else {
10020 pw.println(" (null)");
10021 }
10022 needSep = true;
10023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010024
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010025 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010026 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -080010027 pw.println(" Historical broadcasts:");
10028 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
10029 BroadcastRecord r = mBroadcastHistory[i];
10030 if (r == null) {
10031 break;
10032 }
10033 pw.println(" Historical Broadcast #" + i + ":");
10034 r.dump(pw, " ");
10035 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010036 needSep = true;
10037 }
10038
10039 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010040 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010041 pw.println(" Sticky broadcasts:");
10042 StringBuilder sb = new StringBuilder(128);
10043 for (Map.Entry<String, ArrayList<Intent>> ent
10044 : mStickyBroadcasts.entrySet()) {
10045 pw.print(" * Sticky action "); pw.print(ent.getKey());
10046 pw.println(":");
10047 ArrayList<Intent> intents = ent.getValue();
10048 final int N = intents.size();
10049 for (int i=0; i<N; i++) {
10050 sb.setLength(0);
10051 sb.append(" Intent: ");
10052 intents.get(i).toShortString(sb, true, false);
10053 pw.println(sb.toString());
10054 Bundle bundle = intents.get(i).getExtras();
10055 if (bundle != null) {
10056 pw.print(" ");
10057 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010058 }
10059 }
10060 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010061 needSep = true;
10062 }
10063
10064 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010065 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010066 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010067 pw.println(" mHandler:");
10068 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010069 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010070 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010071
10072 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010073 }
10074
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010075 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10076 int opti, boolean dumpAll) {
10077 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010078
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010079 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010080 if (mServices.size() > 0) {
10081 pw.println(" Active services:");
10082 Iterator<ServiceRecord> it = mServices.values().iterator();
10083 while (it.hasNext()) {
10084 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010085 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010086 r.dump(pw, " ");
10087 }
10088 needSep = true;
10089 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010091
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010092 if (mPendingServices.size() > 0) {
10093 if (needSep) pw.println(" ");
10094 pw.println(" Pending services:");
10095 for (int i=0; i<mPendingServices.size(); i++) {
10096 ServiceRecord r = mPendingServices.get(i);
10097 pw.print(" * Pending "); pw.println(r);
10098 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010100 needSep = true;
10101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010102
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010103 if (mRestartingServices.size() > 0) {
10104 if (needSep) pw.println(" ");
10105 pw.println(" Restarting services:");
10106 for (int i=0; i<mRestartingServices.size(); i++) {
10107 ServiceRecord r = mRestartingServices.get(i);
10108 pw.print(" * Restarting "); pw.println(r);
10109 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010110 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010111 needSep = true;
10112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010113
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010114 if (mStoppingServices.size() > 0) {
10115 if (needSep) pw.println(" ");
10116 pw.println(" Stopping services:");
10117 for (int i=0; i<mStoppingServices.size(); i++) {
10118 ServiceRecord r = mStoppingServices.get(i);
10119 pw.print(" * Stopping "); pw.println(r);
10120 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010121 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010122 needSep = true;
10123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010124
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010125 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010126 if (mServiceConnections.size() > 0) {
10127 if (needSep) pw.println(" ");
10128 pw.println(" Connection bindings to services:");
10129 Iterator<ConnectionRecord> it
10130 = mServiceConnections.values().iterator();
10131 while (it.hasNext()) {
10132 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010133 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010134 r.dump(pw, " ");
10135 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010136 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010137 }
10138 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010139
10140 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010141 }
10142
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010143 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10144 int opti, boolean dumpAll) {
10145 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010146
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010147 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 if (mProvidersByClass.size() > 0) {
10149 if (needSep) pw.println(" ");
10150 pw.println(" Published content providers (by class):");
10151 Iterator it = mProvidersByClass.entrySet().iterator();
10152 while (it.hasNext()) {
10153 Map.Entry e = (Map.Entry)it.next();
10154 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010155 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010156 r.dump(pw, " ");
10157 }
10158 needSep = true;
10159 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010160
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010161 if (mProvidersByName.size() > 0) {
10162 pw.println(" ");
10163 pw.println(" Authority to provider mappings:");
10164 Iterator it = mProvidersByName.entrySet().iterator();
10165 while (it.hasNext()) {
10166 Map.Entry e = (Map.Entry)it.next();
10167 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
10168 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10169 pw.println(r);
10170 }
10171 needSep = true;
10172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010173 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010174
10175 if (mLaunchingProviders.size() > 0) {
10176 if (needSep) pw.println(" ");
10177 pw.println(" Launching content providers:");
10178 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10179 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10180 pw.println(mLaunchingProviders.get(i));
10181 }
10182 needSep = true;
10183 }
10184
10185 if (mGrantedUriPermissions.size() > 0) {
10186 pw.println();
10187 pw.println("Granted Uri Permissions:");
10188 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10189 int uid = mGrantedUriPermissions.keyAt(i);
10190 HashMap<Uri, UriPermission> perms
10191 = mGrantedUriPermissions.valueAt(i);
10192 pw.print(" * UID "); pw.print(uid);
10193 pw.println(" holds:");
10194 for (UriPermission perm : perms.values()) {
10195 pw.print(" "); pw.println(perm);
10196 perm.dump(pw, " ");
10197 }
10198 }
10199 needSep = true;
10200 }
10201
10202 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 }
10204
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010205 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10206 int opti, boolean dumpAll) {
10207 boolean needSep = false;
10208
10209 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010210 if (this.mIntentSenderRecords.size() > 0) {
10211 Iterator<WeakReference<PendingIntentRecord>> it
10212 = mIntentSenderRecords.values().iterator();
10213 while (it.hasNext()) {
10214 WeakReference<PendingIntentRecord> ref = it.next();
10215 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010216 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010217 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010218 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010219 rec.dump(pw, " ");
10220 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010221 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010222 }
10223 }
10224 }
10225 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010226
10227 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010228 }
10229
10230 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010231 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010232 TaskRecord lastTask = null;
10233 for (int i=list.size()-1; i>=0; i--) {
10234 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010235 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 if (lastTask != r.task) {
10237 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010238 pw.print(prefix);
10239 pw.print(full ? "* " : " ");
10240 pw.println(lastTask);
10241 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010242 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010244 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010245 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10246 pw.print(" #"); pw.print(i); pw.print(": ");
10247 pw.println(r);
10248 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010249 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 }
10252 }
10253
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010254 private static String buildOomTag(String prefix, String space, int val, int base) {
10255 if (val == base) {
10256 if (space == null) return prefix;
10257 return prefix + " ";
10258 }
10259 return prefix + "+" + Integer.toString(val-base);
10260 }
10261
10262 private static final int dumpProcessList(PrintWriter pw,
10263 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010264 String prefix, String normalLabel, String persistentLabel,
10265 boolean inclOomAdj) {
10266 int numPers = 0;
10267 for (int i=list.size()-1; i>=0; i--) {
10268 ProcessRecord r = (ProcessRecord)list.get(i);
10269 if (false) {
10270 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10271 + " #" + i + ":");
10272 r.dump(pw, prefix + " ");
10273 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010274 String oomAdj;
10275 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010276 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010277 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010278 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10279 } else if (r.setAdj >= HOME_APP_ADJ) {
10280 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10281 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10282 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10283 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10284 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10285 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10286 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10287 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10288 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010289 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010290 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010291 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010292 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010293 } else {
10294 oomAdj = Integer.toString(r.setAdj);
10295 }
10296 String schedGroup;
10297 switch (r.setSchedGroup) {
10298 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10299 schedGroup = "B";
10300 break;
10301 case Process.THREAD_GROUP_DEFAULT:
10302 schedGroup = "F";
10303 break;
10304 default:
10305 schedGroup = Integer.toString(r.setSchedGroup);
10306 break;
10307 }
10308 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010309 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010310 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010311 if (r.adjSource != null || r.adjTarget != null) {
10312 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010313 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 } else {
10316 pw.println(String.format("%s%s #%2d: %s",
10317 prefix, (r.persistent ? persistentLabel : normalLabel),
10318 i, r.toString()));
10319 }
10320 if (r.persistent) {
10321 numPers++;
10322 }
10323 }
10324 return numPers;
10325 }
10326
Dianne Hackborn472ad872010-04-07 17:31:48 -070010327 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010329 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010330 long uptime = SystemClock.uptimeMillis();
10331 long realtime = SystemClock.elapsedRealtime();
10332
10333 if (isCheckinRequest) {
10334 // short checkin version
10335 pw.println(uptime + "," + realtime);
10336 pw.flush();
10337 } else {
10338 pw.println("Applications Memory Usage (kB):");
10339 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10340 }
10341 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10342 ProcessRecord r = (ProcessRecord)list.get(i);
10343 if (r.thread != null) {
10344 if (!isCheckinRequest) {
10345 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10346 pw.flush();
10347 }
10348 try {
10349 r.thread.asBinder().dump(fd, args);
10350 } catch (RemoteException e) {
10351 if (!isCheckinRequest) {
10352 pw.println("Got RemoteException!");
10353 pw.flush();
10354 }
10355 }
10356 }
10357 }
10358 }
10359
10360 /**
10361 * Searches array of arguments for the specified string
10362 * @param args array of argument strings
10363 * @param value value to search for
10364 * @return true if the value is contained in the array
10365 */
10366 private static boolean scanArgs(String[] args, String value) {
10367 if (args != null) {
10368 for (String arg : args) {
10369 if (value.equals(arg)) {
10370 return true;
10371 }
10372 }
10373 }
10374 return false;
10375 }
10376
Dianne Hackborn75b03852009-06-12 15:43:26 -070010377 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378 int count = mHistory.size();
10379
10380 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010381 int index = -1;
10382 for (int i=count-1; i>=0; i--) {
10383 Object o = mHistory.get(i);
10384 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010385 index = i;
10386 break;
10387 }
10388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010389
10390 return index;
10391 }
10392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010393 private final void killServicesLocked(ProcessRecord app,
10394 boolean allowRestart) {
10395 // Report disconnected services.
10396 if (false) {
10397 // XXX we are letting the client link to the service for
10398 // death notifications.
10399 if (app.services.size() > 0) {
10400 Iterator it = app.services.iterator();
10401 while (it.hasNext()) {
10402 ServiceRecord r = (ServiceRecord)it.next();
10403 if (r.connections.size() > 0) {
10404 Iterator<ConnectionRecord> jt
10405 = r.connections.values().iterator();
10406 while (jt.hasNext()) {
10407 ConnectionRecord c = jt.next();
10408 if (c.binding.client != app) {
10409 try {
10410 //c.conn.connected(r.className, null);
10411 } catch (Exception e) {
10412 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010413 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414 + r.shortName
10415 + " from app " + app.processName, e);
10416 }
10417 }
10418 }
10419 }
10420 }
10421 }
10422 }
10423
10424 // Clean up any connections this application has to other services.
10425 if (app.connections.size() > 0) {
10426 Iterator<ConnectionRecord> it = app.connections.iterator();
10427 while (it.hasNext()) {
10428 ConnectionRecord r = it.next();
10429 removeConnectionLocked(r, app, null);
10430 }
10431 }
10432 app.connections.clear();
10433
10434 if (app.services.size() != 0) {
10435 // Any services running in the application need to be placed
10436 // back in the pending list.
10437 Iterator it = app.services.iterator();
10438 while (it.hasNext()) {
10439 ServiceRecord sr = (ServiceRecord)it.next();
10440 synchronized (sr.stats.getBatteryStats()) {
10441 sr.stats.stopLaunchedLocked();
10442 }
10443 sr.app = null;
10444 sr.executeNesting = 0;
10445 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010446
10447 boolean hasClients = sr.bindings.size() > 0;
10448 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010449 Iterator<IntentBindRecord> bindings
10450 = sr.bindings.values().iterator();
10451 while (bindings.hasNext()) {
10452 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010453 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010454 + ": shouldUnbind=" + b.hasBound);
10455 b.binder = null;
10456 b.requested = b.received = b.hasBound = false;
10457 }
10458 }
10459
10460 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010461 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010462 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010463 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010464 sr.crashCount, sr.shortName, app.pid);
10465 bringDownServiceLocked(sr, true);
10466 } else if (!allowRestart) {
10467 bringDownServiceLocked(sr, true);
10468 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010469 boolean canceled = scheduleServiceRestartLocked(sr, true);
10470
10471 // Should the service remain running? Note that in the
10472 // extreme case of so many attempts to deliver a command
10473 // that it failed, that we also will stop it here.
10474 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10475 if (sr.pendingStarts.size() == 0) {
10476 sr.startRequested = false;
10477 if (!hasClients) {
10478 // Whoops, no reason to restart!
10479 bringDownServiceLocked(sr, true);
10480 }
10481 }
10482 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010483 }
10484 }
10485
10486 if (!allowRestart) {
10487 app.services.clear();
10488 }
10489 }
10490
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010491 // Make sure we have no more records on the stopping list.
10492 int i = mStoppingServices.size();
10493 while (i > 0) {
10494 i--;
10495 ServiceRecord sr = mStoppingServices.get(i);
10496 if (sr.app == app) {
10497 mStoppingServices.remove(i);
10498 }
10499 }
10500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010501 app.executingServices.clear();
10502 }
10503
10504 private final void removeDyingProviderLocked(ProcessRecord proc,
10505 ContentProviderRecord cpr) {
10506 synchronized (cpr) {
10507 cpr.launchingApp = null;
10508 cpr.notifyAll();
10509 }
10510
10511 mProvidersByClass.remove(cpr.info.name);
10512 String names[] = cpr.info.authority.split(";");
10513 for (int j = 0; j < names.length; j++) {
10514 mProvidersByName.remove(names[j]);
10515 }
10516
10517 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10518 while (cit.hasNext()) {
10519 ProcessRecord capp = cit.next();
10520 if (!capp.persistent && capp.thread != null
10521 && capp.pid != 0
10522 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010523 Slog.i(TAG, "Kill " + capp.processName
10524 + " (pid " + capp.pid + "): provider " + cpr.info.name
10525 + " in dying process " + proc.processName);
10526 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10527 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 Process.killProcess(capp.pid);
10529 }
10530 }
10531
10532 mLaunchingProviders.remove(cpr);
10533 }
10534
10535 /**
10536 * Main code for cleaning up a process when it has gone away. This is
10537 * called both as a result of the process dying, or directly when stopping
10538 * a process when running in single process mode.
10539 */
10540 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10541 boolean restarting, int index) {
10542 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010543 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010544 }
10545
Dianne Hackborn36124872009-10-08 16:22:03 -070010546 mProcessesToGc.remove(app);
10547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 // Dismiss any open dialogs.
10549 if (app.crashDialog != null) {
10550 app.crashDialog.dismiss();
10551 app.crashDialog = null;
10552 }
10553 if (app.anrDialog != null) {
10554 app.anrDialog.dismiss();
10555 app.anrDialog = null;
10556 }
10557 if (app.waitDialog != null) {
10558 app.waitDialog.dismiss();
10559 app.waitDialog = null;
10560 }
10561
10562 app.crashing = false;
10563 app.notResponding = false;
10564
10565 app.resetPackageList();
10566 app.thread = null;
10567 app.forcingToForeground = null;
10568 app.foregroundServices = false;
10569
10570 killServicesLocked(app, true);
10571
10572 boolean restart = false;
10573
10574 int NL = mLaunchingProviders.size();
10575
10576 // Remove published content providers.
10577 if (!app.pubProviders.isEmpty()) {
10578 Iterator it = app.pubProviders.values().iterator();
10579 while (it.hasNext()) {
10580 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10581 cpr.provider = null;
10582 cpr.app = null;
10583
10584 // See if someone is waiting for this provider... in which
10585 // case we don't remove it, but just let it restart.
10586 int i = 0;
10587 if (!app.bad) {
10588 for (; i<NL; i++) {
10589 if (mLaunchingProviders.get(i) == cpr) {
10590 restart = true;
10591 break;
10592 }
10593 }
10594 } else {
10595 i = NL;
10596 }
10597
10598 if (i >= NL) {
10599 removeDyingProviderLocked(app, cpr);
10600 NL = mLaunchingProviders.size();
10601 }
10602 }
10603 app.pubProviders.clear();
10604 }
10605
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010606 // Take care of any launching providers waiting for this process.
10607 if (checkAppInLaunchingProvidersLocked(app, false)) {
10608 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010609 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 // Unregister from connected content providers.
10612 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010613 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 while (it.hasNext()) {
10615 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10616 cpr.clients.remove(app);
10617 }
10618 app.conProviders.clear();
10619 }
10620
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010621 // At this point there may be remaining entries in mLaunchingProviders
10622 // where we were the only one waiting, so they are no longer of use.
10623 // Look for these and clean up if found.
10624 // XXX Commented out for now. Trying to figure out a way to reproduce
10625 // the actual situation to identify what is actually going on.
10626 if (false) {
10627 for (int i=0; i<NL; i++) {
10628 ContentProviderRecord cpr = (ContentProviderRecord)
10629 mLaunchingProviders.get(i);
10630 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10631 synchronized (cpr) {
10632 cpr.launchingApp = null;
10633 cpr.notifyAll();
10634 }
10635 }
10636 }
10637 }
10638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010639 skipCurrentReceiverLocked(app);
10640
10641 // Unregister any receivers.
10642 if (app.receivers.size() > 0) {
10643 Iterator<ReceiverList> it = app.receivers.iterator();
10644 while (it.hasNext()) {
10645 removeReceiverLocked(it.next());
10646 }
10647 app.receivers.clear();
10648 }
10649
Christopher Tate181fafa2009-05-14 11:12:14 -070010650 // If the app is undergoing backup, tell the backup manager about it
10651 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010652 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010653 try {
10654 IBackupManager bm = IBackupManager.Stub.asInterface(
10655 ServiceManager.getService(Context.BACKUP_SERVICE));
10656 bm.agentDisconnected(app.info.packageName);
10657 } catch (RemoteException e) {
10658 // can't happen; backup manager is local
10659 }
10660 }
10661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010662 // If the caller is restarting this app, then leave it in its
10663 // current lists and let the caller take care of it.
10664 if (restarting) {
10665 return;
10666 }
10667
10668 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010669 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010670 "Removing non-persistent process during cleanup: " + app);
10671 mProcessNames.remove(app.processName, app.info.uid);
10672 } else if (!app.removed) {
10673 // This app is persistent, so we need to keep its record around.
10674 // If it is not already on the pending app list, add it there
10675 // and start a new process for it.
10676 app.thread = null;
10677 app.forcingToForeground = null;
10678 app.foregroundServices = false;
10679 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10680 mPersistentStartingProcesses.add(app);
10681 restart = true;
10682 }
10683 }
10684 mProcessesOnHold.remove(app);
10685
The Android Open Source Project4df24232009-03-05 14:34:35 -080010686 if (app == mHomeProcess) {
10687 mHomeProcess = null;
10688 }
10689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010690 if (restart) {
10691 // We have components that still need to be running in the
10692 // process, so re-launch it.
10693 mProcessNames.put(app.processName, app.info.uid, app);
10694 startProcessLocked(app, "restart", app.processName);
10695 } else if (app.pid > 0 && app.pid != MY_PID) {
10696 // Goodbye!
10697 synchronized (mPidsSelfLocked) {
10698 mPidsSelfLocked.remove(app.pid);
10699 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10700 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010701 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010702 }
10703 }
10704
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010705 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10706 // Look through the content providers we are waiting to have launched,
10707 // and if any run in this process then either schedule a restart of
10708 // the process or kill the client waiting for it if this process has
10709 // gone bad.
10710 int NL = mLaunchingProviders.size();
10711 boolean restart = false;
10712 for (int i=0; i<NL; i++) {
10713 ContentProviderRecord cpr = (ContentProviderRecord)
10714 mLaunchingProviders.get(i);
10715 if (cpr.launchingApp == app) {
10716 if (!alwaysBad && !app.bad) {
10717 restart = true;
10718 } else {
10719 removeDyingProviderLocked(app, cpr);
10720 NL = mLaunchingProviders.size();
10721 }
10722 }
10723 }
10724 return restart;
10725 }
10726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010727 // =========================================================
10728 // SERVICES
10729 // =========================================================
10730
10731 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10732 ActivityManager.RunningServiceInfo info =
10733 new ActivityManager.RunningServiceInfo();
10734 info.service = r.name;
10735 if (r.app != null) {
10736 info.pid = r.app.pid;
10737 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010738 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010739 info.process = r.processName;
10740 info.foreground = r.isForeground;
10741 info.activeSince = r.createTime;
10742 info.started = r.startRequested;
10743 info.clientCount = r.connections.size();
10744 info.crashCount = r.crashCount;
10745 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010746 if (r.isForeground) {
10747 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10748 }
10749 if (r.startRequested) {
10750 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10751 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010752 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010753 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10754 }
10755 if (r.app != null && r.app.persistent) {
10756 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10757 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010758 for (ConnectionRecord conn : r.connections.values()) {
10759 if (conn.clientLabel != 0) {
10760 info.clientPackage = conn.binding.client.info.packageName;
10761 info.clientLabel = conn.clientLabel;
10762 break;
10763 }
10764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 return info;
10766 }
10767
10768 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10769 int flags) {
10770 synchronized (this) {
10771 ArrayList<ActivityManager.RunningServiceInfo> res
10772 = new ArrayList<ActivityManager.RunningServiceInfo>();
10773
10774 if (mServices.size() > 0) {
10775 Iterator<ServiceRecord> it = mServices.values().iterator();
10776 while (it.hasNext() && res.size() < maxNum) {
10777 res.add(makeRunningServiceInfoLocked(it.next()));
10778 }
10779 }
10780
10781 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10782 ServiceRecord r = mRestartingServices.get(i);
10783 ActivityManager.RunningServiceInfo info =
10784 makeRunningServiceInfoLocked(r);
10785 info.restarting = r.nextRestartTime;
10786 res.add(info);
10787 }
10788
10789 return res;
10790 }
10791 }
10792
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010793 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10794 synchronized (this) {
10795 ServiceRecord r = mServices.get(name);
10796 if (r != null) {
10797 for (ConnectionRecord conn : r.connections.values()) {
10798 if (conn.clientIntent != null) {
10799 return conn.clientIntent;
10800 }
10801 }
10802 }
10803 }
10804 return null;
10805 }
10806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010807 private final ServiceRecord findServiceLocked(ComponentName name,
10808 IBinder token) {
10809 ServiceRecord r = mServices.get(name);
10810 return r == token ? r : null;
10811 }
10812
10813 private final class ServiceLookupResult {
10814 final ServiceRecord record;
10815 final String permission;
10816
10817 ServiceLookupResult(ServiceRecord _record, String _permission) {
10818 record = _record;
10819 permission = _permission;
10820 }
10821 };
10822
10823 private ServiceLookupResult findServiceLocked(Intent service,
10824 String resolvedType) {
10825 ServiceRecord r = null;
10826 if (service.getComponent() != null) {
10827 r = mServices.get(service.getComponent());
10828 }
10829 if (r == null) {
10830 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10831 r = mServicesByIntent.get(filter);
10832 }
10833
10834 if (r == null) {
10835 try {
10836 ResolveInfo rInfo =
10837 ActivityThread.getPackageManager().resolveService(
10838 service, resolvedType, 0);
10839 ServiceInfo sInfo =
10840 rInfo != null ? rInfo.serviceInfo : null;
10841 if (sInfo == null) {
10842 return null;
10843 }
10844
10845 ComponentName name = new ComponentName(
10846 sInfo.applicationInfo.packageName, sInfo.name);
10847 r = mServices.get(name);
10848 } catch (RemoteException ex) {
10849 // pm is in same process, this will never happen.
10850 }
10851 }
10852 if (r != null) {
10853 int callingPid = Binder.getCallingPid();
10854 int callingUid = Binder.getCallingUid();
10855 if (checkComponentPermission(r.permission,
10856 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10857 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010858 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 + " from pid=" + callingPid
10860 + ", uid=" + callingUid
10861 + " requires " + r.permission);
10862 return new ServiceLookupResult(null, r.permission);
10863 }
10864 return new ServiceLookupResult(r, null);
10865 }
10866 return null;
10867 }
10868
10869 private class ServiceRestarter implements Runnable {
10870 private ServiceRecord mService;
10871
10872 void setService(ServiceRecord service) {
10873 mService = service;
10874 }
10875
10876 public void run() {
10877 synchronized(ActivityManagerService.this) {
10878 performServiceRestartLocked(mService);
10879 }
10880 }
10881 }
10882
10883 private ServiceLookupResult retrieveServiceLocked(Intent service,
10884 String resolvedType, int callingPid, int callingUid) {
10885 ServiceRecord r = null;
10886 if (service.getComponent() != null) {
10887 r = mServices.get(service.getComponent());
10888 }
10889 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10890 r = mServicesByIntent.get(filter);
10891 if (r == null) {
10892 try {
10893 ResolveInfo rInfo =
10894 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010895 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010896 ServiceInfo sInfo =
10897 rInfo != null ? rInfo.serviceInfo : null;
10898 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010899 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010900 ": not found");
10901 return null;
10902 }
10903
10904 ComponentName name = new ComponentName(
10905 sInfo.applicationInfo.packageName, sInfo.name);
10906 r = mServices.get(name);
10907 if (r == null) {
10908 filter = new Intent.FilterComparison(service.cloneFilter());
10909 ServiceRestarter res = new ServiceRestarter();
10910 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10911 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10912 synchronized (stats) {
10913 ss = stats.getServiceStatsLocked(
10914 sInfo.applicationInfo.uid, sInfo.packageName,
10915 sInfo.name);
10916 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010917 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010918 res.setService(r);
10919 mServices.put(name, r);
10920 mServicesByIntent.put(filter, r);
10921
10922 // Make sure this component isn't in the pending list.
10923 int N = mPendingServices.size();
10924 for (int i=0; i<N; i++) {
10925 ServiceRecord pr = mPendingServices.get(i);
10926 if (pr.name.equals(name)) {
10927 mPendingServices.remove(i);
10928 i--;
10929 N--;
10930 }
10931 }
10932 }
10933 } catch (RemoteException ex) {
10934 // pm is in same process, this will never happen.
10935 }
10936 }
10937 if (r != null) {
10938 if (checkComponentPermission(r.permission,
10939 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10940 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010941 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010942 + " from pid=" + Binder.getCallingPid()
10943 + ", uid=" + Binder.getCallingUid()
10944 + " requires " + r.permission);
10945 return new ServiceLookupResult(null, r.permission);
10946 }
10947 return new ServiceLookupResult(r, null);
10948 }
10949 return null;
10950 }
10951
10952 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10953 long now = SystemClock.uptimeMillis();
10954 if (r.executeNesting == 0 && r.app != null) {
10955 if (r.app.executingServices.size() == 0) {
10956 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10957 msg.obj = r.app;
10958 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10959 }
10960 r.app.executingServices.add(r);
10961 }
10962 r.executeNesting++;
10963 r.executingStart = now;
10964 }
10965
10966 private final void sendServiceArgsLocked(ServiceRecord r,
10967 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010968 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 if (N == 0) {
10970 return;
10971 }
10972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 int i = 0;
10974 while (i < N) {
10975 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010976 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010977 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010978 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010979 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010980 // If somehow we got a dummy start at the front, then
10981 // just drop it here.
10982 i++;
10983 continue;
10984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 bumpServiceExecutingLocked(r);
10986 if (!oomAdjusted) {
10987 oomAdjusted = true;
10988 updateOomAdjLocked(r.app);
10989 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010990 int flags = 0;
10991 if (si.deliveryCount > 0) {
10992 flags |= Service.START_FLAG_RETRY;
10993 }
10994 if (si.doneExecutingCount > 0) {
10995 flags |= Service.START_FLAG_REDELIVERY;
10996 }
10997 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10998 si.deliveredTime = SystemClock.uptimeMillis();
10999 r.deliveredStarts.add(si);
11000 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011002 } catch (RemoteException e) {
11003 // Remote process gone... we'll let the normal cleanup take
11004 // care of this.
11005 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011006 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011007 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 break;
11009 }
11010 }
11011 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011012 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011013 } else {
11014 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011015 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011016 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017 }
11018 }
11019 }
11020
11021 private final boolean requestServiceBindingLocked(ServiceRecord r,
11022 IntentBindRecord i, boolean rebind) {
11023 if (r.app == null || r.app.thread == null) {
11024 // If service is not currently running, can't yet bind.
11025 return false;
11026 }
11027 if ((!i.requested || rebind) && i.apps.size() > 0) {
11028 try {
11029 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011030 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011031 + ": shouldUnbind=" + i.hasBound);
11032 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11033 if (!rebind) {
11034 i.requested = true;
11035 }
11036 i.hasBound = true;
11037 i.doRebind = false;
11038 } catch (RemoteException e) {
11039 return false;
11040 }
11041 }
11042 return true;
11043 }
11044
11045 private final void requestServiceBindingsLocked(ServiceRecord r) {
11046 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11047 while (bindings.hasNext()) {
11048 IntentBindRecord i = bindings.next();
11049 if (!requestServiceBindingLocked(r, i, false)) {
11050 break;
11051 }
11052 }
11053 }
11054
11055 private final void realStartServiceLocked(ServiceRecord r,
11056 ProcessRecord app) throws RemoteException {
11057 if (app.thread == null) {
11058 throw new RemoteException();
11059 }
11060
11061 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011062 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011063
11064 app.services.add(r);
11065 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011066 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011067
11068 boolean created = false;
11069 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011070 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011071 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011072 mStringBuilder.setLength(0);
11073 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011074 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011075 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011076 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077 synchronized (r.stats.getBatteryStats()) {
11078 r.stats.startLaunchedLocked();
11079 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011080 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011081 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011082 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011083 created = true;
11084 } finally {
11085 if (!created) {
11086 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011087 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011088 }
11089 }
11090
11091 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011092
11093 // If the service is in the started state, and there are no
11094 // pending arguments, then fake up one so its onStartCommand() will
11095 // be called.
11096 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11097 r.lastStartId++;
11098 if (r.lastStartId < 1) {
11099 r.lastStartId = 1;
11100 }
11101 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11102 }
11103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 sendServiceArgsLocked(r, true);
11105 }
11106
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011107 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11108 boolean allowCancel) {
11109 boolean canceled = false;
11110
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011111 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011112 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011113 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011114
11115 // Any delivered but not yet finished starts should be put back
11116 // on the pending list.
11117 final int N = r.deliveredStarts.size();
11118 if (N > 0) {
11119 for (int i=N-1; i>=0; i--) {
11120 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11121 if (si.intent == null) {
11122 // We'll generate this again if needed.
11123 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11124 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11125 r.pendingStarts.add(0, si);
11126 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11127 dur *= 2;
11128 if (minDuration < dur) minDuration = dur;
11129 if (resetTime < dur) resetTime = dur;
11130 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011131 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011132 + r.name);
11133 canceled = true;
11134 }
11135 }
11136 r.deliveredStarts.clear();
11137 }
11138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011139 r.totalRestartCount++;
11140 if (r.restartDelay == 0) {
11141 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011142 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011143 } else {
11144 // If it has been a "reasonably long time" since the service
11145 // was started, then reset our restart duration back to
11146 // the beginning, so we don't infinitely increase the duration
11147 // on a service that just occasionally gets killed (which is
11148 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011149 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011150 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011151 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011153 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011154 if (r.restartDelay < minDuration) {
11155 r.restartDelay = minDuration;
11156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011157 }
11158 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011159
11160 r.nextRestartTime = now + r.restartDelay;
11161
11162 // Make sure that we don't end up restarting a bunch of services
11163 // all at the same time.
11164 boolean repeat;
11165 do {
11166 repeat = false;
11167 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11168 ServiceRecord r2 = mRestartingServices.get(i);
11169 if (r2 != r && r.nextRestartTime
11170 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11171 && r.nextRestartTime
11172 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11173 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11174 r.restartDelay = r.nextRestartTime - now;
11175 repeat = true;
11176 break;
11177 }
11178 }
11179 } while (repeat);
11180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011181 if (!mRestartingServices.contains(r)) {
11182 mRestartingServices.add(r);
11183 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011184
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011185 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011187 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011188 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011190 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011191 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011192 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011193 r.shortName, r.restartDelay);
11194
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011195 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011196 }
11197
11198 final void performServiceRestartLocked(ServiceRecord r) {
11199 if (!mRestartingServices.contains(r)) {
11200 return;
11201 }
11202 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11203 }
11204
11205 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11206 if (r.restartDelay == 0) {
11207 return false;
11208 }
11209 r.resetRestartCounter();
11210 mRestartingServices.remove(r);
11211 mHandler.removeCallbacks(r.restarter);
11212 return true;
11213 }
11214
11215 private final boolean bringUpServiceLocked(ServiceRecord r,
11216 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011217 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011218 //r.dump(" ");
11219
Dianne Hackborn36124872009-10-08 16:22:03 -070011220 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011221 sendServiceArgsLocked(r, false);
11222 return true;
11223 }
11224
11225 if (!whileRestarting && r.restartDelay > 0) {
11226 // If waiting for a restart, then do nothing.
11227 return true;
11228 }
11229
Joe Onorato8a9b2202010-02-26 18:56:32 -080011230 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 + " " + r.intent);
11232
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011233 // We are now bringing the service up, so no longer in the
11234 // restarting state.
11235 mRestartingServices.remove(r);
11236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 final String appName = r.processName;
11238 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11239 if (app != null && app.thread != null) {
11240 try {
11241 realStartServiceLocked(r, app);
11242 return true;
11243 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011244 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011245 }
11246
11247 // If a dead object exception was thrown -- fall through to
11248 // restart the application.
11249 }
11250
Dianne Hackborn36124872009-10-08 16:22:03 -070011251 // Not running -- get it started, and enqueue this service record
11252 // to be executed when the app comes up.
11253 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11254 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011255 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011256 + r.appInfo.packageName + "/"
11257 + r.appInfo.uid + " for service "
11258 + r.intent.getIntent() + ": process is bad");
11259 bringDownServiceLocked(r, true);
11260 return false;
11261 }
11262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011264 mPendingServices.add(r);
11265 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 return true;
11268 }
11269
11270 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011271 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 //r.dump(" ");
11273
11274 // Does it still need to run?
11275 if (!force && r.startRequested) {
11276 return;
11277 }
11278 if (r.connections.size() > 0) {
11279 if (!force) {
11280 // XXX should probably keep a count of the number of auto-create
11281 // connections directly in the service.
11282 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11283 while (it.hasNext()) {
11284 ConnectionRecord cr = it.next();
11285 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11286 return;
11287 }
11288 }
11289 }
11290
11291 // Report to all of the connections that the service is no longer
11292 // available.
11293 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11294 while (it.hasNext()) {
11295 ConnectionRecord c = it.next();
11296 try {
11297 // todo: shouldn't be a synchronous call!
11298 c.conn.connected(r.name, null);
11299 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011300 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011301 " to connection " + c.conn.asBinder() +
11302 " (in " + c.binding.client.processName + ")", e);
11303 }
11304 }
11305 }
11306
11307 // Tell the service that it has been unbound.
11308 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11309 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11310 while (it.hasNext()) {
11311 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011312 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 + ": hasBound=" + ibr.hasBound);
11314 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11315 try {
11316 bumpServiceExecutingLocked(r);
11317 updateOomAdjLocked(r.app);
11318 ibr.hasBound = false;
11319 r.app.thread.scheduleUnbindService(r,
11320 ibr.intent.getIntent());
11321 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011322 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011323 + r.shortName, e);
11324 serviceDoneExecutingLocked(r, true);
11325 }
11326 }
11327 }
11328 }
11329
Joe Onorato8a9b2202010-02-26 18:56:32 -080011330 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011331 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011332 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011333 System.identityHashCode(r), r.shortName,
11334 (r.app != null) ? r.app.pid : -1);
11335
11336 mServices.remove(r.name);
11337 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011338 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 r.totalRestartCount = 0;
11340 unscheduleServiceRestartLocked(r);
11341
11342 // Also make sure it is not on the pending list.
11343 int N = mPendingServices.size();
11344 for (int i=0; i<N; i++) {
11345 if (mPendingServices.get(i) == r) {
11346 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011347 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011348 TAG, "Removed pending service: " + r.shortName);
11349 i--;
11350 N--;
11351 }
11352 }
11353
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011354 r.cancelNotification();
11355 r.isForeground = false;
11356 r.foregroundId = 0;
11357 r.foregroundNoti = null;
11358
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011359 // Clear start entries.
11360 r.deliveredStarts.clear();
11361 r.pendingStarts.clear();
11362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011363 if (r.app != null) {
11364 synchronized (r.stats.getBatteryStats()) {
11365 r.stats.stopLaunchedLocked();
11366 }
11367 r.app.services.remove(r);
11368 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011369 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011370 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011371 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011372 bumpServiceExecutingLocked(r);
11373 mStoppingServices.add(r);
11374 updateOomAdjLocked(r.app);
11375 r.app.thread.scheduleStopService(r);
11376 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011377 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011378 + r.shortName, e);
11379 serviceDoneExecutingLocked(r, true);
11380 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011381 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011382 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011383 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384 TAG, "Removed service that has no process: " + r.shortName);
11385 }
11386 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011387 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011388 TAG, "Removed service that is not running: " + r.shortName);
11389 }
11390 }
11391
11392 ComponentName startServiceLocked(IApplicationThread caller,
11393 Intent service, String resolvedType,
11394 int callingPid, int callingUid) {
11395 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011396 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011397 + " type=" + resolvedType + " args=" + service.getExtras());
11398
11399 if (caller != null) {
11400 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11401 if (callerApp == null) {
11402 throw new SecurityException(
11403 "Unable to find app for caller " + caller
11404 + " (pid=" + Binder.getCallingPid()
11405 + ") when starting service " + service);
11406 }
11407 }
11408
11409 ServiceLookupResult res =
11410 retrieveServiceLocked(service, resolvedType,
11411 callingPid, callingUid);
11412 if (res == null) {
11413 return null;
11414 }
11415 if (res.record == null) {
11416 return new ComponentName("!", res.permission != null
11417 ? res.permission : "private to package");
11418 }
11419 ServiceRecord r = res.record;
11420 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011421 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011422 + r.shortName);
11423 }
11424 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011425 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426 r.lastStartId++;
11427 if (r.lastStartId < 1) {
11428 r.lastStartId = 1;
11429 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011430 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011431 r.lastActivity = SystemClock.uptimeMillis();
11432 synchronized (r.stats.getBatteryStats()) {
11433 r.stats.startRunningLocked();
11434 }
11435 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11436 return new ComponentName("!", "Service process is bad");
11437 }
11438 return r.name;
11439 }
11440 }
11441
11442 public ComponentName startService(IApplicationThread caller, Intent service,
11443 String resolvedType) {
11444 // Refuse possible leaked file descriptors
11445 if (service != null && service.hasFileDescriptors() == true) {
11446 throw new IllegalArgumentException("File descriptors passed in Intent");
11447 }
11448
11449 synchronized(this) {
11450 final int callingPid = Binder.getCallingPid();
11451 final int callingUid = Binder.getCallingUid();
11452 final long origId = Binder.clearCallingIdentity();
11453 ComponentName res = startServiceLocked(caller, service,
11454 resolvedType, callingPid, callingUid);
11455 Binder.restoreCallingIdentity(origId);
11456 return res;
11457 }
11458 }
11459
11460 ComponentName startServiceInPackage(int uid,
11461 Intent service, String resolvedType) {
11462 synchronized(this) {
11463 final long origId = Binder.clearCallingIdentity();
11464 ComponentName res = startServiceLocked(null, service,
11465 resolvedType, -1, uid);
11466 Binder.restoreCallingIdentity(origId);
11467 return res;
11468 }
11469 }
11470
11471 public int stopService(IApplicationThread caller, Intent service,
11472 String resolvedType) {
11473 // Refuse possible leaked file descriptors
11474 if (service != null && service.hasFileDescriptors() == true) {
11475 throw new IllegalArgumentException("File descriptors passed in Intent");
11476 }
11477
11478 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011479 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011480 + " type=" + resolvedType);
11481
11482 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11483 if (caller != null && callerApp == null) {
11484 throw new SecurityException(
11485 "Unable to find app for caller " + caller
11486 + " (pid=" + Binder.getCallingPid()
11487 + ") when stopping service " + service);
11488 }
11489
11490 // If this service is active, make sure it is stopped.
11491 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11492 if (r != null) {
11493 if (r.record != null) {
11494 synchronized (r.record.stats.getBatteryStats()) {
11495 r.record.stats.stopRunningLocked();
11496 }
11497 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011498 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011499 final long origId = Binder.clearCallingIdentity();
11500 bringDownServiceLocked(r.record, false);
11501 Binder.restoreCallingIdentity(origId);
11502 return 1;
11503 }
11504 return -1;
11505 }
11506 }
11507
11508 return 0;
11509 }
11510
11511 public IBinder peekService(Intent service, String resolvedType) {
11512 // Refuse possible leaked file descriptors
11513 if (service != null && service.hasFileDescriptors() == true) {
11514 throw new IllegalArgumentException("File descriptors passed in Intent");
11515 }
11516
11517 IBinder ret = null;
11518
11519 synchronized(this) {
11520 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11521
11522 if (r != null) {
11523 // r.record is null if findServiceLocked() failed the caller permission check
11524 if (r.record == null) {
11525 throw new SecurityException(
11526 "Permission Denial: Accessing service " + r.record.name
11527 + " from pid=" + Binder.getCallingPid()
11528 + ", uid=" + Binder.getCallingUid()
11529 + " requires " + r.permission);
11530 }
11531 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11532 if (ib != null) {
11533 ret = ib.binder;
11534 }
11535 }
11536 }
11537
11538 return ret;
11539 }
11540
11541 public boolean stopServiceToken(ComponentName className, IBinder token,
11542 int startId) {
11543 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011544 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545 + " " + token + " startId=" + startId);
11546 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011547 if (r != null) {
11548 if (startId >= 0) {
11549 // Asked to only stop if done with all work. Note that
11550 // to avoid leaks, we will take this as dropping all
11551 // start items up to and including this one.
11552 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11553 if (si != null) {
11554 while (r.deliveredStarts.size() > 0) {
11555 if (r.deliveredStarts.remove(0) == si) {
11556 break;
11557 }
11558 }
11559 }
11560
11561 if (r.lastStartId != startId) {
11562 return false;
11563 }
11564
11565 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011566 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011567 + " is last, but have " + r.deliveredStarts.size()
11568 + " remaining args");
11569 }
11570 }
11571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572 synchronized (r.stats.getBatteryStats()) {
11573 r.stats.stopRunningLocked();
11574 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011575 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576 }
11577 final long origId = Binder.clearCallingIdentity();
11578 bringDownServiceLocked(r, false);
11579 Binder.restoreCallingIdentity(origId);
11580 return true;
11581 }
11582 }
11583 return false;
11584 }
11585
11586 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011587 int id, Notification notification, boolean removeNotification) {
11588 final long origId = Binder.clearCallingIdentity();
11589 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011590 synchronized(this) {
11591 ServiceRecord r = findServiceLocked(className, token);
11592 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011593 if (id != 0) {
11594 if (notification == null) {
11595 throw new IllegalArgumentException("null notification");
11596 }
11597 if (r.foregroundId != id) {
11598 r.cancelNotification();
11599 r.foregroundId = id;
11600 }
11601 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11602 r.foregroundNoti = notification;
11603 r.isForeground = true;
11604 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011605 if (r.app != null) {
11606 updateServiceForegroundLocked(r.app, true);
11607 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011608 } else {
11609 if (r.isForeground) {
11610 r.isForeground = false;
11611 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011612 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011613 updateServiceForegroundLocked(r.app, true);
11614 }
11615 }
11616 if (removeNotification) {
11617 r.cancelNotification();
11618 r.foregroundId = 0;
11619 r.foregroundNoti = null;
11620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 }
11622 }
11623 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011624 } finally {
11625 Binder.restoreCallingIdentity(origId);
11626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011627 }
11628
11629 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11630 boolean anyForeground = false;
11631 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11632 if (sr.isForeground) {
11633 anyForeground = true;
11634 break;
11635 }
11636 }
11637 if (anyForeground != proc.foregroundServices) {
11638 proc.foregroundServices = anyForeground;
11639 if (oomAdj) {
11640 updateOomAdjLocked();
11641 }
11642 }
11643 }
11644
11645 public int bindService(IApplicationThread caller, IBinder token,
11646 Intent service, String resolvedType,
11647 IServiceConnection connection, int flags) {
11648 // Refuse possible leaked file descriptors
11649 if (service != null && service.hasFileDescriptors() == true) {
11650 throw new IllegalArgumentException("File descriptors passed in Intent");
11651 }
11652
11653 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011654 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011655 + " type=" + resolvedType + " conn=" + connection.asBinder()
11656 + " flags=0x" + Integer.toHexString(flags));
11657 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11658 if (callerApp == null) {
11659 throw new SecurityException(
11660 "Unable to find app for caller " + caller
11661 + " (pid=" + Binder.getCallingPid()
11662 + ") when binding service " + service);
11663 }
11664
11665 HistoryRecord activity = null;
11666 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011667 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011668 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011669 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011670 return 0;
11671 }
11672 activity = (HistoryRecord)mHistory.get(aindex);
11673 }
11674
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011675 int clientLabel = 0;
11676 PendingIntent clientIntent = null;
11677
11678 if (callerApp.info.uid == Process.SYSTEM_UID) {
11679 // Hacky kind of thing -- allow system stuff to tell us
11680 // what they are, so we can report this elsewhere for
11681 // others to know why certain services are running.
11682 try {
11683 clientIntent = (PendingIntent)service.getParcelableExtra(
11684 Intent.EXTRA_CLIENT_INTENT);
11685 } catch (RuntimeException e) {
11686 }
11687 if (clientIntent != null) {
11688 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11689 if (clientLabel != 0) {
11690 // There are no useful extras in the intent, trash them.
11691 // System code calling with this stuff just needs to know
11692 // this will happen.
11693 service = service.cloneFilter();
11694 }
11695 }
11696 }
11697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011698 ServiceLookupResult res =
11699 retrieveServiceLocked(service, resolvedType,
11700 Binder.getCallingPid(), Binder.getCallingUid());
11701 if (res == null) {
11702 return 0;
11703 }
11704 if (res.record == null) {
11705 return -1;
11706 }
11707 ServiceRecord s = res.record;
11708
11709 final long origId = Binder.clearCallingIdentity();
11710
11711 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011712 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011713 + s.shortName);
11714 }
11715
11716 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11717 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011718 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011719
11720 IBinder binder = connection.asBinder();
11721 s.connections.put(binder, c);
11722 b.connections.add(c);
11723 if (activity != null) {
11724 if (activity.connections == null) {
11725 activity.connections = new HashSet<ConnectionRecord>();
11726 }
11727 activity.connections.add(c);
11728 }
11729 b.client.connections.add(c);
11730 mServiceConnections.put(binder, c);
11731
11732 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11733 s.lastActivity = SystemClock.uptimeMillis();
11734 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11735 return 0;
11736 }
11737 }
11738
11739 if (s.app != null) {
11740 // This could have made the service more important.
11741 updateOomAdjLocked(s.app);
11742 }
11743
Joe Onorato8a9b2202010-02-26 18:56:32 -080011744 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011745 + ": received=" + b.intent.received
11746 + " apps=" + b.intent.apps.size()
11747 + " doRebind=" + b.intent.doRebind);
11748
11749 if (s.app != null && b.intent.received) {
11750 // Service is already running, so we can immediately
11751 // publish the connection.
11752 try {
11753 c.conn.connected(s.name, b.intent.binder);
11754 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011755 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011756 + " to connection " + c.conn.asBinder()
11757 + " (in " + c.binding.client.processName + ")", e);
11758 }
11759
11760 // If this is the first app connected back to this binding,
11761 // and the service had previously asked to be told when
11762 // rebound, then do so.
11763 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11764 requestServiceBindingLocked(s, b.intent, true);
11765 }
11766 } else if (!b.intent.requested) {
11767 requestServiceBindingLocked(s, b.intent, false);
11768 }
11769
11770 Binder.restoreCallingIdentity(origId);
11771 }
11772
11773 return 1;
11774 }
11775
11776 private void removeConnectionLocked(
11777 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11778 IBinder binder = c.conn.asBinder();
11779 AppBindRecord b = c.binding;
11780 ServiceRecord s = b.service;
11781 s.connections.remove(binder);
11782 b.connections.remove(c);
11783 if (c.activity != null && c.activity != skipAct) {
11784 if (c.activity.connections != null) {
11785 c.activity.connections.remove(c);
11786 }
11787 }
11788 if (b.client != skipApp) {
11789 b.client.connections.remove(c);
11790 }
11791 mServiceConnections.remove(binder);
11792
11793 if (b.connections.size() == 0) {
11794 b.intent.apps.remove(b.client);
11795 }
11796
Joe Onorato8a9b2202010-02-26 18:56:32 -080011797 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011798 + ": shouldUnbind=" + b.intent.hasBound);
11799 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11800 && b.intent.hasBound) {
11801 try {
11802 bumpServiceExecutingLocked(s);
11803 updateOomAdjLocked(s.app);
11804 b.intent.hasBound = false;
11805 // Assume the client doesn't want to know about a rebind;
11806 // we will deal with that later if it asks for one.
11807 b.intent.doRebind = false;
11808 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11809 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011810 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011811 serviceDoneExecutingLocked(s, true);
11812 }
11813 }
11814
11815 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11816 bringDownServiceLocked(s, false);
11817 }
11818 }
11819
11820 public boolean unbindService(IServiceConnection connection) {
11821 synchronized (this) {
11822 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011823 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011824 ConnectionRecord r = mServiceConnections.get(binder);
11825 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011826 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011827 + connection.asBinder());
11828 return false;
11829 }
11830
11831 final long origId = Binder.clearCallingIdentity();
11832
11833 removeConnectionLocked(r, null, null);
11834
11835 if (r.binding.service.app != null) {
11836 // This could have made the service less important.
11837 updateOomAdjLocked(r.binding.service.app);
11838 }
11839
11840 Binder.restoreCallingIdentity(origId);
11841 }
11842
11843 return true;
11844 }
11845
11846 public void publishService(IBinder token, Intent intent, IBinder service) {
11847 // Refuse possible leaked file descriptors
11848 if (intent != null && intent.hasFileDescriptors() == true) {
11849 throw new IllegalArgumentException("File descriptors passed in Intent");
11850 }
11851
11852 synchronized(this) {
11853 if (!(token instanceof ServiceRecord)) {
11854 throw new IllegalArgumentException("Invalid service token");
11855 }
11856 ServiceRecord r = (ServiceRecord)token;
11857
11858 final long origId = Binder.clearCallingIdentity();
11859
Joe Onorato8a9b2202010-02-26 18:56:32 -080011860 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011861 + " " + intent + ": " + service);
11862 if (r != null) {
11863 Intent.FilterComparison filter
11864 = new Intent.FilterComparison(intent);
11865 IntentBindRecord b = r.bindings.get(filter);
11866 if (b != null && !b.received) {
11867 b.binder = service;
11868 b.requested = true;
11869 b.received = true;
11870 if (r.connections.size() > 0) {
11871 Iterator<ConnectionRecord> it
11872 = r.connections.values().iterator();
11873 while (it.hasNext()) {
11874 ConnectionRecord c = it.next();
11875 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011876 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011877 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011878 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011879 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011880 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011881 TAG, "Published intent: " + intent);
11882 continue;
11883 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011884 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011885 try {
11886 c.conn.connected(r.name, service);
11887 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011888 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011889 " to connection " + c.conn.asBinder() +
11890 " (in " + c.binding.client.processName + ")", e);
11891 }
11892 }
11893 }
11894 }
11895
11896 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11897
11898 Binder.restoreCallingIdentity(origId);
11899 }
11900 }
11901 }
11902
11903 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11904 // Refuse possible leaked file descriptors
11905 if (intent != null && intent.hasFileDescriptors() == true) {
11906 throw new IllegalArgumentException("File descriptors passed in Intent");
11907 }
11908
11909 synchronized(this) {
11910 if (!(token instanceof ServiceRecord)) {
11911 throw new IllegalArgumentException("Invalid service token");
11912 }
11913 ServiceRecord r = (ServiceRecord)token;
11914
11915 final long origId = Binder.clearCallingIdentity();
11916
11917 if (r != null) {
11918 Intent.FilterComparison filter
11919 = new Intent.FilterComparison(intent);
11920 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011921 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011922 + " at " + b + ": apps="
11923 + (b != null ? b.apps.size() : 0));
11924 if (b != null) {
11925 if (b.apps.size() > 0) {
11926 // Applications have already bound since the last
11927 // unbind, so just rebind right here.
11928 requestServiceBindingLocked(r, b, true);
11929 } else {
11930 // Note to tell the service the next time there is
11931 // a new client.
11932 b.doRebind = true;
11933 }
11934 }
11935
11936 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11937
11938 Binder.restoreCallingIdentity(origId);
11939 }
11940 }
11941 }
11942
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011943 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011944 synchronized(this) {
11945 if (!(token instanceof ServiceRecord)) {
11946 throw new IllegalArgumentException("Invalid service token");
11947 }
11948 ServiceRecord r = (ServiceRecord)token;
11949 boolean inStopping = mStoppingServices.contains(token);
11950 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011951 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 + ": nesting=" + r.executeNesting
11953 + ", inStopping=" + inStopping);
11954 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011955 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011956 + " with incorrect token: given " + token
11957 + ", expected " + r);
11958 return;
11959 }
11960
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011961 if (type == 1) {
11962 // This is a call from a service start... take care of
11963 // book-keeping.
11964 r.callStart = true;
11965 switch (res) {
11966 case Service.START_STICKY_COMPATIBILITY:
11967 case Service.START_STICKY: {
11968 // We are done with the associated start arguments.
11969 r.findDeliveredStart(startId, true);
11970 // Don't stop if killed.
11971 r.stopIfKilled = false;
11972 break;
11973 }
11974 case Service.START_NOT_STICKY: {
11975 // We are done with the associated start arguments.
11976 r.findDeliveredStart(startId, true);
11977 if (r.lastStartId == startId) {
11978 // There is no more work, and this service
11979 // doesn't want to hang around if killed.
11980 r.stopIfKilled = true;
11981 }
11982 break;
11983 }
11984 case Service.START_REDELIVER_INTENT: {
11985 // We'll keep this item until they explicitly
11986 // call stop for it, but keep track of the fact
11987 // that it was delivered.
11988 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11989 if (si != null) {
11990 si.deliveryCount = 0;
11991 si.doneExecutingCount++;
11992 // Don't stop if killed.
11993 r.stopIfKilled = true;
11994 }
11995 break;
11996 }
11997 default:
11998 throw new IllegalArgumentException(
11999 "Unknown service start result: " + res);
12000 }
12001 if (res == Service.START_STICKY_COMPATIBILITY) {
12002 r.callStart = false;
12003 }
12004 }
12005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012006 final long origId = Binder.clearCallingIdentity();
12007 serviceDoneExecutingLocked(r, inStopping);
12008 Binder.restoreCallingIdentity(origId);
12009 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012010 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012011 + " with token " + token);
12012 }
12013 }
12014 }
12015
12016 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
12017 r.executeNesting--;
12018 if (r.executeNesting <= 0 && r.app != null) {
12019 r.app.executingServices.remove(r);
12020 if (r.app.executingServices.size() == 0) {
12021 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12022 }
12023 if (inStopping) {
12024 mStoppingServices.remove(r);
12025 }
12026 updateOomAdjLocked(r.app);
12027 }
12028 }
12029
12030 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012031 String anrMessage = null;
12032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012033 synchronized(this) {
12034 if (proc.executingServices.size() == 0 || proc.thread == null) {
12035 return;
12036 }
12037 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12038 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12039 ServiceRecord timeout = null;
12040 long nextTime = 0;
12041 while (it.hasNext()) {
12042 ServiceRecord sr = it.next();
12043 if (sr.executingStart < maxTime) {
12044 timeout = sr;
12045 break;
12046 }
12047 if (sr.executingStart > nextTime) {
12048 nextTime = sr.executingStart;
12049 }
12050 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012051 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012052 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012053 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012054 } else {
12055 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12056 msg.obj = proc;
12057 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12058 }
12059 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012060
12061 if (anrMessage != null) {
12062 appNotResponding(proc, null, null, anrMessage);
12063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012064 }
12065
12066 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012067 // BACKUP AND RESTORE
12068 // =========================================================
12069
12070 // Cause the target app to be launched if necessary and its backup agent
12071 // instantiated. The backup agent will invoke backupAgentCreated() on the
12072 // activity manager to announce its creation.
12073 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012074 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012075 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12076
12077 synchronized(this) {
12078 // !!! TODO: currently no check here that we're already bound
12079 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12080 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12081 synchronized (stats) {
12082 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12083 }
12084
12085 BackupRecord r = new BackupRecord(ss, app, backupMode);
12086 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12087 // startProcessLocked() returns existing proc's record if it's already running
12088 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012089 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012090 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012091 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012092 return false;
12093 }
12094
12095 r.app = proc;
12096 mBackupTarget = r;
12097 mBackupAppName = app.packageName;
12098
Christopher Tate6fa95972009-06-05 18:43:55 -070012099 // Try not to kill the process during backup
12100 updateOomAdjLocked(proc);
12101
Christopher Tate181fafa2009-05-14 11:12:14 -070012102 // If the process is already attached, schedule the creation of the backup agent now.
12103 // If it is not yet live, this will be done when it attaches to the framework.
12104 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012105 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012106 try {
12107 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12108 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012109 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012110 }
12111 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012112 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012113 }
12114 // Invariants: at this point, the target app process exists and the application
12115 // is either already running or in the process of coming up. mBackupTarget and
12116 // mBackupAppName describe the app, so that when it binds back to the AM we
12117 // know that it's scheduled for a backup-agent operation.
12118 }
12119
12120 return true;
12121 }
12122
12123 // A backup agent has just come up
12124 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012125 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012126 + " = " + agent);
12127
12128 synchronized(this) {
12129 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012130 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012131 return;
12132 }
12133
Christopher Tate043dadc2009-06-02 16:11:00 -070012134 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012135 try {
12136 IBackupManager bm = IBackupManager.Stub.asInterface(
12137 ServiceManager.getService(Context.BACKUP_SERVICE));
12138 bm.agentConnected(agentPackageName, agent);
12139 } catch (RemoteException e) {
12140 // can't happen; the backup manager service is local
12141 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012142 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012143 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012144 } finally {
12145 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012146 }
12147 }
12148 }
12149
12150 // done with this agent
12151 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012152 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012153 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012154 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012155 return;
12156 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012157
12158 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012159 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012160 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012161 return;
12162 }
12163
Christopher Tate181fafa2009-05-14 11:12:14 -070012164 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012165 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012166 return;
12167 }
12168
Christopher Tate6fa95972009-06-05 18:43:55 -070012169 ProcessRecord proc = mBackupTarget.app;
12170 mBackupTarget = null;
12171 mBackupAppName = null;
12172
12173 // Not backing this app up any more; reset its OOM adjustment
12174 updateOomAdjLocked(proc);
12175
Christopher Tatec7b31e32009-06-10 15:49:30 -070012176 // If the app crashed during backup, 'thread' will be null here
12177 if (proc.thread != null) {
12178 try {
12179 proc.thread.scheduleDestroyBackupAgent(appInfo);
12180 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012181 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012182 e.printStackTrace();
12183 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012184 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012185 }
12186 }
12187 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012188 // BROADCASTS
12189 // =========================================================
12190
Josh Bartel7f208742010-02-25 11:01:44 -060012191 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012192 List cur) {
12193 final ContentResolver resolver = mContext.getContentResolver();
12194 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12195 if (list == null) {
12196 return cur;
12197 }
12198 int N = list.size();
12199 for (int i=0; i<N; i++) {
12200 Intent intent = list.get(i);
12201 if (filter.match(resolver, intent, true, TAG) >= 0) {
12202 if (cur == null) {
12203 cur = new ArrayList<Intent>();
12204 }
12205 cur.add(intent);
12206 }
12207 }
12208 return cur;
12209 }
12210
12211 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012212 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012213 + mBroadcastsScheduled);
12214
12215 if (mBroadcastsScheduled) {
12216 return;
12217 }
12218 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12219 mBroadcastsScheduled = true;
12220 }
12221
12222 public Intent registerReceiver(IApplicationThread caller,
12223 IIntentReceiver receiver, IntentFilter filter, String permission) {
12224 synchronized(this) {
12225 ProcessRecord callerApp = null;
12226 if (caller != null) {
12227 callerApp = getRecordForAppLocked(caller);
12228 if (callerApp == null) {
12229 throw new SecurityException(
12230 "Unable to find app for caller " + caller
12231 + " (pid=" + Binder.getCallingPid()
12232 + ") when registering receiver " + receiver);
12233 }
12234 }
12235
12236 List allSticky = null;
12237
12238 // Look for any matching sticky broadcasts...
12239 Iterator actions = filter.actionsIterator();
12240 if (actions != null) {
12241 while (actions.hasNext()) {
12242 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012243 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012244 }
12245 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012246 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012247 }
12248
12249 // The first sticky in the list is returned directly back to
12250 // the client.
12251 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12252
Joe Onorato8a9b2202010-02-26 18:56:32 -080012253 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012254 + ": " + sticky);
12255
12256 if (receiver == null) {
12257 return sticky;
12258 }
12259
12260 ReceiverList rl
12261 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12262 if (rl == null) {
12263 rl = new ReceiverList(this, callerApp,
12264 Binder.getCallingPid(),
12265 Binder.getCallingUid(), receiver);
12266 if (rl.app != null) {
12267 rl.app.receivers.add(rl);
12268 } else {
12269 try {
12270 receiver.asBinder().linkToDeath(rl, 0);
12271 } catch (RemoteException e) {
12272 return sticky;
12273 }
12274 rl.linkedToDeath = true;
12275 }
12276 mRegisteredReceivers.put(receiver.asBinder(), rl);
12277 }
12278 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12279 rl.add(bf);
12280 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012281 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012282 }
12283 mReceiverResolver.addFilter(bf);
12284
12285 // Enqueue broadcasts for all existing stickies that match
12286 // this filter.
12287 if (allSticky != null) {
12288 ArrayList receivers = new ArrayList();
12289 receivers.add(bf);
12290
12291 int N = allSticky.size();
12292 for (int i=0; i<N; i++) {
12293 Intent intent = (Intent)allSticky.get(i);
12294 BroadcastRecord r = new BroadcastRecord(intent, null,
12295 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012296 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012297 if (mParallelBroadcasts.size() == 0) {
12298 scheduleBroadcastsLocked();
12299 }
12300 mParallelBroadcasts.add(r);
12301 }
12302 }
12303
12304 return sticky;
12305 }
12306 }
12307
12308 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012309 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012310
12311 boolean doNext = false;
12312
12313 synchronized(this) {
12314 ReceiverList rl
12315 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12316 if (rl != null) {
12317 if (rl.curBroadcast != null) {
12318 BroadcastRecord r = rl.curBroadcast;
12319 doNext = finishReceiverLocked(
12320 receiver.asBinder(), r.resultCode, r.resultData,
12321 r.resultExtras, r.resultAbort, true);
12322 }
12323
12324 if (rl.app != null) {
12325 rl.app.receivers.remove(rl);
12326 }
12327 removeReceiverLocked(rl);
12328 if (rl.linkedToDeath) {
12329 rl.linkedToDeath = false;
12330 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12331 }
12332 }
12333 }
12334
12335 if (!doNext) {
12336 return;
12337 }
12338
12339 final long origId = Binder.clearCallingIdentity();
12340 processNextBroadcast(false);
12341 trimApplications();
12342 Binder.restoreCallingIdentity(origId);
12343 }
12344
12345 void removeReceiverLocked(ReceiverList rl) {
12346 mRegisteredReceivers.remove(rl.receiver.asBinder());
12347 int N = rl.size();
12348 for (int i=0; i<N; i++) {
12349 mReceiverResolver.removeFilter(rl.get(i));
12350 }
12351 }
12352
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012353 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12354 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12355 ProcessRecord r = mLruProcesses.get(i);
12356 if (r.thread != null) {
12357 try {
12358 r.thread.dispatchPackageBroadcast(cmd, packages);
12359 } catch (RemoteException ex) {
12360 }
12361 }
12362 }
12363 }
12364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012365 private final int broadcastIntentLocked(ProcessRecord callerApp,
12366 String callerPackage, Intent intent, String resolvedType,
12367 IIntentReceiver resultTo, int resultCode, String resultData,
12368 Bundle map, String requiredPermission,
12369 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12370 intent = new Intent(intent);
12371
Joe Onorato8a9b2202010-02-26 18:56:32 -080012372 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012373 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12374 + " ordered=" + ordered);
12375 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012376 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012377 }
12378
12379 // Handle special intents: if this broadcast is from the package
12380 // manager about a package being removed, we need to remove all of
12381 // its activities from the history stack.
12382 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12383 intent.getAction());
12384 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12385 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012386 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012387 || uidRemoved) {
12388 if (checkComponentPermission(
12389 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12390 callingPid, callingUid, -1)
12391 == PackageManager.PERMISSION_GRANTED) {
12392 if (uidRemoved) {
12393 final Bundle intentExtras = intent.getExtras();
12394 final int uid = intentExtras != null
12395 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12396 if (uid >= 0) {
12397 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12398 synchronized (bs) {
12399 bs.removeUidStatsLocked(uid);
12400 }
12401 }
12402 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012403 // If resources are unvailble just force stop all
12404 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012405 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012406 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12407 if (list != null && (list.length > 0)) {
12408 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012409 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012410 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012411 sendPackageBroadcastLocked(
12412 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012413 }
12414 } else {
12415 Uri data = intent.getData();
12416 String ssp;
12417 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12418 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12419 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012420 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012421 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012422 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12423 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12424 new String[] {ssp});
12425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012426 }
12427 }
12428 }
12429 } else {
12430 String msg = "Permission Denial: " + intent.getAction()
12431 + " broadcast from " + callerPackage + " (pid=" + callingPid
12432 + ", uid=" + callingUid + ")"
12433 + " requires "
12434 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012435 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012436 throw new SecurityException(msg);
12437 }
12438 }
12439
12440 /*
12441 * If this is the time zone changed action, queue up a message that will reset the timezone
12442 * of all currently running processes. This message will get queued up before the broadcast
12443 * happens.
12444 */
12445 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12446 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12447 }
12448
Dianne Hackborn854060af2009-07-09 18:14:31 -070012449 /*
12450 * Prevent non-system code (defined here to be non-persistent
12451 * processes) from sending protected broadcasts.
12452 */
12453 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12454 || callingUid == Process.SHELL_UID || callingUid == 0) {
12455 // Always okay.
12456 } else if (callerApp == null || !callerApp.persistent) {
12457 try {
12458 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12459 intent.getAction())) {
12460 String msg = "Permission Denial: not allowed to send broadcast "
12461 + intent.getAction() + " from pid="
12462 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012463 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012464 throw new SecurityException(msg);
12465 }
12466 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012467 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012468 return BROADCAST_SUCCESS;
12469 }
12470 }
12471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012472 // Add to the sticky list if requested.
12473 if (sticky) {
12474 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12475 callingPid, callingUid)
12476 != PackageManager.PERMISSION_GRANTED) {
12477 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12478 + callingPid + ", uid=" + callingUid
12479 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012480 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012481 throw new SecurityException(msg);
12482 }
12483 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012484 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012485 + " and enforce permission " + requiredPermission);
12486 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12487 }
12488 if (intent.getComponent() != null) {
12489 throw new SecurityException(
12490 "Sticky broadcasts can't target a specific component");
12491 }
12492 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12493 if (list == null) {
12494 list = new ArrayList<Intent>();
12495 mStickyBroadcasts.put(intent.getAction(), list);
12496 }
12497 int N = list.size();
12498 int i;
12499 for (i=0; i<N; i++) {
12500 if (intent.filterEquals(list.get(i))) {
12501 // This sticky already exists, replace it.
12502 list.set(i, new Intent(intent));
12503 break;
12504 }
12505 }
12506 if (i >= N) {
12507 list.add(new Intent(intent));
12508 }
12509 }
12510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012511 // Figure out who all will receive this broadcast.
12512 List receivers = null;
12513 List<BroadcastFilter> registeredReceivers = null;
12514 try {
12515 if (intent.getComponent() != null) {
12516 // Broadcast is going to one specific receiver class...
12517 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012518 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012519 if (ai != null) {
12520 receivers = new ArrayList();
12521 ResolveInfo ri = new ResolveInfo();
12522 ri.activityInfo = ai;
12523 receivers.add(ri);
12524 }
12525 } else {
12526 // Need to resolve the intent to interested receivers...
12527 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12528 == 0) {
12529 receivers =
12530 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012531 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012532 }
Mihai Preda074edef2009-05-18 17:13:31 +020012533 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012534 }
12535 } catch (RemoteException ex) {
12536 // pm is in same process, this will never happen.
12537 }
12538
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012539 final boolean replacePending =
12540 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12541
Joe Onorato8a9b2202010-02-26 18:56:32 -080012542 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012543 + " replacePending=" + replacePending);
12544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012545 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12546 if (!ordered && NR > 0) {
12547 // If we are not serializing this broadcast, then send the
12548 // registered receivers separately so they don't wait for the
12549 // components to be launched.
12550 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12551 callerPackage, callingPid, callingUid, requiredPermission,
12552 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012553 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012554 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012555 TAG, "Enqueueing parallel broadcast " + r
12556 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012557 boolean replaced = false;
12558 if (replacePending) {
12559 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12560 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012561 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012562 "***** DROPPING PARALLEL: " + intent);
12563 mParallelBroadcasts.set(i, r);
12564 replaced = true;
12565 break;
12566 }
12567 }
12568 }
12569 if (!replaced) {
12570 mParallelBroadcasts.add(r);
12571 scheduleBroadcastsLocked();
12572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012573 registeredReceivers = null;
12574 NR = 0;
12575 }
12576
12577 // Merge into one list.
12578 int ir = 0;
12579 if (receivers != null) {
12580 // A special case for PACKAGE_ADDED: do not allow the package
12581 // being added to see this broadcast. This prevents them from
12582 // using this as a back door to get run as soon as they are
12583 // installed. Maybe in the future we want to have a special install
12584 // broadcast or such for apps, but we'd like to deliberately make
12585 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012586 String skipPackages[] = null;
12587 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12588 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12589 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12590 Uri data = intent.getData();
12591 if (data != null) {
12592 String pkgName = data.getSchemeSpecificPart();
12593 if (pkgName != null) {
12594 skipPackages = new String[] { pkgName };
12595 }
12596 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012597 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012598 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012599 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012600 if (skipPackages != null && (skipPackages.length > 0)) {
12601 for (String skipPackage : skipPackages) {
12602 if (skipPackage != null) {
12603 int NT = receivers.size();
12604 for (int it=0; it<NT; it++) {
12605 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12606 if (curt.activityInfo.packageName.equals(skipPackage)) {
12607 receivers.remove(it);
12608 it--;
12609 NT--;
12610 }
12611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012612 }
12613 }
12614 }
12615
12616 int NT = receivers != null ? receivers.size() : 0;
12617 int it = 0;
12618 ResolveInfo curt = null;
12619 BroadcastFilter curr = null;
12620 while (it < NT && ir < NR) {
12621 if (curt == null) {
12622 curt = (ResolveInfo)receivers.get(it);
12623 }
12624 if (curr == null) {
12625 curr = registeredReceivers.get(ir);
12626 }
12627 if (curr.getPriority() >= curt.priority) {
12628 // Insert this broadcast record into the final list.
12629 receivers.add(it, curr);
12630 ir++;
12631 curr = null;
12632 it++;
12633 NT++;
12634 } else {
12635 // Skip to the next ResolveInfo in the final list.
12636 it++;
12637 curt = null;
12638 }
12639 }
12640 }
12641 while (ir < NR) {
12642 if (receivers == null) {
12643 receivers = new ArrayList();
12644 }
12645 receivers.add(registeredReceivers.get(ir));
12646 ir++;
12647 }
12648
12649 if ((receivers != null && receivers.size() > 0)
12650 || resultTo != null) {
12651 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12652 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012653 receivers, resultTo, resultCode, resultData, map, ordered,
12654 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012655 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012656 TAG, "Enqueueing ordered broadcast " + r
12657 + ": prev had " + mOrderedBroadcasts.size());
12658 if (DEBUG_BROADCAST) {
12659 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012660 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012661 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012662 boolean replaced = false;
12663 if (replacePending) {
12664 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12665 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012666 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012667 "***** DROPPING ORDERED: " + intent);
12668 mOrderedBroadcasts.set(i, r);
12669 replaced = true;
12670 break;
12671 }
12672 }
12673 }
12674 if (!replaced) {
12675 mOrderedBroadcasts.add(r);
12676 scheduleBroadcastsLocked();
12677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012678 }
12679
12680 return BROADCAST_SUCCESS;
12681 }
12682
12683 public final int broadcastIntent(IApplicationThread caller,
12684 Intent intent, String resolvedType, IIntentReceiver resultTo,
12685 int resultCode, String resultData, Bundle map,
12686 String requiredPermission, boolean serialized, boolean sticky) {
12687 // Refuse possible leaked file descriptors
12688 if (intent != null && intent.hasFileDescriptors() == true) {
12689 throw new IllegalArgumentException("File descriptors passed in Intent");
12690 }
12691
12692 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012693 int flags = intent.getFlags();
12694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012695 if (!mSystemReady) {
12696 // if the caller really truly claims to know what they're doing, go
12697 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012698 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12699 intent = new Intent(intent);
12700 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12701 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012702 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012703 + " before boot completion");
12704 throw new IllegalStateException("Cannot broadcast before boot completed");
12705 }
12706 }
12707
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012708 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12709 throw new IllegalArgumentException(
12710 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12711 }
12712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012713 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12714 final int callingPid = Binder.getCallingPid();
12715 final int callingUid = Binder.getCallingUid();
12716 final long origId = Binder.clearCallingIdentity();
12717 int res = broadcastIntentLocked(callerApp,
12718 callerApp != null ? callerApp.info.packageName : null,
12719 intent, resolvedType, resultTo,
12720 resultCode, resultData, map, requiredPermission, serialized,
12721 sticky, callingPid, callingUid);
12722 Binder.restoreCallingIdentity(origId);
12723 return res;
12724 }
12725 }
12726
12727 int broadcastIntentInPackage(String packageName, int uid,
12728 Intent intent, String resolvedType, IIntentReceiver resultTo,
12729 int resultCode, String resultData, Bundle map,
12730 String requiredPermission, boolean serialized, boolean sticky) {
12731 synchronized(this) {
12732 final long origId = Binder.clearCallingIdentity();
12733 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12734 resultTo, resultCode, resultData, map, requiredPermission,
12735 serialized, sticky, -1, uid);
12736 Binder.restoreCallingIdentity(origId);
12737 return res;
12738 }
12739 }
12740
12741 public final void unbroadcastIntent(IApplicationThread caller,
12742 Intent intent) {
12743 // Refuse possible leaked file descriptors
12744 if (intent != null && intent.hasFileDescriptors() == true) {
12745 throw new IllegalArgumentException("File descriptors passed in Intent");
12746 }
12747
12748 synchronized(this) {
12749 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12750 != PackageManager.PERMISSION_GRANTED) {
12751 String msg = "Permission Denial: unbroadcastIntent() from pid="
12752 + Binder.getCallingPid()
12753 + ", uid=" + Binder.getCallingUid()
12754 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012755 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012756 throw new SecurityException(msg);
12757 }
12758 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12759 if (list != null) {
12760 int N = list.size();
12761 int i;
12762 for (i=0; i<N; i++) {
12763 if (intent.filterEquals(list.get(i))) {
12764 list.remove(i);
12765 break;
12766 }
12767 }
12768 }
12769 }
12770 }
12771
12772 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12773 String resultData, Bundle resultExtras, boolean resultAbort,
12774 boolean explicit) {
12775 if (mOrderedBroadcasts.size() == 0) {
12776 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012777 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012778 }
12779 return false;
12780 }
12781 BroadcastRecord r = mOrderedBroadcasts.get(0);
12782 if (r.receiver == null) {
12783 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012784 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012785 }
12786 return false;
12787 }
12788 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012789 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012790 return false;
12791 }
12792 int state = r.state;
12793 r.state = r.IDLE;
12794 if (state == r.IDLE) {
12795 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012796 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012797 }
12798 }
12799 r.receiver = null;
12800 r.intent.setComponent(null);
12801 if (r.curApp != null) {
12802 r.curApp.curReceiver = null;
12803 }
12804 if (r.curFilter != null) {
12805 r.curFilter.receiverList.curBroadcast = null;
12806 }
12807 r.curFilter = null;
12808 r.curApp = null;
12809 r.curComponent = null;
12810 r.curReceiver = null;
12811 mPendingBroadcast = null;
12812
12813 r.resultCode = resultCode;
12814 r.resultData = resultData;
12815 r.resultExtras = resultExtras;
12816 r.resultAbort = resultAbort;
12817
12818 // We will process the next receiver right now if this is finishing
12819 // an app receiver (which is always asynchronous) or after we have
12820 // come back from calling a receiver.
12821 return state == BroadcastRecord.APP_RECEIVE
12822 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12823 }
12824
12825 public void finishReceiver(IBinder who, int resultCode, String resultData,
12826 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012827 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012828
12829 // Refuse possible leaked file descriptors
12830 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12831 throw new IllegalArgumentException("File descriptors passed in Bundle");
12832 }
12833
12834 boolean doNext;
12835
12836 final long origId = Binder.clearCallingIdentity();
12837
12838 synchronized(this) {
12839 doNext = finishReceiverLocked(
12840 who, resultCode, resultData, resultExtras, resultAbort, true);
12841 }
12842
12843 if (doNext) {
12844 processNextBroadcast(false);
12845 }
12846 trimApplications();
12847
12848 Binder.restoreCallingIdentity(origId);
12849 }
12850
12851 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12852 if (r.nextReceiver > 0) {
12853 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12854 if (curReceiver instanceof BroadcastFilter) {
12855 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012856 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012857 System.identityHashCode(r),
12858 r.intent.getAction(),
12859 r.nextReceiver - 1,
12860 System.identityHashCode(bf));
12861 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012862 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012863 System.identityHashCode(r),
12864 r.intent.getAction(),
12865 r.nextReceiver - 1,
12866 ((ResolveInfo)curReceiver).toString());
12867 }
12868 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012869 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012870 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012871 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012872 System.identityHashCode(r),
12873 r.intent.getAction(),
12874 r.nextReceiver,
12875 "NONE");
12876 }
12877 }
12878
12879 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012880 ProcessRecord app = null;
12881 String anrMessage = null;
12882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012883 synchronized (this) {
12884 if (mOrderedBroadcasts.size() == 0) {
12885 return;
12886 }
12887 long now = SystemClock.uptimeMillis();
12888 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012889 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012890 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012891 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012892 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012893 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012894 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012895 return;
12896 }
12897
Joe Onorato8a9b2202010-02-26 18:56:32 -080012898 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012899 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012900 r.anrCount++;
12901
12902 // Current receiver has passed its expiration date.
12903 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012904 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012905 return;
12906 }
12907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012908 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012909 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012910 logBroadcastReceiverDiscard(r);
12911 if (curReceiver instanceof BroadcastFilter) {
12912 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12913 if (bf.receiverList.pid != 0
12914 && bf.receiverList.pid != MY_PID) {
12915 synchronized (this.mPidsSelfLocked) {
12916 app = this.mPidsSelfLocked.get(
12917 bf.receiverList.pid);
12918 }
12919 }
12920 } else {
12921 app = r.curApp;
12922 }
12923
12924 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012925 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012926 }
12927
12928 if (mPendingBroadcast == r) {
12929 mPendingBroadcast = null;
12930 }
12931
12932 // Move on to the next receiver.
12933 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12934 r.resultExtras, r.resultAbort, true);
12935 scheduleBroadcastsLocked();
12936 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012937
12938 if (anrMessage != null) {
12939 appNotResponding(app, null, null, anrMessage);
12940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012941 }
12942
12943 private final void processCurBroadcastLocked(BroadcastRecord r,
12944 ProcessRecord app) throws RemoteException {
12945 if (app.thread == null) {
12946 throw new RemoteException();
12947 }
12948 r.receiver = app.thread.asBinder();
12949 r.curApp = app;
12950 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012951 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012952
12953 // Tell the application to launch this receiver.
12954 r.intent.setComponent(r.curComponent);
12955
12956 boolean started = false;
12957 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012958 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012959 "Delivering to component " + r.curComponent
12960 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012961 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012962 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12963 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12964 started = true;
12965 } finally {
12966 if (!started) {
12967 r.receiver = null;
12968 r.curApp = null;
12969 app.curReceiver = null;
12970 }
12971 }
12972
12973 }
12974
12975 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012976 Intent intent, int resultCode, String data, Bundle extras,
12977 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012978 if (app != null && app.thread != null) {
12979 // If we have an app thread, do the call through that so it is
12980 // correctly ordered with other one-way calls.
12981 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012982 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012983 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012984 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012985 }
12986 }
12987
12988 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12989 BroadcastFilter filter, boolean ordered) {
12990 boolean skip = false;
12991 if (filter.requiredPermission != null) {
12992 int perm = checkComponentPermission(filter.requiredPermission,
12993 r.callingPid, r.callingUid, -1);
12994 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012995 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012996 + r.intent.toString()
12997 + " from " + r.callerPackage + " (pid="
12998 + r.callingPid + ", uid=" + r.callingUid + ")"
12999 + " requires " + filter.requiredPermission
13000 + " due to registered receiver " + filter);
13001 skip = true;
13002 }
13003 }
13004 if (r.requiredPermission != null) {
13005 int perm = checkComponentPermission(r.requiredPermission,
13006 filter.receiverList.pid, filter.receiverList.uid, -1);
13007 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013008 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013009 + r.intent.toString()
13010 + " to " + filter.receiverList.app
13011 + " (pid=" + filter.receiverList.pid
13012 + ", uid=" + filter.receiverList.uid + ")"
13013 + " requires " + r.requiredPermission
13014 + " due to sender " + r.callerPackage
13015 + " (uid " + r.callingUid + ")");
13016 skip = true;
13017 }
13018 }
13019
13020 if (!skip) {
13021 // If this is not being sent as an ordered broadcast, then we
13022 // don't want to touch the fields that keep track of the current
13023 // state of ordered broadcasts.
13024 if (ordered) {
13025 r.receiver = filter.receiverList.receiver.asBinder();
13026 r.curFilter = filter;
13027 filter.receiverList.curBroadcast = r;
13028 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013029 if (filter.receiverList.app != null) {
13030 // Bump hosting application to no longer be in background
13031 // scheduling class. Note that we can't do that if there
13032 // isn't an app... but we can only be in that case for
13033 // things that directly call the IActivityManager API, which
13034 // are already core system stuff so don't matter for this.
13035 r.curApp = filter.receiverList.app;
13036 filter.receiverList.app.curReceiver = r;
13037 updateOomAdjLocked();
13038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013039 }
13040 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013041 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013042 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013043 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013044 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013045 }
13046 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13047 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013048 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013049 if (ordered) {
13050 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13051 }
13052 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013053 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013054 if (ordered) {
13055 r.receiver = null;
13056 r.curFilter = null;
13057 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013058 if (filter.receiverList.app != null) {
13059 filter.receiverList.app.curReceiver = null;
13060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013061 }
13062 }
13063 }
13064 }
13065
Dianne Hackborn12527f92009-11-11 17:39:50 -080013066 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13067 if (r.callingUid < 0) {
13068 // This was from a registerReceiver() call; ignore it.
13069 return;
13070 }
13071 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13072 MAX_BROADCAST_HISTORY-1);
13073 r.finishTime = SystemClock.uptimeMillis();
13074 mBroadcastHistory[0] = r;
13075 }
13076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013077 private final void processNextBroadcast(boolean fromMsg) {
13078 synchronized(this) {
13079 BroadcastRecord r;
13080
Joe Onorato8a9b2202010-02-26 18:56:32 -080013081 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013082 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013083 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013084
13085 updateCpuStats();
13086
13087 if (fromMsg) {
13088 mBroadcastsScheduled = false;
13089 }
13090
13091 // First, deliver any non-serialized broadcasts right away.
13092 while (mParallelBroadcasts.size() > 0) {
13093 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013094 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013095 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013096 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013097 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013098 for (int i=0; i<N; i++) {
13099 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013100 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013101 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013102 + target + ": " + r);
13103 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13104 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013105 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013106 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013107 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013108 }
13109
13110 // Now take care of the next serialized one...
13111
13112 // If we are waiting for a process to come up to handle the next
13113 // broadcast, then do nothing at this point. Just in case, we
13114 // check that the process we're waiting for still exists.
13115 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013116 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013117 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013118 + mPendingBroadcast.curApp);
13119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013120
13121 boolean isDead;
13122 synchronized (mPidsSelfLocked) {
13123 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13124 }
13125 if (!isDead) {
13126 // It's still alive, so keep waiting
13127 return;
13128 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013129 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013130 + " died before responding to broadcast");
13131 mPendingBroadcast = null;
13132 }
13133 }
13134
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013135 boolean looped = false;
13136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013137 do {
13138 if (mOrderedBroadcasts.size() == 0) {
13139 // No more broadcasts pending, so all done!
13140 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013141 if (looped) {
13142 // If we had finished the last ordered broadcast, then
13143 // make sure all processes have correct oom and sched
13144 // adjustments.
13145 updateOomAdjLocked();
13146 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013147 return;
13148 }
13149 r = mOrderedBroadcasts.get(0);
13150 boolean forceReceive = false;
13151
13152 // Ensure that even if something goes awry with the timeout
13153 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013154 // and continue to make progress.
13155 //
13156 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
13157 // receivers don't get executed with with timeouts. They're intended for
13158 // one time heavy lifting after system upgrades and can take
13159 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013160 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013161 if (mSystemReady && r.dispatchTime > 0) {
13162 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013163 if ((numReceivers > 0) &&
13164 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013165 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013166 + " now=" + now
13167 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013168 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013169 + " intent=" + r.intent
13170 + " numReceivers=" + numReceivers
13171 + " nextReceiver=" + r.nextReceiver
13172 + " state=" + r.state);
13173 broadcastTimeout(); // forcibly finish this broadcast
13174 forceReceive = true;
13175 r.state = BroadcastRecord.IDLE;
13176 }
13177 }
13178
13179 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013180 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013181 "processNextBroadcast() called when not idle (state="
13182 + r.state + ")");
13183 return;
13184 }
13185
13186 if (r.receivers == null || r.nextReceiver >= numReceivers
13187 || r.resultAbort || forceReceive) {
13188 // No more receivers for this broadcast! Send the final
13189 // result if requested...
13190 if (r.resultTo != null) {
13191 try {
13192 if (DEBUG_BROADCAST) {
13193 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013194 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013195 + " seq=" + seq + " app=" + r.callerApp);
13196 }
13197 performReceive(r.callerApp, r.resultTo,
13198 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013199 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013200 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013201 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013202 }
13203 }
13204
Joe Onorato8a9b2202010-02-26 18:56:32 -080013205 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013206 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13207
Joe Onorato8a9b2202010-02-26 18:56:32 -080013208 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013209 + r);
13210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013211 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013212 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013213 mOrderedBroadcasts.remove(0);
13214 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013215 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013216 continue;
13217 }
13218 } while (r == null);
13219
13220 // Get the next receiver...
13221 int recIdx = r.nextReceiver++;
13222
13223 // Keep track of when this receiver started, and make sure there
13224 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013225 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013226 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013227 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013228
Joe Onorato8a9b2202010-02-26 18:56:32 -080013229 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013230 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013231 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013232 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013233 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013234 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013235 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013236 }
13237
13238 Object nextReceiver = r.receivers.get(recIdx);
13239 if (nextReceiver instanceof BroadcastFilter) {
13240 // Simple case: this is a registered receiver who gets
13241 // a direct call.
13242 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013243 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013244 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013245 + filter + ": " + r);
13246 deliverToRegisteredReceiver(r, filter, r.ordered);
13247 if (r.receiver == null || !r.ordered) {
13248 // The receiver has already finished, so schedule to
13249 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013250 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13251 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013252 r.state = BroadcastRecord.IDLE;
13253 scheduleBroadcastsLocked();
13254 }
13255 return;
13256 }
13257
13258 // Hard case: need to instantiate the receiver, possibly
13259 // starting its application process to host it.
13260
13261 ResolveInfo info =
13262 (ResolveInfo)nextReceiver;
13263
13264 boolean skip = false;
13265 int perm = checkComponentPermission(info.activityInfo.permission,
13266 r.callingPid, r.callingUid,
13267 info.activityInfo.exported
13268 ? -1 : info.activityInfo.applicationInfo.uid);
13269 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013270 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013271 + r.intent.toString()
13272 + " from " + r.callerPackage + " (pid=" + r.callingPid
13273 + ", uid=" + r.callingUid + ")"
13274 + " requires " + info.activityInfo.permission
13275 + " due to receiver " + info.activityInfo.packageName
13276 + "/" + info.activityInfo.name);
13277 skip = true;
13278 }
13279 if (r.callingUid != Process.SYSTEM_UID &&
13280 r.requiredPermission != null) {
13281 try {
13282 perm = ActivityThread.getPackageManager().
13283 checkPermission(r.requiredPermission,
13284 info.activityInfo.applicationInfo.packageName);
13285 } catch (RemoteException e) {
13286 perm = PackageManager.PERMISSION_DENIED;
13287 }
13288 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013289 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013290 + r.intent + " to "
13291 + info.activityInfo.applicationInfo.packageName
13292 + " requires " + r.requiredPermission
13293 + " due to sender " + r.callerPackage
13294 + " (uid " + r.callingUid + ")");
13295 skip = true;
13296 }
13297 }
13298 if (r.curApp != null && r.curApp.crashing) {
13299 // If the target process is crashing, just skip it.
13300 skip = true;
13301 }
13302
13303 if (skip) {
13304 r.receiver = null;
13305 r.curFilter = null;
13306 r.state = BroadcastRecord.IDLE;
13307 scheduleBroadcastsLocked();
13308 return;
13309 }
13310
13311 r.state = BroadcastRecord.APP_RECEIVE;
13312 String targetProcess = info.activityInfo.processName;
13313 r.curComponent = new ComponentName(
13314 info.activityInfo.applicationInfo.packageName,
13315 info.activityInfo.name);
13316 r.curReceiver = info.activityInfo;
13317
13318 // Is this receiver's application already running?
13319 ProcessRecord app = getProcessRecordLocked(targetProcess,
13320 info.activityInfo.applicationInfo.uid);
13321 if (app != null && app.thread != null) {
13322 try {
13323 processCurBroadcastLocked(r, app);
13324 return;
13325 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013326 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013327 + r.curComponent, e);
13328 }
13329
13330 // If a dead object exception was thrown -- fall through to
13331 // restart the application.
13332 }
13333
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013334 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013335 if ((r.curApp=startProcessLocked(targetProcess,
13336 info.activityInfo.applicationInfo, true,
13337 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013338 "broadcast", r.curComponent,
13339 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13340 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013341 // Ah, this recipient is unavailable. Finish it if necessary,
13342 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013343 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013344 + info.activityInfo.applicationInfo.packageName + "/"
13345 + info.activityInfo.applicationInfo.uid + " for broadcast "
13346 + r.intent + ": process is bad");
13347 logBroadcastReceiverDiscard(r);
13348 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13349 r.resultExtras, r.resultAbort, true);
13350 scheduleBroadcastsLocked();
13351 r.state = BroadcastRecord.IDLE;
13352 return;
13353 }
13354
13355 mPendingBroadcast = r;
13356 }
13357 }
13358
13359 // =========================================================
13360 // INSTRUMENTATION
13361 // =========================================================
13362
13363 public boolean startInstrumentation(ComponentName className,
13364 String profileFile, int flags, Bundle arguments,
13365 IInstrumentationWatcher watcher) {
13366 // Refuse possible leaked file descriptors
13367 if (arguments != null && arguments.hasFileDescriptors()) {
13368 throw new IllegalArgumentException("File descriptors passed in Bundle");
13369 }
13370
13371 synchronized(this) {
13372 InstrumentationInfo ii = null;
13373 ApplicationInfo ai = null;
13374 try {
13375 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013376 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013377 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013378 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013379 } catch (PackageManager.NameNotFoundException e) {
13380 }
13381 if (ii == null) {
13382 reportStartInstrumentationFailure(watcher, className,
13383 "Unable to find instrumentation info for: " + className);
13384 return false;
13385 }
13386 if (ai == null) {
13387 reportStartInstrumentationFailure(watcher, className,
13388 "Unable to find instrumentation target package: " + ii.targetPackage);
13389 return false;
13390 }
13391
13392 int match = mContext.getPackageManager().checkSignatures(
13393 ii.targetPackage, ii.packageName);
13394 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13395 String msg = "Permission Denial: starting instrumentation "
13396 + className + " from pid="
13397 + Binder.getCallingPid()
13398 + ", uid=" + Binder.getCallingPid()
13399 + " not allowed because package " + ii.packageName
13400 + " does not have a signature matching the target "
13401 + ii.targetPackage;
13402 reportStartInstrumentationFailure(watcher, className, msg);
13403 throw new SecurityException(msg);
13404 }
13405
13406 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013407 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013408 ProcessRecord app = addAppLocked(ai);
13409 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013410 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013411 app.instrumentationProfileFile = profileFile;
13412 app.instrumentationArguments = arguments;
13413 app.instrumentationWatcher = watcher;
13414 app.instrumentationResultClass = className;
13415 Binder.restoreCallingIdentity(origId);
13416 }
13417
13418 return true;
13419 }
13420
13421 /**
13422 * Report errors that occur while attempting to start Instrumentation. Always writes the
13423 * error to the logs, but if somebody is watching, send the report there too. This enables
13424 * the "am" command to report errors with more information.
13425 *
13426 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13427 * @param cn The component name of the instrumentation.
13428 * @param report The error report.
13429 */
13430 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13431 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013432 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013433 try {
13434 if (watcher != null) {
13435 Bundle results = new Bundle();
13436 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13437 results.putString("Error", report);
13438 watcher.instrumentationStatus(cn, -1, results);
13439 }
13440 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013441 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013442 }
13443 }
13444
13445 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13446 if (app.instrumentationWatcher != null) {
13447 try {
13448 // NOTE: IInstrumentationWatcher *must* be oneway here
13449 app.instrumentationWatcher.instrumentationFinished(
13450 app.instrumentationClass,
13451 resultCode,
13452 results);
13453 } catch (RemoteException e) {
13454 }
13455 }
13456 app.instrumentationWatcher = null;
13457 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013458 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013459 app.instrumentationProfileFile = null;
13460 app.instrumentationArguments = null;
13461
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013462 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013463 }
13464
13465 public void finishInstrumentation(IApplicationThread target,
13466 int resultCode, Bundle results) {
13467 // Refuse possible leaked file descriptors
13468 if (results != null && results.hasFileDescriptors()) {
13469 throw new IllegalArgumentException("File descriptors passed in Intent");
13470 }
13471
13472 synchronized(this) {
13473 ProcessRecord app = getRecordForAppLocked(target);
13474 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013475 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013476 return;
13477 }
13478 final long origId = Binder.clearCallingIdentity();
13479 finishInstrumentationLocked(app, resultCode, results);
13480 Binder.restoreCallingIdentity(origId);
13481 }
13482 }
13483
13484 // =========================================================
13485 // CONFIGURATION
13486 // =========================================================
13487
13488 public ConfigurationInfo getDeviceConfigurationInfo() {
13489 ConfigurationInfo config = new ConfigurationInfo();
13490 synchronized (this) {
13491 config.reqTouchScreen = mConfiguration.touchscreen;
13492 config.reqKeyboardType = mConfiguration.keyboard;
13493 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013494 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13495 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013496 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13497 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013498 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13499 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013500 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13501 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013502 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013503 }
13504 return config;
13505 }
13506
13507 public Configuration getConfiguration() {
13508 Configuration ci;
13509 synchronized(this) {
13510 ci = new Configuration(mConfiguration);
13511 }
13512 return ci;
13513 }
13514
13515 public void updateConfiguration(Configuration values) {
13516 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13517 "updateConfiguration()");
13518
13519 synchronized(this) {
13520 if (values == null && mWindowManager != null) {
13521 // sentinel: fetch the current configuration from the window manager
13522 values = mWindowManager.computeNewConfiguration();
13523 }
13524
13525 final long origId = Binder.clearCallingIdentity();
13526 updateConfigurationLocked(values, null);
13527 Binder.restoreCallingIdentity(origId);
13528 }
13529 }
13530
13531 /**
13532 * Do either or both things: (1) change the current configuration, and (2)
13533 * make sure the given activity is running with the (now) current
13534 * configuration. Returns true if the activity has been left running, or
13535 * false if <var>starting</var> is being destroyed to match the new
13536 * configuration.
13537 */
13538 public boolean updateConfigurationLocked(Configuration values,
13539 HistoryRecord starting) {
13540 int changes = 0;
13541
13542 boolean kept = true;
13543
13544 if (values != null) {
13545 Configuration newConfig = new Configuration(mConfiguration);
13546 changes = newConfig.updateFrom(values);
13547 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013548 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013549 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013550 }
13551
Doug Zongker2bec3d42009-12-04 12:52:44 -080013552 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013553
13554 if (values.locale != null) {
13555 saveLocaleLocked(values.locale,
13556 !values.locale.equals(mConfiguration.locale),
13557 values.userSetLocale);
13558 }
13559
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013560 mConfigurationSeq++;
13561 if (mConfigurationSeq <= 0) {
13562 mConfigurationSeq = 1;
13563 }
13564 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013565 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013566 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013567
13568 AttributeCache ac = AttributeCache.instance();
13569 if (ac != null) {
13570 ac.updateConfiguration(mConfiguration);
13571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013572
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013573 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13574 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13575 msg.obj = new Configuration(mConfiguration);
13576 mHandler.sendMessage(msg);
13577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013578
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013579 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13580 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013581 try {
13582 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013583 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013584 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013585 app.thread.scheduleConfigurationChanged(mConfiguration);
13586 }
13587 } catch (Exception e) {
13588 }
13589 }
13590 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013591 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13592 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013593 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13594 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013595 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13596 broadcastIntentLocked(null, null,
13597 new Intent(Intent.ACTION_LOCALE_CHANGED),
13598 null, null, 0, null, null,
13599 null, false, false, MY_PID, Process.SYSTEM_UID);
13600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013601 }
13602 }
13603
13604 if (changes != 0 && starting == null) {
13605 // If the configuration changed, and the caller is not already
13606 // in the process of starting an activity, then find the top
13607 // activity to check if its configuration needs to change.
13608 starting = topRunningActivityLocked(null);
13609 }
13610
13611 if (starting != null) {
13612 kept = ensureActivityConfigurationLocked(starting, changes);
13613 if (kept) {
13614 // If this didn't result in the starting activity being
13615 // destroyed, then we need to make sure at this point that all
13616 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013617 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013618 + ", ensuring others are correct.");
13619 ensureActivitiesVisibleLocked(starting, changes);
13620 }
13621 }
13622
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013623 if (values != null && mWindowManager != null) {
13624 mWindowManager.setNewConfiguration(mConfiguration);
13625 }
13626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013627 return kept;
13628 }
13629
13630 private final boolean relaunchActivityLocked(HistoryRecord r,
13631 int changes, boolean andResume) {
13632 List<ResultInfo> results = null;
13633 List<Intent> newIntents = null;
13634 if (andResume) {
13635 results = r.results;
13636 newIntents = r.newIntents;
13637 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013638 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013639 + " with results=" + results + " newIntents=" + newIntents
13640 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013641 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13642 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013643 r.task.taskId, r.shortComponentName);
13644
13645 r.startFreezingScreenLocked(r.app, 0);
13646
13647 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013648 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013649 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013650 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013651 // Note: don't need to call pauseIfSleepingLocked() here, because
13652 // the caller will only pass in 'andResume' if this activity is
13653 // currently resumed, which implies we aren't sleeping.
13654 } catch (RemoteException e) {
13655 return false;
13656 }
13657
13658 if (andResume) {
13659 r.results = null;
13660 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013661 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013662 }
13663
13664 return true;
13665 }
13666
13667 /**
13668 * Make sure the given activity matches the current configuration. Returns
13669 * false if the activity had to be destroyed. Returns true if the
13670 * configuration is the same, or the activity will remain running as-is
13671 * for whatever reason. Ensures the HistoryRecord is updated with the
13672 * correct configuration and all other bookkeeping is handled.
13673 */
13674 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13675 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013676 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013677 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13678 "Skipping config check (will change): " + r);
13679 return true;
13680 }
13681
Joe Onorato8a9b2202010-02-26 18:56:32 -080013682 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013683 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013684
13685 // Short circuit: if the two configurations are the exact same
13686 // object (the common case), then there is nothing to do.
13687 Configuration newConfig = mConfiguration;
13688 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013689 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013690 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013691 return true;
13692 }
13693
13694 // We don't worry about activities that are finishing.
13695 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013696 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013697 "Configuration doesn't matter in finishing " + r);
13698 r.stopFreezingScreenLocked(false);
13699 return true;
13700 }
13701
13702 // Okay we now are going to make this activity have the new config.
13703 // But then we need to figure out how it needs to deal with that.
13704 Configuration oldConfig = r.configuration;
13705 r.configuration = newConfig;
13706
13707 // If the activity isn't currently running, just leave the new
13708 // configuration and it will pick that up next time it starts.
13709 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013710 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013711 "Configuration doesn't matter not running " + r);
13712 r.stopFreezingScreenLocked(false);
13713 return true;
13714 }
13715
13716 // If the activity isn't persistent, there is a chance we will
13717 // need to restart it.
13718 if (!r.persistent) {
13719
13720 // Figure out what has changed between the two configurations.
13721 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013722 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013723 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013724 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013725 + Integer.toHexString(r.info.configChanges)
13726 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013727 }
13728 if ((changes&(~r.info.configChanges)) != 0) {
13729 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13730 r.configChangeFlags |= changes;
13731 r.startFreezingScreenLocked(r.app, globalChanges);
13732 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013733 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013734 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013735 destroyActivityLocked(r, true);
13736 } else if (r.state == ActivityState.PAUSING) {
13737 // A little annoying: we are waiting for this activity to
13738 // finish pausing. Let's not do anything now, but just
13739 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013740 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013741 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013742 r.configDestroy = true;
13743 return true;
13744 } else if (r.state == ActivityState.RESUMED) {
13745 // Try to optimize this case: the configuration is changing
13746 // and we need to restart the top, resumed activity.
13747 // Instead of doing the normal handshaking, just say
13748 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013749 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013750 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013751 relaunchActivityLocked(r, r.configChangeFlags, true);
13752 r.configChangeFlags = 0;
13753 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013754 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013755 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013756 relaunchActivityLocked(r, r.configChangeFlags, false);
13757 r.configChangeFlags = 0;
13758 }
13759
13760 // All done... tell the caller we weren't able to keep this
13761 // activity around.
13762 return false;
13763 }
13764 }
13765
13766 // Default case: the activity can handle this new configuration, so
13767 // hand it over. Note that we don't need to give it the new
13768 // configuration, since we always send configuration changes to all
13769 // process when they happen so it can just use whatever configuration
13770 // it last got.
13771 if (r.app != null && r.app.thread != null) {
13772 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013773 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013774 r.app.thread.scheduleActivityConfigurationChanged(r);
13775 } catch (RemoteException e) {
13776 // If process died, whatever.
13777 }
13778 }
13779 r.stopFreezingScreenLocked(false);
13780
13781 return true;
13782 }
13783
13784 /**
13785 * Save the locale. You must be inside a synchronized (this) block.
13786 */
13787 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13788 if(isDiff) {
13789 SystemProperties.set("user.language", l.getLanguage());
13790 SystemProperties.set("user.region", l.getCountry());
13791 }
13792
13793 if(isPersist) {
13794 SystemProperties.set("persist.sys.language", l.getLanguage());
13795 SystemProperties.set("persist.sys.country", l.getCountry());
13796 SystemProperties.set("persist.sys.localevar", l.getVariant());
13797 }
13798 }
13799
13800 // =========================================================
13801 // LIFETIME MANAGEMENT
13802 // =========================================================
13803
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013804 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13805 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013806 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013807 // This adjustment has already been computed. If we are calling
13808 // from the top, we may have already computed our adjustment with
13809 // an earlier hidden adjustment that isn't really for us... if
13810 // so, use the new hidden adjustment.
13811 if (!recursed && app.hidden) {
13812 app.curAdj = hiddenAdj;
13813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013814 return app.curAdj;
13815 }
13816
13817 if (app.thread == null) {
13818 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013819 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013820 return (app.curAdj=EMPTY_APP_ADJ);
13821 }
13822
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013823 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13824 // The max adjustment doesn't allow this app to be anything
13825 // below foreground, so it is not worth doing work for it.
13826 app.adjType = "fixed";
13827 app.adjSeq = mAdjSeq;
13828 app.curRawAdj = app.maxAdj;
13829 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13830 return (app.curAdj=app.maxAdj);
13831 }
13832
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013833 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013834 app.adjSource = null;
13835 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013836 app.empty = false;
13837 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013838
The Android Open Source Project4df24232009-03-05 14:34:35 -080013839 // Determine the importance of the process, starting with most
13840 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013841 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013842 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013843 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013844 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013845 // The last app on the list is the foreground app.
13846 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013847 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013848 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013849 } else if (app.instrumentationClass != null) {
13850 // Don't want to kill running instrumentation.
13851 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013852 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013853 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013854 } else if (app.persistentActivities > 0) {
13855 // Special persistent activities... shouldn't be used these days.
13856 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013857 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013858 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013859 } else if (app.curReceiver != null ||
13860 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13861 // An app that is currently receiving a broadcast also
13862 // counts as being in the foreground.
13863 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013864 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013865 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013866 } else if (app.executingServices.size() > 0) {
13867 // An app that is currently executing a service callback also
13868 // counts as being in the foreground.
13869 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013870 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013871 app.adjType = "exec-service";
13872 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013873 // The user is aware of this app, so make it visible.
13874 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013875 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013876 app.adjType = "foreground-service";
13877 } else if (app.forcingToForeground != null) {
13878 // The user is aware of this app, so make it visible.
13879 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013880 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013881 app.adjType = "force-foreground";
13882 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013883 } else if (app == mHomeProcess) {
13884 // This process is hosting what we currently consider to be the
13885 // home app, so we don't want to let it go into the background.
13886 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013887 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013888 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013889 } else if ((N=app.activities.size()) != 0) {
13890 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013891 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013892 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013893 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013894 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013895 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013896 for (int j=0; j<N; j++) {
13897 if (((HistoryRecord)app.activities.get(j)).visible) {
13898 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013899 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013900 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013901 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013902 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013903 break;
13904 }
13905 }
13906 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013907 // A very not-needed process. If this is lower in the lru list,
13908 // we will push it in to the empty bucket.
13909 app.hidden = true;
13910 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013911 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013912 adj = hiddenAdj;
13913 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013914 }
13915
Joe Onorato8a9b2202010-02-26 18:56:32 -080013916 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013917
The Android Open Source Project4df24232009-03-05 14:34:35 -080013918 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013919 // there are applications dependent on our services or providers, but
13920 // this gives us a baseline and makes sure we don't get into an
13921 // infinite recursion.
13922 app.adjSeq = mAdjSeq;
13923 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013924
Christopher Tate6fa95972009-06-05 18:43:55 -070013925 if (mBackupTarget != null && app == mBackupTarget.app) {
13926 // If possible we want to avoid killing apps while they're being backed up
13927 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013928 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013929 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013930 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013931 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013932 }
13933 }
13934
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013935 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13936 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013937 final long now = SystemClock.uptimeMillis();
13938 // This process is more important if the top activity is
13939 // bound to the service.
13940 Iterator jt = app.services.iterator();
13941 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13942 ServiceRecord s = (ServiceRecord)jt.next();
13943 if (s.startRequested) {
13944 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13945 // This service has seen some activity within
13946 // recent memory, so we will keep its process ahead
13947 // of the background processes.
13948 if (adj > SECONDARY_SERVER_ADJ) {
13949 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013950 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013951 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013952 }
13953 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013954 // If we have let the service slide into the background
13955 // state, still have some text describing what it is doing
13956 // even though the service no longer has an impact.
13957 if (adj > SECONDARY_SERVER_ADJ) {
13958 app.adjType = "started-bg-services";
13959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013960 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013961 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13962 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013963 Iterator<ConnectionRecord> kt
13964 = s.connections.values().iterator();
13965 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13966 // XXX should compute this based on the max of
13967 // all connected clients.
13968 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013969 if (cr.binding.client == app) {
13970 // Binding to ourself is not interesting.
13971 continue;
13972 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013973 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13974 ProcessRecord client = cr.binding.client;
13975 int myHiddenAdj = hiddenAdj;
13976 if (myHiddenAdj > client.hiddenAdj) {
13977 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13978 myHiddenAdj = client.hiddenAdj;
13979 } else {
13980 myHiddenAdj = VISIBLE_APP_ADJ;
13981 }
13982 }
13983 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013984 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013985 if (adj > clientAdj) {
13986 adj = clientAdj > VISIBLE_APP_ADJ
13987 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013988 if (!client.hidden) {
13989 app.hidden = false;
13990 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013991 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013992 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13993 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013994 app.adjSource = cr.binding.client;
13995 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013996 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013997 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13998 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13999 schedGroup = Process.THREAD_GROUP_DEFAULT;
14000 }
14001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014002 }
14003 HistoryRecord a = cr.activity;
14004 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014005 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014006 //}
14007 if (a != null && adj > FOREGROUND_APP_ADJ &&
14008 (a.state == ActivityState.RESUMED
14009 || a.state == ActivityState.PAUSING)) {
14010 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014011 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014012 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014013 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014014 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14015 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014016 app.adjSource = a;
14017 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014018 }
14019 }
14020 }
14021 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014022
14023 // Finally, f this process has active services running in it, we
14024 // would like to avoid killing it unless it would prevent the current
14025 // application from running. By default we put the process in
14026 // with the rest of the background processes; as we scan through
14027 // its services we may bump it up from there.
14028 if (adj > hiddenAdj) {
14029 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014030 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014031 app.adjType = "bg-services";
14032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014033 }
14034
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014035 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
14036 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014037 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014038 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
14039 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014040 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
14041 if (cpr.clients.size() != 0) {
14042 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14043 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14044 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014045 if (client == app) {
14046 // Being our own client is not interesting.
14047 continue;
14048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014049 int myHiddenAdj = hiddenAdj;
14050 if (myHiddenAdj > client.hiddenAdj) {
14051 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14052 myHiddenAdj = client.hiddenAdj;
14053 } else {
14054 myHiddenAdj = FOREGROUND_APP_ADJ;
14055 }
14056 }
14057 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014058 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014059 if (adj > clientAdj) {
14060 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014061 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014062 if (!client.hidden) {
14063 app.hidden = false;
14064 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014065 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014066 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14067 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014068 app.adjSource = client;
14069 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014070 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014071 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14072 schedGroup = Process.THREAD_GROUP_DEFAULT;
14073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014074 }
14075 }
14076 // If the provider has external (non-framework) process
14077 // dependencies, ensure that its adjustment is at least
14078 // FOREGROUND_APP_ADJ.
14079 if (cpr.externals != 0) {
14080 if (adj > FOREGROUND_APP_ADJ) {
14081 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014082 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014083 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014084 app.adjType = "provider";
14085 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014086 }
14087 }
14088 }
14089 }
14090
14091 app.curRawAdj = adj;
14092
Joe Onorato8a9b2202010-02-26 18:56:32 -080014093 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014094 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14095 if (adj > app.maxAdj) {
14096 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014097 if (app.maxAdj <= VISIBLE_APP_ADJ) {
14098 schedGroup = Process.THREAD_GROUP_DEFAULT;
14099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014100 }
14101
14102 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014103 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014105 return adj;
14106 }
14107
14108 /**
14109 * Ask a given process to GC right now.
14110 */
14111 final void performAppGcLocked(ProcessRecord app) {
14112 try {
14113 app.lastRequestedGc = SystemClock.uptimeMillis();
14114 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014115 if (app.reportLowMemory) {
14116 app.reportLowMemory = false;
14117 app.thread.scheduleLowMemory();
14118 } else {
14119 app.thread.processInBackground();
14120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014121 }
14122 } catch (Exception e) {
14123 // whatever.
14124 }
14125 }
14126
14127 /**
14128 * Returns true if things are idle enough to perform GCs.
14129 */
Josh Bartel7f208742010-02-25 11:01:44 -060014130 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014131 return mParallelBroadcasts.size() == 0
14132 && mOrderedBroadcasts.size() == 0
14133 && (mSleeping || (mResumedActivity != null &&
14134 mResumedActivity.idle));
14135 }
14136
14137 /**
14138 * Perform GCs on all processes that are waiting for it, but only
14139 * if things are idle.
14140 */
14141 final void performAppGcsLocked() {
14142 final int N = mProcessesToGc.size();
14143 if (N <= 0) {
14144 return;
14145 }
Josh Bartel7f208742010-02-25 11:01:44 -060014146 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014147 while (mProcessesToGc.size() > 0) {
14148 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014149 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
14150 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14151 <= SystemClock.uptimeMillis()) {
14152 // To avoid spamming the system, we will GC processes one
14153 // at a time, waiting a few seconds between each.
14154 performAppGcLocked(proc);
14155 scheduleAppGcsLocked();
14156 return;
14157 } else {
14158 // It hasn't been long enough since we last GCed this
14159 // process... put it in the list to wait for its time.
14160 addProcessToGcListLocked(proc);
14161 break;
14162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014163 }
14164 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014165
14166 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014167 }
14168 }
14169
14170 /**
14171 * If all looks good, perform GCs on all processes waiting for them.
14172 */
14173 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014174 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014175 performAppGcsLocked();
14176 return;
14177 }
14178 // Still not idle, wait some more.
14179 scheduleAppGcsLocked();
14180 }
14181
14182 /**
14183 * Schedule the execution of all pending app GCs.
14184 */
14185 final void scheduleAppGcsLocked() {
14186 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014187
14188 if (mProcessesToGc.size() > 0) {
14189 // Schedule a GC for the time to the next process.
14190 ProcessRecord proc = mProcessesToGc.get(0);
14191 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14192
14193 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14194 long now = SystemClock.uptimeMillis();
14195 if (when < (now+GC_TIMEOUT)) {
14196 when = now + GC_TIMEOUT;
14197 }
14198 mHandler.sendMessageAtTime(msg, when);
14199 }
14200 }
14201
14202 /**
14203 * Add a process to the array of processes waiting to be GCed. Keeps the
14204 * list in sorted order by the last GC time. The process can't already be
14205 * on the list.
14206 */
14207 final void addProcessToGcListLocked(ProcessRecord proc) {
14208 boolean added = false;
14209 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14210 if (mProcessesToGc.get(i).lastRequestedGc <
14211 proc.lastRequestedGc) {
14212 added = true;
14213 mProcessesToGc.add(i+1, proc);
14214 break;
14215 }
14216 }
14217 if (!added) {
14218 mProcessesToGc.add(0, proc);
14219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014220 }
14221
14222 /**
14223 * Set up to ask a process to GC itself. This will either do it
14224 * immediately, or put it on the list of processes to gc the next
14225 * time things are idle.
14226 */
14227 final void scheduleAppGcLocked(ProcessRecord app) {
14228 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014229 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014230 return;
14231 }
14232 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014233 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014234 scheduleAppGcsLocked();
14235 }
14236 }
14237
14238 private final boolean updateOomAdjLocked(
14239 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14240 app.hiddenAdj = hiddenAdj;
14241
14242 if (app.thread == null) {
14243 return true;
14244 }
14245
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014246 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014247
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014248 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014249 if (app.curRawAdj != app.setRawAdj) {
14250 if (app.curRawAdj > FOREGROUND_APP_ADJ
14251 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14252 // If this app is transitioning from foreground to
14253 // non-foreground, have it do a gc.
14254 scheduleAppGcLocked(app);
14255 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14256 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14257 // Likewise do a gc when an app is moving in to the
14258 // background (such as a service stopping).
14259 scheduleAppGcLocked(app);
14260 }
14261 app.setRawAdj = app.curRawAdj;
14262 }
14263 if (adj != app.setAdj) {
14264 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014265 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014266 TAG, "Set app " + app.processName +
14267 " oom adj to " + adj);
14268 app.setAdj = adj;
14269 } else {
14270 return false;
14271 }
14272 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014273 if (app.setSchedGroup != app.curSchedGroup) {
14274 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014275 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014276 "Setting process group of " + app.processName
14277 + " to " + app.curSchedGroup);
14278 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014279 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014280 try {
14281 Process.setProcessGroup(app.pid, app.curSchedGroup);
14282 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014283 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014284 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014285 e.printStackTrace();
14286 } finally {
14287 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014288 }
14289 }
14290 if (false) {
14291 if (app.thread != null) {
14292 try {
14293 app.thread.setSchedulingGroup(app.curSchedGroup);
14294 } catch (RemoteException e) {
14295 }
14296 }
14297 }
14298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014299 }
14300
14301 return true;
14302 }
14303
14304 private final HistoryRecord resumedAppLocked() {
14305 HistoryRecord resumedActivity = mResumedActivity;
14306 if (resumedActivity == null || resumedActivity.app == null) {
14307 resumedActivity = mPausingActivity;
14308 if (resumedActivity == null || resumedActivity.app == null) {
14309 resumedActivity = topRunningActivityLocked(null);
14310 }
14311 }
14312 return resumedActivity;
14313 }
14314
14315 private final boolean updateOomAdjLocked(ProcessRecord app) {
14316 final HistoryRecord TOP_ACT = resumedAppLocked();
14317 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14318 int curAdj = app.curAdj;
14319 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14320 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14321
14322 mAdjSeq++;
14323
14324 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14325 if (res) {
14326 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14327 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14328 if (nowHidden != wasHidden) {
14329 // Changed to/from hidden state, so apps after it in the LRU
14330 // list may also be changed.
14331 updateOomAdjLocked();
14332 }
14333 }
14334 return res;
14335 }
14336
14337 private final boolean updateOomAdjLocked() {
14338 boolean didOomAdj = true;
14339 final HistoryRecord TOP_ACT = resumedAppLocked();
14340 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14341
14342 if (false) {
14343 RuntimeException e = new RuntimeException();
14344 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014345 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014346 }
14347
14348 mAdjSeq++;
14349
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014350 // Let's determine how many processes we have running vs.
14351 // how many slots we have for background processes; we may want
14352 // to put multiple processes in a slot of there are enough of
14353 // them.
14354 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14355 int factor = (mLruProcesses.size()-4)/numSlots;
14356 if (factor < 1) factor = 1;
14357 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014358 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014360 // First try updating the OOM adjustment for each of the
14361 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014362 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014363 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14364 while (i > 0) {
14365 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014366 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014367 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014368 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014369 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014370 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014371 step++;
14372 if (step >= factor) {
14373 step = 0;
14374 curHiddenAdj++;
14375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014376 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014377 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014378 if (!app.killedBackground) {
14379 numHidden++;
14380 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014381 Slog.i(TAG, "No longer want " + app.processName
14382 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014383 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14384 app.processName, app.setAdj, "too many background");
14385 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014386 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014387 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014388 }
14389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014390 } else {
14391 didOomAdj = false;
14392 }
14393 }
14394
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014395 // If we return false, we will fall back on killing processes to
14396 // have a fixed limit. Do this if a limit has been requested; else
14397 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014398 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14399 }
14400
14401 private final void trimApplications() {
14402 synchronized (this) {
14403 int i;
14404
14405 // First remove any unused application processes whose package
14406 // has been removed.
14407 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14408 final ProcessRecord app = mRemovedProcesses.get(i);
14409 if (app.activities.size() == 0
14410 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014411 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014412 TAG, "Exiting empty application process "
14413 + 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 cleanUpApplicationRecordLocked(app, false, -1);
14426 mRemovedProcesses.remove(i);
14427
14428 if (app.persistent) {
14429 if (app.persistent) {
14430 addAppLocked(app.info);
14431 }
14432 }
14433 }
14434 }
14435
14436 // Now try updating the OOM adjustment for each of the
14437 // application processes based on their current state.
14438 // If the setOomAdj() API is not supported, then go with our
14439 // back-up plan...
14440 if (!updateOomAdjLocked()) {
14441
14442 // Count how many processes are running services.
14443 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014444 for (i=mLruProcesses.size()-1; i>=0; i--) {
14445 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014446
14447 if (app.persistent || app.services.size() != 0
14448 || app.curReceiver != null
14449 || app.persistentActivities > 0) {
14450 // Don't count processes holding services against our
14451 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014452 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014453 TAG, "Not trimming app " + app + " with services: "
14454 + app.services);
14455 numServiceProcs++;
14456 }
14457 }
14458
14459 int curMaxProcs = mProcessLimit;
14460 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14461 if (mAlwaysFinishActivities) {
14462 curMaxProcs = 1;
14463 }
14464 curMaxProcs += numServiceProcs;
14465
14466 // Quit as many processes as we can to get down to the desired
14467 // process count. First remove any processes that no longer
14468 // have activites running in them.
14469 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014470 i<mLruProcesses.size()
14471 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014472 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014473 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014474 // Quit an application only if it is not currently
14475 // running any activities.
14476 if (!app.persistent && app.activities.size() == 0
14477 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014478 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014479 TAG, "Exiting empty application process "
14480 + app.processName + " ("
14481 + (app.thread != null ? app.thread.asBinder() : null)
14482 + ")\n");
14483 if (app.pid > 0 && app.pid != MY_PID) {
14484 Process.killProcess(app.pid);
14485 } else {
14486 try {
14487 app.thread.scheduleExit();
14488 } catch (Exception e) {
14489 // Ignore exceptions.
14490 }
14491 }
14492 // todo: For now we assume the application is not buggy
14493 // or evil, and will quit as a result of our request.
14494 // Eventually we need to drive this off of the death
14495 // notification, and kill the process if it takes too long.
14496 cleanUpApplicationRecordLocked(app, false, i);
14497 i--;
14498 }
14499 }
14500
14501 // If we still have too many processes, now from the least
14502 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014503 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014504 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014505 " of " + curMaxProcs + " processes");
14506 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014507 i<mLruProcesses.size()
14508 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014509 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014510 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014511 // Quit the application only if we have a state saved for
14512 // all of its activities.
14513 boolean canQuit = !app.persistent && app.curReceiver == null
14514 && app.services.size() == 0
14515 && app.persistentActivities == 0;
14516 int NUMA = app.activities.size();
14517 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014518 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014519 TAG, "Looking to quit " + app.processName);
14520 for (j=0; j<NUMA && canQuit; j++) {
14521 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014522 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014523 TAG, " " + r.intent.getComponent().flattenToShortString()
14524 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14525 canQuit = (r.haveState || !r.stateNotNeeded)
14526 && !r.visible && r.stopped;
14527 }
14528 if (canQuit) {
14529 // Finish all of the activities, and then the app itself.
14530 for (j=0; j<NUMA; j++) {
14531 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14532 if (!r.finishing) {
14533 destroyActivityLocked(r, false);
14534 }
14535 r.resultTo = null;
14536 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014537 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014538 + app.processName + " ("
14539 + (app.thread != null ? app.thread.asBinder() : null)
14540 + ")\n");
14541 if (app.pid > 0 && app.pid != MY_PID) {
14542 Process.killProcess(app.pid);
14543 } else {
14544 try {
14545 app.thread.scheduleExit();
14546 } catch (Exception e) {
14547 // Ignore exceptions.
14548 }
14549 }
14550 // todo: For now we assume the application is not buggy
14551 // or evil, and will quit as a result of our request.
14552 // Eventually we need to drive this off of the death
14553 // notification, and kill the process if it takes too long.
14554 cleanUpApplicationRecordLocked(app, false, i);
14555 i--;
14556 //dump();
14557 }
14558 }
14559
14560 }
14561
14562 int curMaxActivities = MAX_ACTIVITIES;
14563 if (mAlwaysFinishActivities) {
14564 curMaxActivities = 1;
14565 }
14566
14567 // Finally, if there are too many activities now running, try to
14568 // finish as many as we can to get back down to the limit.
14569 for ( i=0;
14570 i<mLRUActivities.size()
14571 && mLRUActivities.size() > curMaxActivities;
14572 i++) {
14573 final HistoryRecord r
14574 = (HistoryRecord)mLRUActivities.get(i);
14575
14576 // We can finish this one if we have its icicle saved and
14577 // it is not persistent.
14578 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14579 && r.stopped && !r.persistent && !r.finishing) {
14580 final int origSize = mLRUActivities.size();
14581 destroyActivityLocked(r, true);
14582
14583 // This will remove it from the LRU list, so keep
14584 // our index at the same value. Note that this check to
14585 // see if the size changes is just paranoia -- if
14586 // something unexpected happens, we don't want to end up
14587 // in an infinite loop.
14588 if (origSize > mLRUActivities.size()) {
14589 i--;
14590 }
14591 }
14592 }
14593 }
14594 }
14595
14596 /** This method sends the specified signal to each of the persistent apps */
14597 public void signalPersistentProcesses(int sig) throws RemoteException {
14598 if (sig != Process.SIGNAL_USR1) {
14599 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14600 }
14601
14602 synchronized (this) {
14603 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14604 != PackageManager.PERMISSION_GRANTED) {
14605 throw new SecurityException("Requires permission "
14606 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14607 }
14608
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014609 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14610 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014611 if (r.thread != null && r.persistent) {
14612 Process.sendSignal(r.pid, sig);
14613 }
14614 }
14615 }
14616 }
14617
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014618 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014619 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014620
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014621 try {
14622 synchronized (this) {
14623 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14624 // its own permission.
14625 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14626 != PackageManager.PERMISSION_GRANTED) {
14627 throw new SecurityException("Requires permission "
14628 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014629 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014630
14631 if (start && fd == null) {
14632 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014633 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014634
14635 ProcessRecord proc = null;
14636 try {
14637 int pid = Integer.parseInt(process);
14638 synchronized (mPidsSelfLocked) {
14639 proc = mPidsSelfLocked.get(pid);
14640 }
14641 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014642 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014643
14644 if (proc == null) {
14645 HashMap<String, SparseArray<ProcessRecord>> all
14646 = mProcessNames.getMap();
14647 SparseArray<ProcessRecord> procs = all.get(process);
14648 if (procs != null && procs.size() > 0) {
14649 proc = procs.valueAt(0);
14650 }
14651 }
14652
14653 if (proc == null || proc.thread == null) {
14654 throw new IllegalArgumentException("Unknown process: " + process);
14655 }
14656
14657 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14658 if (isSecure) {
14659 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14660 throw new SecurityException("Process not debuggable: " + proc);
14661 }
14662 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014663
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014664 proc.thread.profilerControl(start, path, fd);
14665 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014666 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014667 }
14668 } catch (RemoteException e) {
14669 throw new IllegalStateException("Process disappeared");
14670 } finally {
14671 if (fd != null) {
14672 try {
14673 fd.close();
14674 } catch (IOException e) {
14675 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014676 }
14677 }
14678 }
14679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014680 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14681 public void monitor() {
14682 synchronized (this) { }
14683 }
14684}