blob: 436bd17d0f80563beeb32ab387000b168f28504b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070020import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.server.IntentResolver;
22import com.android.server.ProcessMap;
23import com.android.server.ProcessStats;
24import com.android.server.SystemServer;
25import com.android.server.Watchdog;
26import com.android.server.WindowManagerService;
27
Dianne Hackborndd71fc82009-12-16 19:24:32 -080028import dalvik.system.Zygote;
29
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.app.Activity;
31import android.app.ActivityManager;
32import android.app.ActivityManagerNative;
33import android.app.ActivityThread;
34import android.app.AlertDialog;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020035import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070037import android.app.IActivityController;
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -080038import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.IActivityWatcher;
40import android.app.IApplicationThread;
41import android.app.IInstrumentationWatcher;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.app.IServiceConnection;
43import android.app.IThumbnailReceiver;
44import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070045import android.app.Notification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.PendingIntent;
47import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070048import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080049import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020050import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080051import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.ComponentName;
53import android.content.ContentResolver;
54import android.content.Context;
55import android.content.Intent;
56import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070057import android.content.IIntentReceiver;
58import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070059import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.content.pm.ActivityInfo;
61import android.content.pm.ApplicationInfo;
62import android.content.pm.ConfigurationInfo;
63import android.content.pm.IPackageDataObserver;
64import android.content.pm.IPackageManager;
65import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080066import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070068import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.content.pm.ProviderInfo;
70import android.content.pm.ResolveInfo;
71import android.content.pm.ServiceInfo;
72import android.content.res.Configuration;
73import android.graphics.Bitmap;
74import android.net.Uri;
75import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080076import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080077import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070078import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080079import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.FileUtils;
83import android.os.Handler;
84import android.os.IBinder;
85import android.os.IPermissionController;
86import android.os.Looper;
87import android.os.Message;
88import android.os.Parcel;
89import android.os.ParcelFileDescriptor;
90import android.os.PowerManager;
91import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070092import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.os.RemoteException;
94import android.os.ServiceManager;
95import android.os.SystemClock;
96import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.util.Config;
99import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800100import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800101import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.PrintWriterPrinter;
103import android.util.SparseArray;
104import android.view.Gravity;
105import android.view.LayoutInflater;
106import android.view.View;
107import android.view.WindowManager;
108import android.view.WindowManagerPolicy;
109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import java.io.File;
111import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200113import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800114import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import java.io.PrintWriter;
116import java.lang.IllegalStateException;
117import java.lang.ref.WeakReference;
118import java.util.ArrayList;
119import java.util.HashMap;
120import java.util.HashSet;
121import java.util.Iterator;
122import java.util.List;
123import java.util.Locale;
124import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700125import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700126import java.util.concurrent.atomic.AtomicBoolean;
127import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128
129public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
130 static final String TAG = "ActivityManager";
131 static final boolean DEBUG = false;
132 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
133 static final boolean DEBUG_SWITCH = localLOGV || false;
134 static final boolean DEBUG_TASKS = localLOGV || false;
135 static final boolean DEBUG_PAUSE = localLOGV || false;
136 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
137 static final boolean DEBUG_TRANSITION = localLOGV || false;
138 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700139 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 static final boolean DEBUG_SERVICE = localLOGV || false;
141 static final boolean DEBUG_VISBILITY = localLOGV || false;
142 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700143 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800144 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700146 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700147 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700148 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 static final boolean VALIDATE_TOKENS = false;
150 static final boolean SHOW_ACTIVITY_START_TIME = true;
151
152 // Control over CPU and battery monitoring.
153 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
154 static final boolean MONITOR_CPU_USAGE = true;
155 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
156 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
157 static final boolean MONITOR_THREAD_CPU_USAGE = false;
158
Dianne Hackborn1655be42009-05-08 14:29:01 -0700159 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700160 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 private static final String SYSTEM_SECURE = "ro.secure";
163
164 // This is the maximum number of application processes we would like
165 // to have running. Due to the asynchronous nature of things, we can
166 // temporarily go beyond this limit.
167 static final int MAX_PROCESSES = 2;
168
169 // Set to false to leave processes running indefinitely, relying on
170 // the kernel killing them as resources are required.
171 static final boolean ENFORCE_PROCESS_LIMIT = false;
172
173 // This is the maximum number of activities that we would like to have
174 // running at a given time.
175 static final int MAX_ACTIVITIES = 20;
176
177 // Maximum number of recent tasks that we can remember.
178 static final int MAX_RECENT_TASKS = 20;
179
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700180 // Amount of time after a call to stopAppSwitches() during which we will
181 // prevent further untrusted switches from happening.
182 static final long APP_SWITCH_DELAY_TIME = 5*1000;
183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 // How long until we reset a task when the user returns to it. Currently
185 // 30 minutes.
186 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
187
188 // Set to true to disable the icon that is shown while a new activity
189 // is being started.
190 static final boolean SHOW_APP_STARTING_ICON = true;
191
192 // How long we wait until giving up on the last activity to pause. This
193 // is short because it directly impacts the responsiveness of starting the
194 // next activity.
195 static final int PAUSE_TIMEOUT = 500;
196
197 /**
198 * How long we can hold the launch wake lock before giving up.
199 */
200 static final int LAUNCH_TIMEOUT = 10*1000;
201
202 // How long we wait for a launched process to attach to the activity manager
203 // before we decide it's never going to come up for real.
204 static final int PROC_START_TIMEOUT = 10*1000;
205
206 // How long we wait until giving up on the last activity telling us it
207 // is idle.
208 static final int IDLE_TIMEOUT = 10*1000;
209
210 // How long to wait after going idle before forcing apps to GC.
211 static final int GC_TIMEOUT = 5*1000;
212
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700213 // The minimum amount of time between successive GC requests for a process.
214 static final int GC_MIN_INTERVAL = 60*1000;
215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 // How long we wait until giving up on an activity telling us it has
217 // finished destroying itself.
218 static final int DESTROY_TIMEOUT = 10*1000;
219
220 // How long we allow a receiver to run before giving up on it.
221 static final int BROADCAST_TIMEOUT = 10*1000;
222
223 // How long we wait for a service to finish executing.
224 static final int SERVICE_TIMEOUT = 20*1000;
225
226 // How long a service needs to be running until restarting its process
227 // is no longer considered to be a relaunch of the service.
228 static final int SERVICE_RESTART_DURATION = 5*1000;
229
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700230 // How long a service needs to be running until it will start back at
231 // SERVICE_RESTART_DURATION after being killed.
232 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
233
234 // Multiplying factor to increase restart duration time by, for each time
235 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
236 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
237
238 // The minimum amount of time between restarting services that we allow.
239 // That is, when multiple services are restarting, we won't allow each
240 // to restart less than this amount of time from the last one.
241 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 // Maximum amount of time for there to be no activity on a service before
244 // we consider it non-essential and allow its process to go on the
245 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700246 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 // How long we wait until we timeout on key dispatching.
249 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
250
251 // The minimum time we allow between crashes, for us to consider this
252 // application to be bad and stop and its services and reject broadcasts.
253 static final int MIN_CRASH_INTERVAL = 60*1000;
254
255 // How long we wait until we timeout on key dispatching during instrumentation.
256 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
257
258 // OOM adjustments for processes in various states:
259
260 // This is a process without anything currently running in it. Definitely
261 // the first to go! Value set in system/rootdir/init.rc on startup.
262 // This value is initalized in the constructor, careful when refering to
263 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800264 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
266 // This is a process only hosting activities that are not visible,
267 // so it can be killed without any disruption. Value set in
268 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 static int HIDDEN_APP_MIN_ADJ;
271
The Android Open Source Project4df24232009-03-05 14:34:35 -0800272 // This is a process holding the home application -- we want to try
273 // avoiding killing it, even if it would normally be in the background,
274 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800276
Christopher Tate6fa95972009-06-05 18:43:55 -0700277 // This is a process currently hosting a backup operation. Killing it
278 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800279 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 // This is a process holding a secondary server -- killing it will not
282 // have much of an impact as far as the user is concerned. Value set in
283 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
286 // This is a process only hosting activities that are visible to the
287 // user, so we'd prefer they don't disappear. Value set in
288 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
291 // This is the process running the current foreground app. We'd really
292 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800293 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294
295 // This is a process running a core server, such as telephony. Definitely
296 // don't want to kill it, but doing so is not completely fatal.
297 static final int CORE_SERVER_ADJ = -12;
298
299 // The system process runs at the default adjustment.
300 static final int SYSTEM_ADJ = -16;
301
302 // Memory pages are 4K.
303 static final int PAGE_SIZE = 4*1024;
304
305 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int EMPTY_APP_MEM;
307 static final int HIDDEN_APP_MEM;
308 static final int HOME_APP_MEM;
309 static final int BACKUP_APP_MEM;
310 static final int SECONDARY_SERVER_MEM;
311 static final int VISIBLE_APP_MEM;
312 static final int FOREGROUND_APP_MEM;
313
314 // The minimum number of hidden apps we want to be able to keep around,
315 // without empty apps being able to push them out of memory.
316 static final int MIN_HIDDEN_APPS = 2;
317
Dianne Hackborn8633e682010-04-22 16:03:41 -0700318 // The maximum number of hidden processes we will keep around before
319 // killing them; this is just a control to not let us go too crazy with
320 // keeping around processes on devices with large amounts of RAM.
321 static final int MAX_HIDDEN_APPS = 15;
322
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800323 // We put empty content processes after any hidden processes that have
324 // been idle for less than 30 seconds.
325 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
326
327 // We put empty content processes after any hidden processes that have
328 // been idle for less than 60 seconds.
329 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
330
331 static {
332 // These values are set in system/rootdir/init.rc on startup.
333 FOREGROUND_APP_ADJ =
334 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
335 VISIBLE_APP_ADJ =
336 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
337 SECONDARY_SERVER_ADJ =
338 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
339 BACKUP_APP_ADJ =
340 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
341 HOME_APP_ADJ =
342 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
343 HIDDEN_APP_MIN_ADJ =
344 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
345 EMPTY_APP_ADJ =
346 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
347 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
348 FOREGROUND_APP_MEM =
349 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
350 VISIBLE_APP_MEM =
351 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
352 SECONDARY_SERVER_MEM =
353 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
354 BACKUP_APP_MEM =
355 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
356 HOME_APP_MEM =
357 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
358 HIDDEN_APP_MEM =
359 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
360 EMPTY_APP_MEM =
361 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
Dan Egnor42471dd2010-01-07 17:25:22 -0800364 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
366 static final String[] EMPTY_STRING_ARRAY = new String[0];
367
368 enum ActivityState {
369 INITIALIZING,
370 RESUMED,
371 PAUSING,
372 PAUSED,
373 STOPPING,
374 STOPPED,
375 FINISHING,
376 DESTROYING,
377 DESTROYED
378 }
379
380 /**
381 * The back history of all previous (and possibly still
382 * running) activities. It contains HistoryRecord objects.
383 */
384 final ArrayList mHistory = new ArrayList();
385
386 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700387 * Description of a request to start a new activity, which has been held
388 * due to app switches being disabled.
389 */
390 class PendingActivityLaunch {
391 HistoryRecord r;
392 HistoryRecord sourceRecord;
393 Uri[] grantedUriPermissions;
394 int grantedMode;
395 boolean onlyIfNeeded;
396 }
397
398 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
399 = new ArrayList<PendingActivityLaunch>();
400
401 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800402 * List of people waiting to find out about the next launched activity.
403 */
404 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
405 = new ArrayList<IActivityManager.WaitResult>();
406
407 /**
408 * List of people waiting to find out about the next visible activity.
409 */
410 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
411 = new ArrayList<IActivityManager.WaitResult>();
412
413 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 * List of all active broadcasts that are to be executed immediately
415 * (without waiting for another broadcast to finish). Currently this only
416 * contains broadcasts to registered receivers, to avoid spinning up
417 * a bunch of processes to execute IntentReceiver components.
418 */
419 final ArrayList<BroadcastRecord> mParallelBroadcasts
420 = new ArrayList<BroadcastRecord>();
421
422 /**
423 * List of all active broadcasts that are to be executed one at a time.
424 * The object at the top of the list is the currently activity broadcasts;
425 * those after it are waiting for the top to finish..
426 */
427 final ArrayList<BroadcastRecord> mOrderedBroadcasts
428 = new ArrayList<BroadcastRecord>();
429
430 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800431 * Historical data of past broadcasts, for debugging.
432 */
433 static final int MAX_BROADCAST_HISTORY = 100;
434 final BroadcastRecord[] mBroadcastHistory
435 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
436
437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * Set when we current have a BROADCAST_INTENT_MSG in flight.
439 */
440 boolean mBroadcastsScheduled = false;
441
442 /**
443 * Set to indicate whether to issue an onUserLeaving callback when a
444 * newly launched activity is being brought in front of us.
445 */
446 boolean mUserLeaving = false;
447
448 /**
449 * When we are in the process of pausing an activity, before starting the
450 * next one, this variable holds the activity that is currently being paused.
451 */
452 HistoryRecord mPausingActivity = null;
453
454 /**
455 * Current activity that is resumed, or null if there is none.
456 */
457 HistoryRecord mResumedActivity = null;
458
459 /**
460 * Activity we have told the window manager to have key focus.
461 */
462 HistoryRecord mFocusedActivity = null;
463
464 /**
465 * This is the last activity that we put into the paused state. This is
466 * used to determine if we need to do an activity transition while sleeping,
467 * when we normally hold the top activity paused.
468 */
469 HistoryRecord mLastPausedActivity = null;
470
471 /**
472 * List of activities that are waiting for a new activity
473 * to become visible before completing whatever operation they are
474 * supposed to do.
475 */
476 final ArrayList mWaitingVisibleActivities = new ArrayList();
477
478 /**
479 * List of activities that are ready to be stopped, but waiting
480 * for the next activity to settle down before doing so. It contains
481 * HistoryRecord objects.
482 */
483 final ArrayList<HistoryRecord> mStoppingActivities
484 = new ArrayList<HistoryRecord>();
485
486 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700487 * Animations that for the current transition have requested not to
488 * be considered for the transition animation.
489 */
490 final ArrayList<HistoryRecord> mNoAnimActivities
491 = new ArrayList<HistoryRecord>();
492
493 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 * List of intents that were used to start the most recent tasks.
495 */
496 final ArrayList<TaskRecord> mRecentTasks
497 = new ArrayList<TaskRecord>();
498
499 /**
500 * List of activities that are ready to be finished, but waiting
501 * for the previous activity to settle down before doing so. It contains
502 * HistoryRecord objects.
503 */
504 final ArrayList mFinishingActivities = new ArrayList();
505
506 /**
507 * All of the applications we currently have running organized by name.
508 * The keys are strings of the application package name (as
509 * returned by the package manager), and the keys are ApplicationRecord
510 * objects.
511 */
512 final ProcessMap<ProcessRecord> mProcessNames
513 = new ProcessMap<ProcessRecord>();
514
515 /**
516 * The last time that various processes have crashed.
517 */
518 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
519
520 /**
521 * Set of applications that we consider to be bad, and will reject
522 * incoming broadcasts from (which the user has no control over).
523 * Processes are added to this set when they have crashed twice within
524 * a minimum amount of time; they are removed from it when they are
525 * later restarted (hopefully due to some user action). The value is the
526 * time it was added to the list.
527 */
528 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
529
530 /**
531 * All of the processes we currently have running organized by pid.
532 * The keys are the pid running the application.
533 *
534 * <p>NOTE: This object is protected by its own lock, NOT the global
535 * activity manager lock!
536 */
537 final SparseArray<ProcessRecord> mPidsSelfLocked
538 = new SparseArray<ProcessRecord>();
539
540 /**
541 * All of the processes that have been forced to be foreground. The key
542 * is the pid of the caller who requested it (we hold a death
543 * link on it).
544 */
545 abstract class ForegroundToken implements IBinder.DeathRecipient {
546 int pid;
547 IBinder token;
548 }
549 final SparseArray<ForegroundToken> mForegroundProcesses
550 = new SparseArray<ForegroundToken>();
551
552 /**
553 * List of records for processes that someone had tried to start before the
554 * system was ready. We don't start them at that point, but ensure they
555 * are started by the time booting is complete.
556 */
557 final ArrayList<ProcessRecord> mProcessesOnHold
558 = new ArrayList<ProcessRecord>();
559
560 /**
561 * List of records for processes that we have started and are waiting
562 * for them to call back. This is really only needed when running in
563 * single processes mode, in which case we do not have a unique pid for
564 * each process.
565 */
566 final ArrayList<ProcessRecord> mStartingProcesses
567 = new ArrayList<ProcessRecord>();
568
569 /**
570 * List of persistent applications that are in the process
571 * of being started.
572 */
573 final ArrayList<ProcessRecord> mPersistentStartingProcesses
574 = new ArrayList<ProcessRecord>();
575
576 /**
577 * Processes that are being forcibly torn down.
578 */
579 final ArrayList<ProcessRecord> mRemovedProcesses
580 = new ArrayList<ProcessRecord>();
581
582 /**
583 * List of running applications, sorted by recent usage.
584 * The first entry in the list is the least recently used.
585 * It contains ApplicationRecord objects. This list does NOT include
586 * any persistent application records (since we never want to exit them).
587 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800588 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 = new ArrayList<ProcessRecord>();
590
591 /**
592 * List of processes that should gc as soon as things are idle.
593 */
594 final ArrayList<ProcessRecord> mProcessesToGc
595 = new ArrayList<ProcessRecord>();
596
597 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800598 * This is the process holding what we currently consider to be
599 * the "home" activity.
600 */
601 private ProcessRecord mHomeProcess;
602
603 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 * List of running activities, sorted by recent usage.
605 * The first entry in the list is the least recently used.
606 * It contains HistoryRecord objects.
607 */
608 private final ArrayList mLRUActivities = new ArrayList();
609
610 /**
611 * Set of PendingResultRecord objects that are currently active.
612 */
613 final HashSet mPendingResultRecords = new HashSet();
614
615 /**
616 * Set of IntentSenderRecord objects that are currently active.
617 */
618 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
619 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
620
621 /**
622 * Intent broadcast that we have tried to start, but are
623 * waiting for its application's process to be created. We only
624 * need one (instead of a list) because we always process broadcasts
625 * one at a time, so no others can be started while waiting for this
626 * one.
627 */
628 BroadcastRecord mPendingBroadcast = null;
629
630 /**
631 * Keeps track of all IIntentReceivers that have been registered for
632 * broadcasts. Hash keys are the receiver IBinder, hash value is
633 * a ReceiverList.
634 */
635 final HashMap mRegisteredReceivers = new HashMap();
636
637 /**
638 * Resolver for broadcast intents to registered receivers.
639 * Holds BroadcastFilter (subclass of IntentFilter).
640 */
641 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
642 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
643 @Override
644 protected boolean allowFilterResult(
645 BroadcastFilter filter, List<BroadcastFilter> dest) {
646 IBinder target = filter.receiverList.receiver.asBinder();
647 for (int i=dest.size()-1; i>=0; i--) {
648 if (dest.get(i).receiverList.receiver.asBinder() == target) {
649 return false;
650 }
651 }
652 return true;
653 }
654 };
655
656 /**
657 * State of all active sticky broadcasts. Keys are the action of the
658 * sticky Intent, values are an ArrayList of all broadcasted intents with
659 * that action (which should usually be one).
660 */
661 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
662 new HashMap<String, ArrayList<Intent>>();
663
664 /**
665 * All currently running services.
666 */
667 final HashMap<ComponentName, ServiceRecord> mServices =
668 new HashMap<ComponentName, ServiceRecord>();
669
670 /**
671 * All currently running services indexed by the Intent used to start them.
672 */
673 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
674 new HashMap<Intent.FilterComparison, ServiceRecord>();
675
676 /**
677 * All currently bound service connections. Keys are the IBinder of
678 * the client's IServiceConnection.
679 */
680 final HashMap<IBinder, ConnectionRecord> mServiceConnections
681 = new HashMap<IBinder, ConnectionRecord>();
682
683 /**
684 * List of services that we have been asked to start,
685 * but haven't yet been able to. It is used to hold start requests
686 * while waiting for their corresponding application thread to get
687 * going.
688 */
689 final ArrayList<ServiceRecord> mPendingServices
690 = new ArrayList<ServiceRecord>();
691
692 /**
693 * List of services that are scheduled to restart following a crash.
694 */
695 final ArrayList<ServiceRecord> mRestartingServices
696 = new ArrayList<ServiceRecord>();
697
698 /**
699 * List of services that are in the process of being stopped.
700 */
701 final ArrayList<ServiceRecord> mStoppingServices
702 = new ArrayList<ServiceRecord>();
703
704 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700705 * Backup/restore process management
706 */
707 String mBackupAppName = null;
708 BackupRecord mBackupTarget = null;
709
710 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 * List of PendingThumbnailsRecord objects of clients who are still
712 * waiting to receive all of the thumbnails for a task.
713 */
714 final ArrayList mPendingThumbnails = new ArrayList();
715
716 /**
717 * List of HistoryRecord objects that have been finished and must
718 * still report back to a pending thumbnail receiver.
719 */
720 final ArrayList mCancelledThumbnails = new ArrayList();
721
722 /**
723 * All of the currently running global content providers. Keys are a
724 * string containing the provider name and values are a
725 * ContentProviderRecord object containing the data about it. Note
726 * that a single provider may be published under multiple names, so
727 * there may be multiple entries here for a single one in mProvidersByClass.
728 */
729 final HashMap mProvidersByName = new HashMap();
730
731 /**
732 * All of the currently running global content providers. Keys are a
733 * string containing the provider's implementation class and values are a
734 * ContentProviderRecord object containing the data about it.
735 */
736 final HashMap mProvidersByClass = new HashMap();
737
738 /**
739 * List of content providers who have clients waiting for them. The
740 * application is currently being launched and the provider will be
741 * removed from this list once it is published.
742 */
743 final ArrayList mLaunchingProviders = new ArrayList();
744
745 /**
746 * Global set of specific Uri permissions that have been granted.
747 */
748 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
749 = new SparseArray<HashMap<Uri, UriPermission>>();
750
751 /**
752 * Thread-local storage used to carry caller permissions over through
753 * indirect content-provider access.
754 * @see #ActivityManagerService.openContentUri()
755 */
756 private class Identity {
757 public int pid;
758 public int uid;
759
760 Identity(int _pid, int _uid) {
761 pid = _pid;
762 uid = _uid;
763 }
764 }
765 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
766
767 /**
768 * All information we have collected about the runtime performance of
769 * any user id that can impact battery performance.
770 */
771 final BatteryStatsService mBatteryStatsService;
772
773 /**
774 * information about component usage
775 */
776 final UsageStatsService mUsageStatsService;
777
778 /**
779 * Current configuration information. HistoryRecord objects are given
780 * a reference to this object to indicate which configuration they are
781 * currently running in, so this object must be kept immutable.
782 */
783 Configuration mConfiguration = new Configuration();
784
785 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800786 * Current sequencing integer of the configuration, for skipping old
787 * configurations.
788 */
789 int mConfigurationSeq = 0;
790
791 /**
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700792 * Set when we know we are going to be calling updateConfiguration()
793 * soon, so want to skip intermediate config checks.
794 */
795 boolean mConfigWillChange;
796
797 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700798 * Hardware-reported OpenGLES version.
799 */
800 final int GL_ES_VERSION;
801
802 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 * List of initialization arguments to pass to all processes when binding applications to them.
804 * For example, references to the commonly used services.
805 */
806 HashMap<String, IBinder> mAppBindArgs;
807
808 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700809 * Temporary to avoid allocations. Protected by main lock.
810 */
811 final StringBuilder mStringBuilder = new StringBuilder(256);
812
813 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 * Used to control how we initialize the service.
815 */
816 boolean mStartRunning = false;
817 ComponentName mTopComponent;
818 String mTopAction;
819 String mTopData;
820 boolean mSystemReady = false;
821 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700822 boolean mWaitingUpdate = false;
823 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824
825 Context mContext;
826
827 int mFactoryTest;
828
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700829 boolean mCheckedForSetup;
830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700832 * The time at which we will allow normal application switches again,
833 * after a call to {@link #stopAppSwitches()}.
834 */
835 long mAppSwitchesAllowedTime;
836
837 /**
838 * This is set to true after the first switch after mAppSwitchesAllowedTime
839 * is set; any switches after that will clear the time.
840 */
841 boolean mDidAppSwitch;
842
843 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 * Set while we are wanting to sleep, to prevent any
845 * activities from being started/resumed.
846 */
847 boolean mSleeping = false;
848
849 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700850 * Set if we are shutting down the system, similar to sleeping.
851 */
852 boolean mShuttingDown = false;
853
854 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 * Set when the system is going to sleep, until we have
856 * successfully paused the current activity and released our wake lock.
857 * At that point the system is allowed to actually sleep.
858 */
859 PowerManager.WakeLock mGoingToSleep;
860
861 /**
862 * We don't want to allow the device to go to sleep while in the process
863 * of launching an activity. This is primarily to allow alarm intent
864 * receivers to launch an activity and get that to run before the device
865 * goes back to sleep.
866 */
867 PowerManager.WakeLock mLaunchingActivity;
868
869 /**
870 * Task identifier that activities are currently being started
871 * in. Incremented each time a new task is created.
872 * todo: Replace this with a TokenSpace class that generates non-repeating
873 * integers that won't wrap.
874 */
875 int mCurTask = 1;
876
877 /**
878 * Current sequence id for oom_adj computation traversal.
879 */
880 int mAdjSeq = 0;
881
882 /**
883 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
884 * is set, indicating the user wants processes started in such a way
885 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
886 * running in each process (thus no pre-initialized process, etc).
887 */
888 boolean mSimpleProcessManagement = false;
889
890 /**
891 * System monitoring: number of processes that died since the last
892 * N procs were started.
893 */
894 int[] mProcDeaths = new int[20];
895
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700896 /**
897 * This is set if we had to do a delayed dexopt of an app before launching
898 * it, to increasing the ANR timeouts in that case.
899 */
900 boolean mDidDexOpt;
901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 String mDebugApp = null;
903 boolean mWaitForDebugger = false;
904 boolean mDebugTransient = false;
905 String mOrigDebugApp = null;
906 boolean mOrigWaitForDebugger = false;
907 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700908 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700910 final RemoteCallbackList<IActivityWatcher> mWatchers
911 = new RemoteCallbackList<IActivityWatcher>();
912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 /**
914 * Callback of last caller to {@link #requestPss}.
915 */
916 Runnable mRequestPssCallback;
917
918 /**
919 * Remaining processes for which we are waiting results from the last
920 * call to {@link #requestPss}.
921 */
922 final ArrayList<ProcessRecord> mRequestPssList
923 = new ArrayList<ProcessRecord>();
924
925 /**
926 * Runtime statistics collection thread. This object's lock is used to
927 * protect all related state.
928 */
929 final Thread mProcessStatsThread;
930
931 /**
932 * Used to collect process stats when showing not responding dialog.
933 * Protected by mProcessStatsThread.
934 */
935 final ProcessStats mProcessStats = new ProcessStats(
936 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700937 final AtomicLong mLastCpuTime = new AtomicLong(0);
938 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 long mLastWriteTime = 0;
941
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700942 long mInitialStartTime = 0;
943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 /**
945 * Set to true after the system has finished booting.
946 */
947 boolean mBooted = false;
948
949 int mProcessLimit = 0;
950
951 WindowManagerService mWindowManager;
952
953 static ActivityManagerService mSelf;
954 static ActivityThread mSystemThread;
955
956 private final class AppDeathRecipient implements IBinder.DeathRecipient {
957 final ProcessRecord mApp;
958 final int mPid;
959 final IApplicationThread mAppThread;
960
961 AppDeathRecipient(ProcessRecord app, int pid,
962 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800963 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 TAG, "New death recipient " + this
965 + " for thread " + thread.asBinder());
966 mApp = app;
967 mPid = pid;
968 mAppThread = thread;
969 }
970
971 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800972 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 TAG, "Death received in " + this
974 + " for thread " + mAppThread.asBinder());
975 removeRequestedPss(mApp);
976 synchronized(ActivityManagerService.this) {
977 appDiedLocked(mApp, mPid, mAppThread);
978 }
979 }
980 }
981
982 static final int SHOW_ERROR_MSG = 1;
983 static final int SHOW_NOT_RESPONDING_MSG = 2;
984 static final int SHOW_FACTORY_ERROR_MSG = 3;
985 static final int UPDATE_CONFIGURATION_MSG = 4;
986 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
987 static final int WAIT_FOR_DEBUGGER_MSG = 6;
988 static final int BROADCAST_INTENT_MSG = 7;
989 static final int BROADCAST_TIMEOUT_MSG = 8;
990 static final int PAUSE_TIMEOUT_MSG = 9;
991 static final int IDLE_TIMEOUT_MSG = 10;
992 static final int IDLE_NOW_MSG = 11;
993 static final int SERVICE_TIMEOUT_MSG = 12;
994 static final int UPDATE_TIME_ZONE = 13;
995 static final int SHOW_UID_ERROR_MSG = 14;
996 static final int IM_FEELING_LUCKY_MSG = 15;
997 static final int LAUNCH_TIMEOUT_MSG = 16;
998 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 static final int RESUME_TOP_ACTIVITY_MSG = 19;
1000 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001001 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001002 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001003 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004
1005 AlertDialog mUidAlert;
1006
1007 final Handler mHandler = new Handler() {
1008 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001009 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 //}
1011
1012 public void handleMessage(Message msg) {
1013 switch (msg.what) {
1014 case SHOW_ERROR_MSG: {
1015 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 synchronized (ActivityManagerService.this) {
1017 ProcessRecord proc = (ProcessRecord)data.get("app");
1018 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001019 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 return;
1021 }
1022 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001023 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001024 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 d.show();
1026 proc.crashDialog = d;
1027 } else {
1028 // The device is asleep, so just pretend that the user
1029 // saw a crash dialog and hit "force quit".
1030 res.set(0);
1031 }
1032 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001033
1034 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 } break;
1036 case SHOW_NOT_RESPONDING_MSG: {
1037 synchronized (ActivityManagerService.this) {
1038 HashMap data = (HashMap) msg.obj;
1039 ProcessRecord proc = (ProcessRecord)data.get("app");
1040 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001041 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 return;
1043 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001044
1045 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1046 null, null, 0, null, null, null,
1047 false, false, MY_PID, Process.SYSTEM_UID);
1048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1050 mContext, proc, (HistoryRecord)data.get("activity"));
1051 d.show();
1052 proc.anrDialog = d;
1053 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001054
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001055 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 } break;
1057 case SHOW_FACTORY_ERROR_MSG: {
1058 Dialog d = new FactoryErrorDialog(
1059 mContext, msg.getData().getCharSequence("msg"));
1060 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001061 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 } break;
1063 case UPDATE_CONFIGURATION_MSG: {
1064 final ContentResolver resolver = mContext.getContentResolver();
1065 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1066 } break;
1067 case GC_BACKGROUND_PROCESSES_MSG: {
1068 synchronized (ActivityManagerService.this) {
1069 performAppGcsIfAppropriateLocked();
1070 }
1071 } break;
1072 case WAIT_FOR_DEBUGGER_MSG: {
1073 synchronized (ActivityManagerService.this) {
1074 ProcessRecord app = (ProcessRecord)msg.obj;
1075 if (msg.arg1 != 0) {
1076 if (!app.waitedForDebugger) {
1077 Dialog d = new AppWaitingForDebuggerDialog(
1078 ActivityManagerService.this,
1079 mContext, app);
1080 app.waitDialog = d;
1081 app.waitedForDebugger = true;
1082 d.show();
1083 }
1084 } else {
1085 if (app.waitDialog != null) {
1086 app.waitDialog.dismiss();
1087 app.waitDialog = null;
1088 }
1089 }
1090 }
1091 } break;
1092 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001093 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 TAG, "Received BROADCAST_INTENT_MSG");
1095 processNextBroadcast(true);
1096 } break;
1097 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001098 if (mDidDexOpt) {
1099 mDidDexOpt = false;
1100 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1101 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1102 return;
1103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 broadcastTimeout();
1105 } break;
1106 case PAUSE_TIMEOUT_MSG: {
1107 IBinder token = (IBinder)msg.obj;
1108 // We don't at this point know if the activity is fullscreen,
1109 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001110 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 activityPaused(token, null, true);
1112 } break;
1113 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001114 if (mDidDexOpt) {
1115 mDidDexOpt = false;
1116 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1117 nmsg.obj = msg.obj;
1118 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1119 return;
1120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 // We don't at this point know if the activity is fullscreen,
1122 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001123 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001124 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001125 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001126 } break;
1127 case DESTROY_TIMEOUT_MSG: {
1128 IBinder token = (IBinder)msg.obj;
1129 // We don't at this point know if the activity is fullscreen,
1130 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001131 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 activityDestroyed(token);
1133 } break;
1134 case IDLE_NOW_MSG: {
1135 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001136 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 } break;
1138 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001139 if (mDidDexOpt) {
1140 mDidDexOpt = false;
1141 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1142 nmsg.obj = msg.obj;
1143 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1144 return;
1145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 serviceTimeout((ProcessRecord)msg.obj);
1147 } break;
1148 case UPDATE_TIME_ZONE: {
1149 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001150 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1151 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 if (r.thread != null) {
1153 try {
1154 r.thread.updateTimeZone();
1155 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001156 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 }
1158 }
1159 }
1160 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001161 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 case SHOW_UID_ERROR_MSG: {
1163 // XXX This is a temporary dialog, no need to localize.
1164 AlertDialog d = new BaseErrorDialog(mContext);
1165 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1166 d.setCancelable(false);
1167 d.setTitle("System UIDs Inconsistent");
1168 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1169 d.setButton("I'm Feeling Lucky",
1170 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1171 mUidAlert = d;
1172 d.show();
1173 } break;
1174 case IM_FEELING_LUCKY_MSG: {
1175 if (mUidAlert != null) {
1176 mUidAlert.dismiss();
1177 mUidAlert = null;
1178 }
1179 } break;
1180 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001181 if (mDidDexOpt) {
1182 mDidDexOpt = false;
1183 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1184 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1185 return;
1186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 synchronized (ActivityManagerService.this) {
1188 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001189 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 mLaunchingActivity.release();
1191 }
1192 }
1193 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 case RESUME_TOP_ACTIVITY_MSG: {
1195 synchronized (ActivityManagerService.this) {
1196 resumeTopActivityLocked(null);
1197 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001198 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001200 if (mDidDexOpt) {
1201 mDidDexOpt = false;
1202 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1203 nmsg.obj = msg.obj;
1204 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1205 return;
1206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 ProcessRecord app = (ProcessRecord)msg.obj;
1208 synchronized (ActivityManagerService.this) {
1209 processStartTimedOutLocked(app);
1210 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001211 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001212 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1213 synchronized (ActivityManagerService.this) {
1214 doPendingActivityLaunchesLocked(true);
1215 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001216 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001217 case KILL_APPLICATION_MSG: {
1218 synchronized (ActivityManagerService.this) {
1219 int uid = msg.arg1;
1220 boolean restart = (msg.arg2 == 1);
1221 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001222 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001223 }
1224 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001225 case FINALIZE_PENDING_INTENT_MSG: {
1226 ((PendingIntentRecord)msg.obj).completeFinalize();
1227 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 }
1229 }
1230 };
1231
1232 public static void setSystemProcess() {
1233 try {
1234 ActivityManagerService m = mSelf;
1235
1236 ServiceManager.addService("activity", m);
1237 ServiceManager.addService("meminfo", new MemBinder(m));
1238 if (MONITOR_CPU_USAGE) {
1239 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1240 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241 ServiceManager.addService("permission", new PermissionController(m));
1242
1243 ApplicationInfo info =
1244 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001245 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001246 mSystemThread.installSystemApplicationInfo(info);
1247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001248 synchronized (mSelf) {
1249 ProcessRecord app = mSelf.newProcessRecordLocked(
1250 mSystemThread.getApplicationThread(), info,
1251 info.processName);
1252 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001253 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254 app.maxAdj = SYSTEM_ADJ;
1255 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1256 synchronized (mSelf.mPidsSelfLocked) {
1257 mSelf.mPidsSelfLocked.put(app.pid, app);
1258 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001259 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 }
1261 } catch (PackageManager.NameNotFoundException e) {
1262 throw new RuntimeException(
1263 "Unable to find android system package", e);
1264 }
1265 }
1266
1267 public void setWindowManager(WindowManagerService wm) {
1268 mWindowManager = wm;
1269 }
1270
1271 public static final Context main(int factoryTest) {
1272 AThread thr = new AThread();
1273 thr.start();
1274
1275 synchronized (thr) {
1276 while (thr.mService == null) {
1277 try {
1278 thr.wait();
1279 } catch (InterruptedException e) {
1280 }
1281 }
1282 }
1283
1284 ActivityManagerService m = thr.mService;
1285 mSelf = m;
1286 ActivityThread at = ActivityThread.systemMain();
1287 mSystemThread = at;
1288 Context context = at.getSystemContext();
1289 m.mContext = context;
1290 m.mFactoryTest = factoryTest;
1291 PowerManager pm =
1292 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1293 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1294 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1295 m.mLaunchingActivity.setReferenceCounted(false);
1296
1297 m.mBatteryStatsService.publish(context);
1298 m.mUsageStatsService.publish(context);
1299
1300 synchronized (thr) {
1301 thr.mReady = true;
1302 thr.notifyAll();
1303 }
1304
1305 m.startRunning(null, null, null, null);
1306
1307 return context;
1308 }
1309
1310 public static ActivityManagerService self() {
1311 return mSelf;
1312 }
1313
1314 static class AThread extends Thread {
1315 ActivityManagerService mService;
1316 boolean mReady = false;
1317
1318 public AThread() {
1319 super("ActivityManager");
1320 }
1321
1322 public void run() {
1323 Looper.prepare();
1324
1325 android.os.Process.setThreadPriority(
1326 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1327
1328 ActivityManagerService m = new ActivityManagerService();
1329
1330 synchronized (this) {
1331 mService = m;
1332 notifyAll();
1333 }
1334
1335 synchronized (this) {
1336 while (!mReady) {
1337 try {
1338 wait();
1339 } catch (InterruptedException e) {
1340 }
1341 }
1342 }
1343
1344 Looper.loop();
1345 }
1346 }
1347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 static class MemBinder extends Binder {
1349 ActivityManagerService mActivityManagerService;
1350 MemBinder(ActivityManagerService activityManagerService) {
1351 mActivityManagerService = activityManagerService;
1352 }
1353
1354 @Override
1355 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1356 ActivityManagerService service = mActivityManagerService;
1357 ArrayList<ProcessRecord> procs;
1358 synchronized (mActivityManagerService) {
1359 if (args != null && args.length > 0
1360 && args[0].charAt(0) != '-') {
1361 procs = new ArrayList<ProcessRecord>();
1362 int pid = -1;
1363 try {
1364 pid = Integer.parseInt(args[0]);
1365 } catch (NumberFormatException e) {
1366
1367 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001368 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1369 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 if (proc.pid == pid) {
1371 procs.add(proc);
1372 } else if (proc.processName.equals(args[0])) {
1373 procs.add(proc);
1374 }
1375 }
1376 if (procs.size() <= 0) {
1377 pw.println("No process found for: " + args[0]);
1378 return;
1379 }
1380 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001381 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 }
1383 }
1384 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1385 }
1386 }
1387
1388 static class CpuBinder extends Binder {
1389 ActivityManagerService mActivityManagerService;
1390 CpuBinder(ActivityManagerService activityManagerService) {
1391 mActivityManagerService = activityManagerService;
1392 }
1393
1394 @Override
1395 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1396 synchronized (mActivityManagerService.mProcessStatsThread) {
1397 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1398 }
1399 }
1400 }
1401
1402 private ActivityManagerService() {
1403 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1404 if (v != null && Integer.getInteger(v) != 0) {
1405 mSimpleProcessManagement = true;
1406 }
1407 v = System.getenv("ANDROID_DEBUG_APP");
1408 if (v != null) {
1409 mSimpleProcessManagement = true;
1410 }
1411
Joe Onorato8a9b2202010-02-26 18:56:32 -08001412 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 File dataDir = Environment.getDataDirectory();
1415 File systemDir = new File(dataDir, "system");
1416 systemDir.mkdirs();
1417 mBatteryStatsService = new BatteryStatsService(new File(
1418 systemDir, "batterystats.bin").toString());
1419 mBatteryStatsService.getActiveStatistics().readLocked();
1420 mBatteryStatsService.getActiveStatistics().writeLocked();
1421
1422 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001423 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424
Jack Palevichb90d28c2009-07-22 15:35:24 -07001425 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1426 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1427
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001428 mConfiguration.setToDefaults();
1429 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 mProcessStats.init();
1431
1432 // Add ourself to the Watchdog monitors.
1433 Watchdog.getInstance().addMonitor(this);
1434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 mProcessStatsThread = new Thread("ProcessStats") {
1436 public void run() {
1437 while (true) {
1438 try {
1439 try {
1440 synchronized(this) {
1441 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001442 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001444 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 // + ", write delay=" + nextWriteDelay);
1446 if (nextWriteDelay < nextCpuDelay) {
1447 nextCpuDelay = nextWriteDelay;
1448 }
1449 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001450 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 this.wait(nextCpuDelay);
1452 }
1453 }
1454 } catch (InterruptedException e) {
1455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 updateCpuStatsNow();
1457 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001458 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 }
1460 }
1461 }
1462 };
1463 mProcessStatsThread.start();
1464 }
1465
1466 @Override
1467 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1468 throws RemoteException {
1469 try {
1470 return super.onTransact(code, data, reply, flags);
1471 } catch (RuntimeException e) {
1472 // The activity manager only throws security exceptions, so let's
1473 // log all others.
1474 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001475 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 }
1477 throw e;
1478 }
1479 }
1480
1481 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001482 final long now = SystemClock.uptimeMillis();
1483 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1484 return;
1485 }
1486 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1487 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 mProcessStatsThread.notify();
1489 }
1490 }
1491 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 void updateCpuStatsNow() {
1494 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001495 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 final long now = SystemClock.uptimeMillis();
1497 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001500 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1501 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 haveNewCpuStats = true;
1503 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001504 //Slog.i(TAG, mProcessStats.printCurrentState());
1505 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 // + mProcessStats.getTotalCpuPercent() + "%");
1507
Joe Onorato8a9b2202010-02-26 18:56:32 -08001508 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 if ("true".equals(SystemProperties.get("events.cpu"))) {
1510 int user = mProcessStats.getLastUserTime();
1511 int system = mProcessStats.getLastSystemTime();
1512 int iowait = mProcessStats.getLastIoWaitTime();
1513 int irq = mProcessStats.getLastIrqTime();
1514 int softIrq = mProcessStats.getLastSoftIrqTime();
1515 int idle = mProcessStats.getLastIdleTime();
1516
1517 int total = user + system + iowait + irq + softIrq + idle;
1518 if (total == 0) total = 1;
1519
Doug Zongker2bec3d42009-12-04 12:52:44 -08001520 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 ((user+system+iowait+irq+softIrq) * 100) / total,
1522 (user * 100) / total,
1523 (system * 100) / total,
1524 (iowait * 100) / total,
1525 (irq * 100) / total,
1526 (softIrq * 100) / total);
1527 }
1528 }
1529
Amith Yamasanie43530a2009-08-21 13:11:37 -07001530 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001531 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001532 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 synchronized(mPidsSelfLocked) {
1534 if (haveNewCpuStats) {
1535 if (mBatteryStatsService.isOnBattery()) {
1536 final int N = mProcessStats.countWorkingStats();
1537 for (int i=0; i<N; i++) {
1538 ProcessStats.Stats st
1539 = mProcessStats.getWorkingStats(i);
1540 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1541 if (pr != null) {
1542 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1543 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001544 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001545 } else {
1546 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001547 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001548 if (ps != null) {
1549 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001550 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 }
1553 }
1554 }
1555 }
1556 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1559 mLastWriteTime = now;
1560 mBatteryStatsService.getActiveStatistics().writeLocked();
1561 }
1562 }
1563 }
1564 }
1565
1566 /**
1567 * Initialize the application bind args. These are passed to each
1568 * process when the bindApplication() IPC is sent to the process. They're
1569 * lazily setup to make sure the services are running when they're asked for.
1570 */
1571 private HashMap<String, IBinder> getCommonServicesLocked() {
1572 if (mAppBindArgs == null) {
1573 mAppBindArgs = new HashMap<String, IBinder>();
1574
1575 // Setup the application init args
1576 mAppBindArgs.put("package", ServiceManager.getService("package"));
1577 mAppBindArgs.put("window", ServiceManager.getService("window"));
1578 mAppBindArgs.put(Context.ALARM_SERVICE,
1579 ServiceManager.getService(Context.ALARM_SERVICE));
1580 }
1581 return mAppBindArgs;
1582 }
1583
1584 private final void setFocusedActivityLocked(HistoryRecord r) {
1585 if (mFocusedActivity != r) {
1586 mFocusedActivity = r;
1587 mWindowManager.setFocusedApp(r, true);
1588 }
1589 }
1590
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001591 private final void updateLruProcessLocked(ProcessRecord app,
1592 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001594 int lrui = mLruProcesses.indexOf(app);
1595 if (lrui >= 0) mLruProcesses.remove(lrui);
1596
1597 int i = mLruProcesses.size()-1;
1598 int skipTop = 0;
1599
1600 // compute the new weight for this process.
1601 if (updateActivityTime) {
1602 app.lastActivityTime = SystemClock.uptimeMillis();
1603 }
1604 if (app.activities.size() > 0) {
1605 // If this process has activities, we more strongly want to keep
1606 // it around.
1607 app.lruWeight = app.lastActivityTime;
1608 } else if (app.pubProviders.size() > 0) {
1609 // If this process contains content providers, we want to keep
1610 // it a little more strongly.
1611 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1612 // Also don't let it kick out the first few "real" hidden processes.
1613 skipTop = MIN_HIDDEN_APPS;
1614 } else {
1615 // If this process doesn't have activities, we less strongly
1616 // want to keep it around, and generally want to avoid getting
1617 // in front of any very recently used activities.
1618 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1619 // Also don't let it kick out the first few "real" hidden processes.
1620 skipTop = MIN_HIDDEN_APPS;
1621 }
1622 while (i >= 0) {
1623 ProcessRecord p = mLruProcesses.get(i);
1624 // If this app shouldn't be in front of the first N background
1625 // apps, then skip over that many that are currently hidden.
1626 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1627 skipTop--;
1628 }
1629 if (p.lruWeight <= app.lruWeight){
1630 mLruProcesses.add(i+1, app);
1631 break;
1632 }
1633 i--;
1634 }
1635 if (i < 0) {
1636 mLruProcesses.add(0, app);
1637 }
1638
Joe Onorato8a9b2202010-02-26 18:56:32 -08001639 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 if (oomAdj) {
1641 updateOomAdjLocked();
1642 }
1643 }
1644
1645 private final boolean updateLRUListLocked(HistoryRecord r) {
1646 final boolean hadit = mLRUActivities.remove(r);
1647 mLRUActivities.add(r);
1648 return hadit;
1649 }
1650
1651 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1652 int i = mHistory.size()-1;
1653 while (i >= 0) {
1654 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1655 if (!r.finishing && r != notTop) {
1656 return r;
1657 }
1658 i--;
1659 }
1660 return null;
1661 }
1662
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001663 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1664 int i = mHistory.size()-1;
1665 while (i >= 0) {
1666 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1667 if (!r.finishing && !r.delayedResume && r != notTop) {
1668 return r;
1669 }
1670 i--;
1671 }
1672 return null;
1673 }
1674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 /**
1676 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001677 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 *
1679 * @param token If non-null, any history records matching this token will be skipped.
1680 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1681 *
1682 * @return Returns the HistoryRecord of the next activity on the stack.
1683 */
1684 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1685 int i = mHistory.size()-1;
1686 while (i >= 0) {
1687 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1688 // Note: the taskId check depends on real taskId fields being non-zero
1689 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1690 return r;
1691 }
1692 i--;
1693 }
1694 return null;
1695 }
1696
1697 private final ProcessRecord getProcessRecordLocked(
1698 String processName, int uid) {
1699 if (uid == Process.SYSTEM_UID) {
1700 // The system gets to run in any process. If there are multiple
1701 // processes with the same uid, just pick the first (this
1702 // should never happen).
1703 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1704 processName);
1705 return procs != null ? procs.valueAt(0) : null;
1706 }
1707 ProcessRecord proc = mProcessNames.get(processName, uid);
1708 return proc;
1709 }
1710
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001711 private void ensurePackageDexOpt(String packageName) {
1712 IPackageManager pm = ActivityThread.getPackageManager();
1713 try {
1714 if (pm.performDexOpt(packageName)) {
1715 mDidDexOpt = true;
1716 }
1717 } catch (RemoteException e) {
1718 }
1719 }
1720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 private boolean isNextTransitionForward() {
1722 int transit = mWindowManager.getPendingAppTransition();
1723 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1724 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1725 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1726 }
1727
1728 private final boolean realStartActivityLocked(HistoryRecord r,
1729 ProcessRecord app, boolean andResume, boolean checkConfig)
1730 throws RemoteException {
1731
1732 r.startFreezingScreenLocked(app, 0);
1733 mWindowManager.setAppVisibility(r, true);
1734
1735 // Have the window manager re-evaluate the orientation of
1736 // the screen based on the new activity order. Note that
1737 // as a result of this, it can call back into the activity
1738 // manager with a new orientation. We don't care about that,
1739 // because the activity is not currently running so we are
1740 // just restarting it anyway.
1741 if (checkConfig) {
1742 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001743 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 r.mayFreezeScreenLocked(app) ? r : null);
1745 updateConfigurationLocked(config, r);
1746 }
1747
1748 r.app = app;
1749
Joe Onorato8a9b2202010-02-26 18:56:32 -08001750 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751
1752 int idx = app.activities.indexOf(r);
1753 if (idx < 0) {
1754 app.activities.add(r);
1755 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001756 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757
1758 try {
1759 if (app.thread == null) {
1760 throw new RemoteException();
1761 }
1762 List<ResultInfo> results = null;
1763 List<Intent> newIntents = null;
1764 if (andResume) {
1765 results = r.results;
1766 newIntents = r.newIntents;
1767 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001768 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 + " icicle=" + r.icicle
1770 + " with results=" + results + " newIntents=" + newIntents
1771 + " andResume=" + andResume);
1772 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001773 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 System.identityHashCode(r),
1775 r.task.taskId, r.shortComponentName);
1776 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001777 if (r.isHomeActivity) {
1778 mHomeProcess = app;
1779 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001780 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001782 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 r.info, r.icicle, results, newIntents, !andResume,
1784 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 } catch (RemoteException e) {
1786 if (r.launchFailed) {
1787 // This is the second time we failed -- finish activity
1788 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001789 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001790 + r.intent.getComponent().flattenToShortString()
1791 + ", giving up", e);
1792 appDiedLocked(app, app.pid, app.thread);
1793 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1794 "2nd-crash");
1795 return false;
1796 }
1797
1798 // This is the first time we failed -- restart process and
1799 // retry.
1800 app.activities.remove(r);
1801 throw e;
1802 }
1803
1804 r.launchFailed = false;
1805 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001806 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001807 + " being launched, but already in LRU list");
1808 }
1809
1810 if (andResume) {
1811 // As part of the process of launching, ActivityThread also performs
1812 // a resume.
1813 r.state = ActivityState.RESUMED;
1814 r.icicle = null;
1815 r.haveState = false;
1816 r.stopped = false;
1817 mResumedActivity = r;
1818 r.task.touchActiveTime();
1819 completeResumeLocked(r);
1820 pauseIfSleepingLocked();
1821 } else {
1822 // This activity is not starting in the resumed state... which
1823 // should look like we asked it to pause+stop (but remain visible),
1824 // and it has done so and reported back the current icicle and
1825 // other state.
1826 r.state = ActivityState.STOPPED;
1827 r.stopped = true;
1828 }
1829
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001830 // Launch the new version setup screen if needed. We do this -after-
1831 // launching the initial activity (that is, home), so that it can have
1832 // a chance to initialize itself while in the background, making the
1833 // switch back to it faster and look better.
1834 startSetupActivityLocked();
1835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001836 return true;
1837 }
1838
1839 private final void startSpecificActivityLocked(HistoryRecord r,
1840 boolean andResume, boolean checkConfig) {
1841 // Is this activity's application already running?
1842 ProcessRecord app = getProcessRecordLocked(r.processName,
1843 r.info.applicationInfo.uid);
1844
1845 if (r.startTime == 0) {
1846 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001847 if (mInitialStartTime == 0) {
1848 mInitialStartTime = r.startTime;
1849 }
1850 } else if (mInitialStartTime == 0) {
1851 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 }
1853
1854 if (app != null && app.thread != null) {
1855 try {
1856 realStartActivityLocked(r, app, andResume, checkConfig);
1857 return;
1858 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001859 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 + r.intent.getComponent().flattenToShortString(), e);
1861 }
1862
1863 // If a dead object exception was thrown -- fall through to
1864 // restart the application.
1865 }
1866
1867 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001868 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 }
1870
1871 private final ProcessRecord startProcessLocked(String processName,
1872 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001873 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1875 // We don't have to do anything more if:
1876 // (1) There is an existing application record; and
1877 // (2) The caller doesn't think it is dead, OR there is no thread
1878 // object attached to it so we know it couldn't have crashed; and
1879 // (3) There is a pid assigned to it, so it is either starting or
1880 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001881 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001882 + " app=" + app + " knownToBeDead=" + knownToBeDead
1883 + " thread=" + (app != null ? app.thread : null)
1884 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001885 if (app != null && app.pid > 0) {
1886 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001887 // We already have the app running, or are waiting for it to
1888 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001889 return app;
1890 } else {
1891 // An application record is attached to a previous process,
1892 // clean it up now.
1893 handleAppDiedLocked(app, true);
1894 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 String hostingNameStr = hostingName != null
1898 ? hostingName.flattenToShortString() : null;
1899
1900 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1901 // If we are in the background, then check to see if this process
1902 // is bad. If so, we will just silently fail.
1903 if (mBadProcesses.get(info.processName, info.uid) != null) {
1904 return null;
1905 }
1906 } else {
1907 // When the user is explicitly starting a process, then clear its
1908 // crash count so that we won't make it bad until they see at
1909 // least one crash dialog again, and make the process good again
1910 // if it had been bad.
1911 mProcessCrashTimes.remove(info.processName, info.uid);
1912 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001913 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 info.processName);
1915 mBadProcesses.remove(info.processName, info.uid);
1916 if (app != null) {
1917 app.bad = false;
1918 }
1919 }
1920 }
1921
1922 if (app == null) {
1923 app = newProcessRecordLocked(null, info, processName);
1924 mProcessNames.put(processName, info.uid, app);
1925 } else {
1926 // If this is a new package in the process, add the package to the list
1927 app.addPackage(info.packageName);
1928 }
1929
1930 // If the system is not ready yet, then hold off on starting this
1931 // process until it is.
1932 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001933 && !isAllowedWhileBooting(info)
1934 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 if (!mProcessesOnHold.contains(app)) {
1936 mProcessesOnHold.add(app);
1937 }
1938 return app;
1939 }
1940
1941 startProcessLocked(app, hostingType, hostingNameStr);
1942 return (app.pid != 0) ? app : null;
1943 }
1944
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001945 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1946 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1947 }
1948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 private final void startProcessLocked(ProcessRecord app,
1950 String hostingType, String hostingNameStr) {
1951 if (app.pid > 0 && app.pid != MY_PID) {
1952 synchronized (mPidsSelfLocked) {
1953 mPidsSelfLocked.remove(app.pid);
1954 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1955 }
1956 app.pid = 0;
1957 }
1958
1959 mProcessesOnHold.remove(app);
1960
1961 updateCpuStats();
1962
1963 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1964 mProcDeaths[0] = 0;
1965
1966 try {
1967 int uid = app.info.uid;
1968 int[] gids = null;
1969 try {
1970 gids = mContext.getPackageManager().getPackageGids(
1971 app.info.packageName);
1972 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001973 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001974 }
1975 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1976 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1977 && mTopComponent != null
1978 && app.processName.equals(mTopComponent.getPackageName())) {
1979 uid = 0;
1980 }
1981 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1982 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1983 uid = 0;
1984 }
1985 }
1986 int debugFlags = 0;
1987 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1988 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1989 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001990 // Run the app in safe mode if its manifest requests so or the
1991 // system is booted in safe mode.
1992 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1993 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001994 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001996 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1997 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1998 }
1999 if ("1".equals(SystemProperties.get("debug.assert"))) {
2000 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2001 }
2002 int pid = Process.start("android.app.ActivityThread",
2003 mSimpleProcessManagement ? app.processName : null, uid, uid,
2004 gids, debugFlags, null);
2005 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2006 synchronized (bs) {
2007 if (bs.isOnBattery()) {
2008 app.batteryStats.incStartsLocked();
2009 }
2010 }
2011
Doug Zongker2bec3d42009-12-04 12:52:44 -08002012 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 app.processName, hostingType,
2014 hostingNameStr != null ? hostingNameStr : "");
2015
2016 if (app.persistent) {
2017 Watchdog.getInstance().processStarted(app, app.processName, pid);
2018 }
2019
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002020 StringBuilder buf = mStringBuilder;
2021 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002022 buf.append("Start proc ");
2023 buf.append(app.processName);
2024 buf.append(" for ");
2025 buf.append(hostingType);
2026 if (hostingNameStr != null) {
2027 buf.append(" ");
2028 buf.append(hostingNameStr);
2029 }
2030 buf.append(": pid=");
2031 buf.append(pid);
2032 buf.append(" uid=");
2033 buf.append(uid);
2034 buf.append(" gids={");
2035 if (gids != null) {
2036 for (int gi=0; gi<gids.length; gi++) {
2037 if (gi != 0) buf.append(", ");
2038 buf.append(gids[gi]);
2039
2040 }
2041 }
2042 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002043 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 if (pid == 0 || pid == MY_PID) {
2045 // Processes are being emulated with threads.
2046 app.pid = MY_PID;
2047 app.removed = false;
2048 mStartingProcesses.add(app);
2049 } else if (pid > 0) {
2050 app.pid = pid;
2051 app.removed = false;
2052 synchronized (mPidsSelfLocked) {
2053 this.mPidsSelfLocked.put(pid, app);
2054 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2055 msg.obj = app;
2056 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2057 }
2058 } else {
2059 app.pid = 0;
2060 RuntimeException e = new RuntimeException(
2061 "Failure starting process " + app.processName
2062 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002063 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 }
2065 } catch (RuntimeException e) {
2066 // XXX do better error recovery.
2067 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002068 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 }
2070 }
2071
2072 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2073 if (mPausingActivity != null) {
2074 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002075 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076 + mPausingActivity, e);
2077 }
2078 HistoryRecord prev = mResumedActivity;
2079 if (prev == null) {
2080 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002081 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 resumeTopActivityLocked(null);
2083 return;
2084 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002085 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002086 mResumedActivity = null;
2087 mPausingActivity = prev;
2088 mLastPausedActivity = prev;
2089 prev.state = ActivityState.PAUSING;
2090 prev.task.touchActiveTime();
2091
2092 updateCpuStats();
2093
2094 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002095 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002097 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002098 System.identityHashCode(prev),
2099 prev.shortComponentName);
2100 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2101 prev.configChangeFlags);
2102 updateUsageStats(prev, false);
2103 } catch (Exception e) {
2104 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002105 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002106 mPausingActivity = null;
2107 mLastPausedActivity = null;
2108 }
2109 } else {
2110 mPausingActivity = null;
2111 mLastPausedActivity = null;
2112 }
2113
2114 // If we are not going to sleep, we want to ensure the device is
2115 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002116 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 mLaunchingActivity.acquire();
2118 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2119 // To be safe, don't allow the wake lock to be held for too long.
2120 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2121 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2122 }
2123 }
2124
2125
2126 if (mPausingActivity != null) {
2127 // Have the window manager pause its key dispatching until the new
2128 // activity has started. If we're pausing the activity just because
2129 // the screen is being turned off and the UI is sleeping, don't interrupt
2130 // key dispatch; the same activity will pick it up again on wakeup.
2131 if (!uiSleeping) {
2132 prev.pauseKeyDispatchingLocked();
2133 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002134 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 }
2136
2137 // Schedule a pause timeout in case the app doesn't respond.
2138 // We don't give it much time because this directly impacts the
2139 // responsiveness seen by the user.
2140 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2141 msg.obj = prev;
2142 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002143 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 } else {
2145 // This activity failed to schedule the
2146 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002147 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 resumeTopActivityLocked(null);
2149 }
2150 }
2151
2152 private final void completePauseLocked() {
2153 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002154 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155
2156 if (prev != null) {
2157 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002158 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2160 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002161 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 if (prev.waitingVisible) {
2163 prev.waitingVisible = false;
2164 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002165 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 TAG, "Complete pause, no longer waiting: " + prev);
2167 }
2168 if (prev.configDestroy) {
2169 // The previous is being paused because the configuration
2170 // is changing, which means it is actually stopping...
2171 // To juggle the fact that we are also starting a new
2172 // instance right now, we need to first completely stop
2173 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002174 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 destroyActivityLocked(prev, true);
2176 } else {
2177 mStoppingActivities.add(prev);
2178 if (mStoppingActivities.size() > 3) {
2179 // If we already have a few activities waiting to stop,
2180 // then give up on things going idle and start clearing
2181 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002182 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 Message msg = Message.obtain();
2184 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2185 mHandler.sendMessage(msg);
2186 }
2187 }
2188 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002189 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190 prev = null;
2191 }
2192 mPausingActivity = null;
2193 }
2194
Dianne Hackborn55280a92009-05-07 15:53:46 -07002195 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 resumeTopActivityLocked(prev);
2197 } else {
2198 if (mGoingToSleep.isHeld()) {
2199 mGoingToSleep.release();
2200 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002201 if (mShuttingDown) {
2202 notifyAll();
2203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002204 }
2205
2206 if (prev != null) {
2207 prev.resumeKeyDispatchingLocked();
2208 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002209
2210 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2211 long diff = 0;
2212 synchronized (mProcessStatsThread) {
2213 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2214 }
2215 if (diff > 0) {
2216 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2217 synchronized (bsi) {
2218 BatteryStatsImpl.Uid.Proc ps =
2219 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2220 prev.info.packageName);
2221 if (ps != null) {
2222 ps.addForegroundTimeLocked(diff);
2223 }
2224 }
2225 }
2226 }
2227 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228 }
2229
2230 /**
2231 * Once we know that we have asked an application to put an activity in
2232 * the resumed state (either by launching it or explicitly telling it),
2233 * this function updates the rest of our state to match that fact.
2234 */
2235 private final void completeResumeLocked(HistoryRecord next) {
2236 next.idle = false;
2237 next.results = null;
2238 next.newIntents = null;
2239
2240 // schedule an idle timeout in case the app doesn't do it for us.
2241 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2242 msg.obj = next;
2243 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2244
2245 if (false) {
2246 // The activity was never told to pause, so just keep
2247 // things going as-is. To maintain our own state,
2248 // we need to emulate it coming back and saying it is
2249 // idle.
2250 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2251 msg.obj = next;
2252 mHandler.sendMessage(msg);
2253 }
2254
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002255 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 next.thumbnail = null;
2258 setFocusedActivityLocked(next);
2259 next.resumeKeyDispatchingLocked();
2260 ensureActivitiesVisibleLocked(null, 0);
2261 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002262 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002263
2264 // Mark the point when the activity is resuming
2265 // TODO: To be more accurate, the mark should be before the onCreate,
2266 // not after the onResume. But for subsequent starts, onResume is fine.
2267 if (next.app != null) {
2268 synchronized (mProcessStatsThread) {
2269 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2270 }
2271 } else {
2272 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 }
2275
2276 /**
2277 * Make sure that all activities that need to be visible (that is, they
2278 * currently can be seen by the user) actually are.
2279 */
2280 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2281 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002282 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002283 TAG, "ensureActivitiesVisible behind " + top
2284 + " configChanges=0x" + Integer.toHexString(configChanges));
2285
2286 // If the top activity is not fullscreen, then we need to
2287 // make sure any activities under it are now visible.
2288 final int count = mHistory.size();
2289 int i = count-1;
2290 while (mHistory.get(i) != top) {
2291 i--;
2292 }
2293 HistoryRecord r;
2294 boolean behindFullscreen = false;
2295 for (; i>=0; i--) {
2296 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002297 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002298 TAG, "Make visible? " + r + " finishing=" + r.finishing
2299 + " state=" + r.state);
2300 if (r.finishing) {
2301 continue;
2302 }
2303
2304 final boolean doThisProcess = onlyThisProcess == null
2305 || onlyThisProcess.equals(r.processName);
2306
2307 // First: if this is not the current activity being started, make
2308 // sure it matches the current configuration.
2309 if (r != starting && doThisProcess) {
2310 ensureActivityConfigurationLocked(r, 0);
2311 }
2312
2313 if (r.app == null || r.app.thread == null) {
2314 if (onlyThisProcess == null
2315 || onlyThisProcess.equals(r.processName)) {
2316 // This activity needs to be visible, but isn't even
2317 // running... get it started, but don't resume it
2318 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002319 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320 TAG, "Start and freeze screen for " + r);
2321 if (r != starting) {
2322 r.startFreezingScreenLocked(r.app, configChanges);
2323 }
2324 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002325 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 TAG, "Starting and making visible: " + r);
2327 mWindowManager.setAppVisibility(r, true);
2328 }
2329 if (r != starting) {
2330 startSpecificActivityLocked(r, false, false);
2331 }
2332 }
2333
2334 } else if (r.visible) {
2335 // If this activity is already visible, then there is nothing
2336 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002337 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 TAG, "Skipping: already visible at " + r);
2339 r.stopFreezingScreenLocked(false);
2340
2341 } else if (onlyThisProcess == null) {
2342 // This activity is not currently visible, but is running.
2343 // Tell it to become visible.
2344 r.visible = true;
2345 if (r.state != ActivityState.RESUMED && r != starting) {
2346 // If this activity is paused, tell it
2347 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002348 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002349 TAG, "Making visible and scheduling visibility: " + r);
2350 try {
2351 mWindowManager.setAppVisibility(r, true);
2352 r.app.thread.scheduleWindowVisibility(r, true);
2353 r.stopFreezingScreenLocked(false);
2354 } catch (Exception e) {
2355 // Just skip on any failure; we'll make it
2356 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002357 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 + r.intent.getComponent(), e);
2359 }
2360 }
2361 }
2362
2363 // Aggregate current change flags.
2364 configChanges |= r.configChangeFlags;
2365
2366 if (r.fullscreen) {
2367 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002368 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 TAG, "Stopping: fullscreen at " + r);
2370 behindFullscreen = true;
2371 i--;
2372 break;
2373 }
2374 }
2375
2376 // Now for any activities that aren't visible to the user, make
2377 // sure they no longer are keeping the screen frozen.
2378 while (i >= 0) {
2379 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002380 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002381 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2382 + " state=" + r.state
2383 + " behindFullscreen=" + behindFullscreen);
2384 if (!r.finishing) {
2385 if (behindFullscreen) {
2386 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002387 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002388 TAG, "Making invisible: " + r);
2389 r.visible = false;
2390 try {
2391 mWindowManager.setAppVisibility(r, false);
2392 if ((r.state == ActivityState.STOPPING
2393 || r.state == ActivityState.STOPPED)
2394 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002395 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002396 TAG, "Scheduling invisibility: " + r);
2397 r.app.thread.scheduleWindowVisibility(r, false);
2398 }
2399 } catch (Exception e) {
2400 // Just skip on any failure; we'll make it
2401 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002402 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002403 + r.intent.getComponent(), e);
2404 }
2405 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002406 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002407 TAG, "Already invisible: " + r);
2408 }
2409 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002410 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002411 TAG, "Now behindFullscreen: " + r);
2412 behindFullscreen = true;
2413 }
2414 }
2415 i--;
2416 }
2417 }
2418
2419 /**
2420 * Version of ensureActivitiesVisible that can easily be called anywhere.
2421 */
2422 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2423 int configChanges) {
2424 HistoryRecord r = topRunningActivityLocked(null);
2425 if (r != null) {
2426 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2427 }
2428 }
2429
2430 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2431 if (resumed) {
2432 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2433 } else {
2434 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2435 }
2436 }
2437
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002438 private boolean startHomeActivityLocked() {
2439 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2440 && mTopAction == null) {
2441 // We are running in factory test mode, but unable to find
2442 // the factory test app, so just sit around displaying the
2443 // error message and don't try to start anything.
2444 return false;
2445 }
2446 Intent intent = new Intent(
2447 mTopAction,
2448 mTopData != null ? Uri.parse(mTopData) : null);
2449 intent.setComponent(mTopComponent);
2450 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2451 intent.addCategory(Intent.CATEGORY_HOME);
2452 }
2453 ActivityInfo aInfo =
2454 intent.resolveActivityInfo(mContext.getPackageManager(),
2455 STOCK_PM_FLAGS);
2456 if (aInfo != null) {
2457 intent.setComponent(new ComponentName(
2458 aInfo.applicationInfo.packageName, aInfo.name));
2459 // Don't do this if the home app is currently being
2460 // instrumented.
2461 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2462 aInfo.applicationInfo.uid);
2463 if (app == null || app.instrumentationClass == null) {
2464 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2465 startActivityLocked(null, intent, null, null, 0, aInfo,
2466 null, null, 0, 0, 0, false, false);
2467 }
2468 }
2469
2470
2471 return true;
2472 }
2473
2474 /**
2475 * Starts the "new version setup screen" if appropriate.
2476 */
2477 private void startSetupActivityLocked() {
2478 // Only do this once per boot.
2479 if (mCheckedForSetup) {
2480 return;
2481 }
2482
2483 // We will show this screen if the current one is a different
2484 // version than the last one shown, and we are not running in
2485 // low-level factory test mode.
2486 final ContentResolver resolver = mContext.getContentResolver();
2487 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2488 Settings.Secure.getInt(resolver,
2489 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2490 mCheckedForSetup = true;
2491
2492 // See if we should be showing the platform update setup UI.
2493 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2494 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2495 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2496
2497 // We don't allow third party apps to replace this.
2498 ResolveInfo ri = null;
2499 for (int i=0; ris != null && i<ris.size(); i++) {
2500 if ((ris.get(i).activityInfo.applicationInfo.flags
2501 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2502 ri = ris.get(i);
2503 break;
2504 }
2505 }
2506
2507 if (ri != null) {
2508 String vers = ri.activityInfo.metaData != null
2509 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2510 : null;
2511 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2512 vers = ri.activityInfo.applicationInfo.metaData.getString(
2513 Intent.METADATA_SETUP_VERSION);
2514 }
2515 String lastVers = Settings.Secure.getString(
2516 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2517 if (vers != null && !vers.equals(lastVers)) {
2518 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2519 intent.setComponent(new ComponentName(
2520 ri.activityInfo.packageName, ri.activityInfo.name));
2521 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2522 null, null, 0, 0, 0, false, false);
2523 }
2524 }
2525 }
2526 }
2527
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002528 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002529 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002530
2531 final int identHash = System.identityHashCode(r);
2532 updateUsageStats(r, true);
2533
2534 int i = mWatchers.beginBroadcast();
2535 while (i > 0) {
2536 i--;
2537 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2538 if (w != null) {
2539 try {
2540 w.activityResuming(identHash);
2541 } catch (RemoteException e) {
2542 }
2543 }
2544 }
2545 mWatchers.finishBroadcast();
2546 }
2547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002548 /**
2549 * Ensure that the top activity in the stack is resumed.
2550 *
2551 * @param prev The previously resumed activity, for when in the process
2552 * of pausing; can be null to call from elsewhere.
2553 *
2554 * @return Returns true if something is being resumed, or false if
2555 * nothing happened.
2556 */
2557 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2558 // Find the first activity that is not finishing.
2559 HistoryRecord next = topRunningActivityLocked(null);
2560
2561 // Remember how we'll process this pause/resume situation, and ensure
2562 // that the state is reset however we wind up proceeding.
2563 final boolean userLeaving = mUserLeaving;
2564 mUserLeaving = false;
2565
2566 if (next == null) {
2567 // There are no more activities! Let's just start up the
2568 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002569 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 }
2571
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002572 next.delayedResume = false;
2573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 // If the top activity is the resumed one, nothing to do.
2575 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2576 // Make sure we have executed any pending transitions, since there
2577 // should be nothing left to do at this point.
2578 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002579 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 return false;
2581 }
2582
2583 // If we are sleeping, and there is no resumed activity, and the top
2584 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002585 if ((mSleeping || mShuttingDown)
2586 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 // Make sure we have executed any pending transitions, since there
2588 // should be nothing left to do at this point.
2589 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002590 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 return false;
2592 }
2593
2594 // The activity may be waiting for stop, but that is no longer
2595 // appropriate for it.
2596 mStoppingActivities.remove(next);
2597 mWaitingVisibleActivities.remove(next);
2598
Joe Onorato8a9b2202010-02-26 18:56:32 -08002599 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600
2601 // If we are currently pausing an activity, then don't do anything
2602 // until that is done.
2603 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002604 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 return false;
2606 }
2607
2608 // We need to start pausing the current activity so the top one
2609 // can be resumed...
2610 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002611 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002612 startPausingLocked(userLeaving, false);
2613 return true;
2614 }
2615
2616 if (prev != null && prev != next) {
2617 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2618 prev.waitingVisible = true;
2619 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002620 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 TAG, "Resuming top, waiting visible to hide: " + prev);
2622 } else {
2623 // The next activity is already visible, so hide the previous
2624 // activity's windows right now so we can show the new one ASAP.
2625 // We only do this if the previous is finishing, which should mean
2626 // it is on top of the one being resumed so hiding it quickly
2627 // is good. Otherwise, we want to do the normal route of allowing
2628 // the resumed activity to be shown so we can decide if the
2629 // previous should actually be hidden depending on whether the
2630 // new one is found to be full-screen or not.
2631 if (prev.finishing) {
2632 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002633 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 + prev + ", waitingVisible="
2635 + (prev != null ? prev.waitingVisible : null)
2636 + ", nowVisible=" + next.nowVisible);
2637 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002638 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002639 + prev + ", waitingVisible="
2640 + (prev != null ? prev.waitingVisible : null)
2641 + ", nowVisible=" + next.nowVisible);
2642 }
2643 }
2644 }
2645
2646 // We are starting up the next activity, so tell the window manager
2647 // that the previous one will be hidden soon. This way it can know
2648 // to ignore it when computing the desired screen orientation.
2649 if (prev != null) {
2650 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002651 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002652 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002653 if (mNoAnimActivities.contains(prev)) {
2654 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2655 } else {
2656 mWindowManager.prepareAppTransition(prev.task == next.task
2657 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2658 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002660 mWindowManager.setAppWillBeHidden(prev);
2661 mWindowManager.setAppVisibility(prev, false);
2662 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002663 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002665 if (mNoAnimActivities.contains(next)) {
2666 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2667 } else {
2668 mWindowManager.prepareAppTransition(prev.task == next.task
2669 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2670 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 }
2673 if (false) {
2674 mWindowManager.setAppWillBeHidden(prev);
2675 mWindowManager.setAppVisibility(prev, false);
2676 }
2677 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002678 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002680 if (mNoAnimActivities.contains(next)) {
2681 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2682 } else {
2683 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002685 }
2686
2687 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002688 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689
2690 // This activity is now becoming visible.
2691 mWindowManager.setAppVisibility(next, true);
2692
2693 HistoryRecord lastResumedActivity = mResumedActivity;
2694 ActivityState lastState = next.state;
2695
2696 updateCpuStats();
2697
2698 next.state = ActivityState.RESUMED;
2699 mResumedActivity = next;
2700 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002701 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 updateLRUListLocked(next);
2703
2704 // Have the window manager re-evaluate the orientation of
2705 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002706 boolean updated;
2707 synchronized (this) {
2708 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2709 mConfiguration,
2710 next.mayFreezeScreenLocked(next.app) ? next : null);
2711 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002712 next.frozenBeforeDestroy = true;
2713 }
2714 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002715 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002716 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 // The configuration update wasn't able to keep the existing
2718 // instance of the activity, and instead started a new one.
2719 // We should be all done, but let's just make sure our activity
2720 // is still at the top and schedule another run if something
2721 // weird happened.
2722 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002723 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724 "Activity config changed during resume: " + next
2725 + ", new next: " + nextNext);
2726 if (nextNext != next) {
2727 // Do over!
2728 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2729 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002730 setFocusedActivityLocked(next);
2731 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002733 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 return true;
2735 }
2736
2737 try {
2738 // Deliver all pending results.
2739 ArrayList a = next.results;
2740 if (a != null) {
2741 final int N = a.size();
2742 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002743 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744 TAG, "Delivering results to " + next
2745 + ": " + a);
2746 next.app.thread.scheduleSendResult(next, a);
2747 }
2748 }
2749
2750 if (next.newIntents != null) {
2751 next.app.thread.scheduleNewIntent(next.newIntents, next);
2752 }
2753
Doug Zongker2bec3d42009-12-04 12:52:44 -08002754 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 System.identityHashCode(next),
2756 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002757
2758 next.app.thread.scheduleResumeActivity(next,
2759 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 pauseIfSleepingLocked();
2762
2763 } catch (Exception e) {
2764 // Whoops, need to restart this activity!
2765 next.state = lastState;
2766 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002767 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002768 if (!next.hasBeenLaunched) {
2769 next.hasBeenLaunched = true;
2770 } else {
2771 if (SHOW_APP_STARTING_ICON) {
2772 mWindowManager.setAppStartingWindow(
2773 next, next.packageName, next.theme,
2774 next.nonLocalizedLabel,
2775 next.labelRes, next.icon, null, true);
2776 }
2777 }
2778 startSpecificActivityLocked(next, true, false);
2779 return true;
2780 }
2781
2782 // From this point on, if something goes wrong there is no way
2783 // to recover the activity.
2784 try {
2785 next.visible = true;
2786 completeResumeLocked(next);
2787 } catch (Exception e) {
2788 // If any exception gets thrown, toss away this
2789 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002790 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2792 "resume-exception");
2793 return true;
2794 }
2795
2796 // Didn't need to use the icicle, and it is now out of date.
2797 next.icicle = null;
2798 next.haveState = false;
2799 next.stopped = false;
2800
2801 } else {
2802 // Whoops, need to restart this activity!
2803 if (!next.hasBeenLaunched) {
2804 next.hasBeenLaunched = true;
2805 } else {
2806 if (SHOW_APP_STARTING_ICON) {
2807 mWindowManager.setAppStartingWindow(
2808 next, next.packageName, next.theme,
2809 next.nonLocalizedLabel,
2810 next.labelRes, next.icon, null, true);
2811 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002812 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813 }
2814 startSpecificActivityLocked(next, true, true);
2815 }
2816
2817 return true;
2818 }
2819
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002820 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2821 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002822 final int NH = mHistory.size();
2823
2824 int addPos = -1;
2825
2826 if (!newTask) {
2827 // If starting in an existing task, find where that is...
2828 HistoryRecord next = null;
2829 boolean startIt = true;
2830 for (int i = NH-1; i >= 0; i--) {
2831 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2832 if (p.finishing) {
2833 continue;
2834 }
2835 if (p.task == r.task) {
2836 // Here it is! Now, if this is not yet visible to the
2837 // user, then just add it without starting; it will
2838 // get started when the user navigates back to it.
2839 addPos = i+1;
2840 if (!startIt) {
2841 mHistory.add(addPos, r);
2842 r.inHistory = true;
2843 r.task.numActivities++;
2844 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2845 r.info.screenOrientation, r.fullscreen);
2846 if (VALIDATE_TOKENS) {
2847 mWindowManager.validateAppTokens(mHistory);
2848 }
2849 return;
2850 }
2851 break;
2852 }
2853 if (p.fullscreen) {
2854 startIt = false;
2855 }
2856 next = p;
2857 }
2858 }
2859
2860 // Place a new activity at top of stack, so it is next to interact
2861 // with the user.
2862 if (addPos < 0) {
2863 addPos = mHistory.size();
2864 }
2865
2866 // If we are not placing the new activity frontmost, we do not want
2867 // to deliver the onUserLeaving callback to the actual frontmost
2868 // activity
2869 if (addPos < NH) {
2870 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002871 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872 }
2873
2874 // Slot the activity into the history stack and proceed
2875 mHistory.add(addPos, r);
2876 r.inHistory = true;
2877 r.frontOfTask = newTask;
2878 r.task.numActivities++;
2879 if (NH > 0) {
2880 // We want to show the starting preview window if we are
2881 // switching to a new task, or the next activity's process is
2882 // not currently running.
2883 boolean showStartingIcon = newTask;
2884 ProcessRecord proc = r.app;
2885 if (proc == null) {
2886 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2887 }
2888 if (proc == null || proc.thread == null) {
2889 showStartingIcon = true;
2890 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002891 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002893 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2894 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2895 mNoAnimActivities.add(r);
2896 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2897 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2898 mNoAnimActivities.remove(r);
2899 } else {
2900 mWindowManager.prepareAppTransition(newTask
2901 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2902 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2903 mNoAnimActivities.remove(r);
2904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 mWindowManager.addAppToken(
2906 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2907 boolean doShow = true;
2908 if (newTask) {
2909 // Even though this activity is starting fresh, we still need
2910 // to reset it to make sure we apply affinities to move any
2911 // existing activities from other tasks in to it.
2912 // If the caller has requested that the target task be
2913 // reset, then do so.
2914 if ((r.intent.getFlags()
2915 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2916 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002917 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 }
2919 }
2920 if (SHOW_APP_STARTING_ICON && doShow) {
2921 // Figure out if we are transitioning from another activity that is
2922 // "has the same starting icon" as the next one. This allows the
2923 // window manager to keep the previous window it had previously
2924 // created, if it still had one.
2925 HistoryRecord prev = mResumedActivity;
2926 if (prev != null) {
2927 // We don't want to reuse the previous starting preview if:
2928 // (1) The current activity is in a different task.
2929 if (prev.task != r.task) prev = null;
2930 // (2) The current activity is already displayed.
2931 else if (prev.nowVisible) prev = null;
2932 }
2933 mWindowManager.setAppStartingWindow(
2934 r, r.packageName, r.theme, r.nonLocalizedLabel,
2935 r.labelRes, r.icon, prev, showStartingIcon);
2936 }
2937 } else {
2938 // If this is the first activity, don't do any fancy animations,
2939 // because there is nothing for it to animate on top of.
2940 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2941 r.info.screenOrientation, r.fullscreen);
2942 }
2943 if (VALIDATE_TOKENS) {
2944 mWindowManager.validateAppTokens(mHistory);
2945 }
2946
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002947 if (doResume) {
2948 resumeTopActivityLocked(null);
2949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 }
2951
2952 /**
2953 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002954 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2955 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002956 * an instance of that activity in the stack and, if found, finish all
2957 * activities on top of it and return the instance.
2958 *
2959 * @param newR Description of the new activity being started.
2960 * @return Returns the old activity that should be continue to be used,
2961 * or null if none was found.
2962 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002963 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002964 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002966
2967 // First find the requested task.
2968 while (i > 0) {
2969 i--;
2970 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2971 if (r.task.taskId == taskId) {
2972 i++;
2973 break;
2974 }
2975 }
2976
2977 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002978 while (i > 0) {
2979 i--;
2980 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2981 if (r.finishing) {
2982 continue;
2983 }
2984 if (r.task.taskId != taskId) {
2985 return null;
2986 }
2987 if (r.realActivity.equals(newR.realActivity)) {
2988 // Here it is! Now finish everything in front...
2989 HistoryRecord ret = r;
2990 if (doClear) {
2991 while (i < (mHistory.size()-1)) {
2992 i++;
2993 r = (HistoryRecord)mHistory.get(i);
2994 if (r.finishing) {
2995 continue;
2996 }
2997 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2998 null, "clear")) {
2999 i--;
3000 }
3001 }
3002 }
3003
3004 // Finally, if this is a normal launch mode (that is, not
3005 // expecting onNewIntent()), then we will finish the current
3006 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003007 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3008 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003010 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003011 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003012 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003013 null, "clear");
3014 }
3015 return null;
3016 }
3017 }
3018
3019 return ret;
3020 }
3021 }
3022
3023 return null;
3024 }
3025
3026 /**
3027 * Find the activity in the history stack within the given task. Returns
3028 * the index within the history at which it's found, or < 0 if not found.
3029 */
3030 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3031 int i = mHistory.size();
3032 while (i > 0) {
3033 i--;
3034 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3035 if (candidate.task.taskId != task) {
3036 break;
3037 }
3038 if (candidate.realActivity.equals(r.realActivity)) {
3039 return i;
3040 }
3041 }
3042
3043 return -1;
3044 }
3045
3046 /**
3047 * Reorder the history stack so that the activity at the given index is
3048 * brought to the front.
3049 */
3050 private final HistoryRecord moveActivityToFrontLocked(int where) {
3051 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3052 int top = mHistory.size();
3053 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3054 mHistory.add(top, newTop);
3055 oldTop.frontOfTask = false;
3056 newTop.frontOfTask = true;
3057 return newTop;
3058 }
3059
3060 /**
3061 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3062 * method will be called at the proper time.
3063 */
3064 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3065 boolean sent = false;
3066 if (r.state == ActivityState.RESUMED
3067 && r.app != null && r.app.thread != null) {
3068 try {
3069 ArrayList<Intent> ar = new ArrayList<Intent>();
3070 ar.add(new Intent(intent));
3071 r.app.thread.scheduleNewIntent(ar, r);
3072 sent = true;
3073 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003074 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 }
3076 }
3077 if (!sent) {
3078 r.addNewIntentLocked(new Intent(intent));
3079 }
3080 }
3081
3082 private final void logStartActivity(int tag, HistoryRecord r,
3083 TaskRecord task) {
3084 EventLog.writeEvent(tag,
3085 System.identityHashCode(r), task.taskId,
3086 r.shortComponentName, r.intent.getAction(),
3087 r.intent.getType(), r.intent.getDataString(),
3088 r.intent.getFlags());
3089 }
3090
3091 private final int startActivityLocked(IApplicationThread caller,
3092 Intent intent, String resolvedType,
3093 Uri[] grantedUriPermissions,
3094 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3095 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003096 int callingPid, int callingUid, boolean onlyIfNeeded,
3097 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003098 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003099
3100 HistoryRecord sourceRecord = null;
3101 HistoryRecord resultRecord = null;
3102 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003103 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003104 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3106 if (index >= 0) {
3107 sourceRecord = (HistoryRecord)mHistory.get(index);
3108 if (requestCode >= 0 && !sourceRecord.finishing) {
3109 resultRecord = sourceRecord;
3110 }
3111 }
3112 }
3113
3114 int launchFlags = intent.getFlags();
3115
3116 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3117 && sourceRecord != null) {
3118 // Transfer the result target from the source activity to the new
3119 // one being started, including any failures.
3120 if (requestCode >= 0) {
3121 return START_FORWARD_AND_REQUEST_CONFLICT;
3122 }
3123 resultRecord = sourceRecord.resultTo;
3124 resultWho = sourceRecord.resultWho;
3125 requestCode = sourceRecord.requestCode;
3126 sourceRecord.resultTo = null;
3127 if (resultRecord != null) {
3128 resultRecord.removeResultsLocked(
3129 sourceRecord, resultWho, requestCode);
3130 }
3131 }
3132
3133 int err = START_SUCCESS;
3134
3135 if (intent.getComponent() == null) {
3136 // We couldn't find a class that can handle the given Intent.
3137 // That's the end of that!
3138 err = START_INTENT_NOT_RESOLVED;
3139 }
3140
3141 if (err == START_SUCCESS && aInfo == null) {
3142 // We couldn't find the specific class specified in the Intent.
3143 // Also the end of the line.
3144 err = START_CLASS_NOT_FOUND;
3145 }
3146
3147 ProcessRecord callerApp = null;
3148 if (err == START_SUCCESS && caller != null) {
3149 callerApp = getRecordForAppLocked(caller);
3150 if (callerApp != null) {
3151 callingPid = callerApp.pid;
3152 callingUid = callerApp.info.uid;
3153 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003154 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003155 + " (pid=" + callingPid + ") when starting: "
3156 + intent.toString());
3157 err = START_PERMISSION_DENIED;
3158 }
3159 }
3160
3161 if (err != START_SUCCESS) {
3162 if (resultRecord != null) {
3163 sendActivityResultLocked(-1,
3164 resultRecord, resultWho, requestCode,
3165 Activity.RESULT_CANCELED, null);
3166 }
3167 return err;
3168 }
3169
3170 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3171 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3172 if (perm != PackageManager.PERMISSION_GRANTED) {
3173 if (resultRecord != null) {
3174 sendActivityResultLocked(-1,
3175 resultRecord, resultWho, requestCode,
3176 Activity.RESULT_CANCELED, null);
3177 }
3178 String msg = "Permission Denial: starting " + intent.toString()
3179 + " from " + callerApp + " (pid=" + callingPid
3180 + ", uid=" + callingUid + ")"
3181 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003182 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183 throw new SecurityException(msg);
3184 }
3185
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003186 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 boolean abort = false;
3188 try {
3189 // The Intent we give to the watcher has the extra data
3190 // stripped off, since it can contain private information.
3191 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003192 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003193 aInfo.applicationInfo.packageName);
3194 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003195 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003196 }
3197
3198 if (abort) {
3199 if (resultRecord != null) {
3200 sendActivityResultLocked(-1,
3201 resultRecord, resultWho, requestCode,
3202 Activity.RESULT_CANCELED, null);
3203 }
3204 // We pretend to the caller that it was really started, but
3205 // they will just get a cancel result.
3206 return START_SUCCESS;
3207 }
3208 }
3209
3210 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3211 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003212 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003214 if (mResumedActivity == null
3215 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3216 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3217 PendingActivityLaunch pal = new PendingActivityLaunch();
3218 pal.r = r;
3219 pal.sourceRecord = sourceRecord;
3220 pal.grantedUriPermissions = grantedUriPermissions;
3221 pal.grantedMode = grantedMode;
3222 pal.onlyIfNeeded = onlyIfNeeded;
3223 mPendingActivityLaunches.add(pal);
3224 return START_SWITCHES_CANCELED;
3225 }
3226 }
3227
3228 if (mDidAppSwitch) {
3229 // This is the second allowed switch since we stopped switches,
3230 // so now just generally allow switches. Use case: user presses
3231 // home (switches disabled, switch to home, mDidAppSwitch now true);
3232 // user taps a home icon (coming from home so allowed, we hit here
3233 // and now allow anyone to switch again).
3234 mAppSwitchesAllowedTime = 0;
3235 } else {
3236 mDidAppSwitch = true;
3237 }
3238
3239 doPendingActivityLaunchesLocked(false);
3240
3241 return startActivityUncheckedLocked(r, sourceRecord,
3242 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3243 }
3244
3245 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3246 final int N = mPendingActivityLaunches.size();
3247 if (N <= 0) {
3248 return;
3249 }
3250 for (int i=0; i<N; i++) {
3251 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3252 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3253 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3254 doResume && i == (N-1));
3255 }
3256 mPendingActivityLaunches.clear();
3257 }
3258
3259 private final int startActivityUncheckedLocked(HistoryRecord r,
3260 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3261 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3262 final Intent intent = r.intent;
3263 final int callingUid = r.launchedFromUid;
3264
3265 int launchFlags = intent.getFlags();
3266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 // We'll invoke onUserLeaving before onPause only if the launching
3268 // activity did not explicitly state that this is an automated launch.
3269 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003270 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003271 "startActivity() => mUserLeaving=" + mUserLeaving);
3272
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003273 // If the caller has asked not to resume at this point, we make note
3274 // of this in the record so that we can skip it when trying to find
3275 // the top running activity.
3276 if (!doResume) {
3277 r.delayedResume = true;
3278 }
3279
3280 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3281 != 0 ? r : null;
3282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003283 // If the onlyIfNeeded flag is set, then we can do this if the activity
3284 // being launched is the same as the one making the call... or, as
3285 // a special case, if we do not know the caller then we count the
3286 // current top activity as the caller.
3287 if (onlyIfNeeded) {
3288 HistoryRecord checkedCaller = sourceRecord;
3289 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003290 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003291 }
3292 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3293 // Caller is not the same as launcher, so always needed.
3294 onlyIfNeeded = false;
3295 }
3296 }
3297
3298 if (grantedUriPermissions != null && callingUid > 0) {
3299 for (int i=0; i<grantedUriPermissions.length; i++) {
3300 grantUriPermissionLocked(callingUid, r.packageName,
3301 grantedUriPermissions[i], grantedMode, r);
3302 }
3303 }
3304
3305 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3306 intent, r);
3307
3308 if (sourceRecord == null) {
3309 // This activity is not being started from another... in this
3310 // case we -always- start a new task.
3311 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003312 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 -08003313 + intent);
3314 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3315 }
3316 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3317 // The original activity who is starting us is running as a single
3318 // instance... this new activity it is starting must go on its
3319 // own task.
3320 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3321 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3322 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3323 // The activity being started is a single instance... it always
3324 // gets launched into its own task.
3325 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3326 }
3327
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003328 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 // For whatever reason this activity is being launched into a new
3330 // task... yet the caller has requested a result back. Well, that
3331 // is pretty messed up, so instead immediately send back a cancel
3332 // and let the new task continue launched as normal without a
3333 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003334 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003336 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 Activity.RESULT_CANCELED, null);
3338 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 }
3340
3341 boolean addingToTask = false;
3342 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3343 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3344 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3345 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3346 // If bring to front is requested, and no result is requested, and
3347 // we can find a task that was started with this same
3348 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003349 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003350 // See if there is a task to bring to the front. If this is
3351 // a SINGLE_INSTANCE activity, there can be one and only one
3352 // instance of it in the history, and it is always in its own
3353 // unique task, so we do a special search.
3354 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3355 ? findTaskLocked(intent, r.info)
3356 : findActivityLocked(intent, r.info);
3357 if (taskTop != null) {
3358 if (taskTop.task.intent == null) {
3359 // This task was started because of movement of
3360 // the activity based on affinity... now that we
3361 // are actually launching it, we can assign the
3362 // base intent.
3363 taskTop.task.setIntent(intent, r.info);
3364 }
3365 // If the target task is not in the front, then we need
3366 // to bring it to the front... except... well, with
3367 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3368 // to have the same behavior as if a new instance was
3369 // being started, which means not bringing it to the front
3370 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003371 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 if (curTop.task != taskTop.task) {
3373 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3374 boolean callerAtFront = sourceRecord == null
3375 || curTop.task == sourceRecord.task;
3376 if (callerAtFront) {
3377 // We really do want to push this one into the
3378 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003379 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003380 }
3381 }
3382 // If the caller has requested that the target task be
3383 // reset, then do so.
3384 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3385 taskTop = resetTaskIfNeededLocked(taskTop, r);
3386 }
3387 if (onlyIfNeeded) {
3388 // We don't need to start a new activity, and
3389 // the client said not to do anything if that
3390 // is the case, so this is it! And for paranoia, make
3391 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003392 if (doResume) {
3393 resumeTopActivityLocked(null);
3394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 return START_RETURN_INTENT_TO_CALLER;
3396 }
3397 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3398 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3399 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3400 // In this situation we want to remove all activities
3401 // from the task up to the one being started. In most
3402 // cases this means we are resetting the task to its
3403 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003404 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003405 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003406 if (top != null) {
3407 if (top.frontOfTask) {
3408 // Activity aliases may mean we use different
3409 // intents for the top activity, so make sure
3410 // the task now has the identity of the new
3411 // intent.
3412 top.task.setIntent(r.intent, r.info);
3413 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003414 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003415 deliverNewIntentLocked(top, r.intent);
3416 } else {
3417 // A special case: we need to
3418 // start the activity because it is not currently
3419 // running, and the caller has asked to clear the
3420 // current task to have this activity at the top.
3421 addingToTask = true;
3422 // Now pretend like this activity is being started
3423 // by the top of its task, so it is put in the
3424 // right place.
3425 sourceRecord = taskTop;
3426 }
3427 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3428 // In this case the top activity on the task is the
3429 // same as the one being launched, so we take that
3430 // as a request to bring the task to the foreground.
3431 // If the top activity in the task is the root
3432 // activity, deliver this new intent to it if it
3433 // desires.
3434 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3435 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003436 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 if (taskTop.frontOfTask) {
3438 taskTop.task.setIntent(r.intent, r.info);
3439 }
3440 deliverNewIntentLocked(taskTop, r.intent);
3441 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3442 // In this case we are launching the root activity
3443 // of the task, but with a different intent. We
3444 // should start a new instance on top.
3445 addingToTask = true;
3446 sourceRecord = taskTop;
3447 }
3448 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3449 // In this case an activity is being launched in to an
3450 // existing task, without resetting that task. This
3451 // is typically the situation of launching an activity
3452 // from a notification or shortcut. We want to place
3453 // the new activity on top of the current task.
3454 addingToTask = true;
3455 sourceRecord = taskTop;
3456 } else if (!taskTop.task.rootWasReset) {
3457 // In this case we are launching in to an existing task
3458 // that has not yet been started from its front door.
3459 // The current task has been brought to the front.
3460 // Ideally, we'd probably like to place this new task
3461 // at the bottom of its stack, but that's a little hard
3462 // to do with the current organization of the code so
3463 // for now we'll just drop it.
3464 taskTop.task.setIntent(r.intent, r.info);
3465 }
3466 if (!addingToTask) {
3467 // We didn't do anything... but it was needed (a.k.a., client
3468 // don't use that intent!) And for paranoia, make
3469 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003470 if (doResume) {
3471 resumeTopActivityLocked(null);
3472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 return START_TASK_TO_FRONT;
3474 }
3475 }
3476 }
3477 }
3478
3479 //String uri = r.intent.toURI();
3480 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003481 //Slog.i(TAG, "Given intent: " + r.intent);
3482 //Slog.i(TAG, "URI is: " + uri);
3483 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484
3485 if (r.packageName != null) {
3486 // If the activity being launched is the same as the one currently
3487 // at the top, then we need to check if it should only be launched
3488 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003489 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3490 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003491 if (top.realActivity.equals(r.realActivity)) {
3492 if (top.app != null && top.app.thread != null) {
3493 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3494 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3495 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003496 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 // For paranoia, make sure we have correctly
3498 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003499 if (doResume) {
3500 resumeTopActivityLocked(null);
3501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 if (onlyIfNeeded) {
3503 // We don't need to start a new activity, and
3504 // the client said not to do anything if that
3505 // is the case, so this is it!
3506 return START_RETURN_INTENT_TO_CALLER;
3507 }
3508 deliverNewIntentLocked(top, r.intent);
3509 return START_DELIVERED_TO_TOP;
3510 }
3511 }
3512 }
3513 }
3514
3515 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003516 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003517 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003518 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 Activity.RESULT_CANCELED, null);
3520 }
3521 return START_CLASS_NOT_FOUND;
3522 }
3523
3524 boolean newTask = false;
3525
3526 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003527 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3529 // todo: should do better management of integers.
3530 mCurTask++;
3531 if (mCurTask <= 0) {
3532 mCurTask = 1;
3533 }
3534 r.task = new TaskRecord(mCurTask, r.info, intent,
3535 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003536 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 + " in new task " + r.task);
3538 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003539 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540
3541 } else if (sourceRecord != null) {
3542 if (!addingToTask &&
3543 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3544 // In this case, we are adding the activity to an existing
3545 // task, but the caller has asked to clear that task if the
3546 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003547 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003548 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003549 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003550 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 deliverNewIntentLocked(top, r.intent);
3552 // For paranoia, make sure we have correctly
3553 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003554 if (doResume) {
3555 resumeTopActivityLocked(null);
3556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 return START_DELIVERED_TO_TOP;
3558 }
3559 } else if (!addingToTask &&
3560 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3561 // In this case, we are launching an activity in our own task
3562 // that may already be running somewhere in the history, and
3563 // we want to shuffle it to the front of the stack if so.
3564 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3565 if (where >= 0) {
3566 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003567 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003569 if (doResume) {
3570 resumeTopActivityLocked(null);
3571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 return START_DELIVERED_TO_TOP;
3573 }
3574 }
3575 // An existing activity is starting this new activity, so we want
3576 // to keep the new one in the same task as the one that is starting
3577 // it.
3578 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003579 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 + " in existing task " + r.task);
3581
3582 } else {
3583 // This not being started from an existing activity, and not part
3584 // of a new task... just put it in the top task, though these days
3585 // this case should never happen.
3586 final int N = mHistory.size();
3587 HistoryRecord prev =
3588 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3589 r.task = prev != null
3590 ? prev.task
3591 : new TaskRecord(mCurTask, r.info, intent,
3592 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003593 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 + " in new guessed " + r.task);
3595 }
3596 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003597 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003598 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003599 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003600 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003601 return START_SUCCESS;
3602 }
3603
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003604 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3605 long thisTime, long totalTime) {
3606 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3607 WaitResult w = mWaitingActivityLaunched.get(i);
3608 w.timeout = timeout;
3609 if (r != null) {
3610 w.who = new ComponentName(r.info.packageName, r.info.name);
3611 }
3612 w.thisTime = thisTime;
3613 w.totalTime = totalTime;
3614 }
3615 notify();
3616 }
3617
3618 void reportActivityVisibleLocked(HistoryRecord r) {
3619 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3620 WaitResult w = mWaitingActivityVisible.get(i);
3621 w.timeout = false;
3622 if (r != null) {
3623 w.who = new ComponentName(r.info.packageName, r.info.name);
3624 }
3625 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3626 w.thisTime = w.totalTime;
3627 }
3628 notify();
3629 }
3630
3631 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003632 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3633 int grantedMode, IBinder resultTo,
3634 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003635 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 // Refuse possible leaked file descriptors
3637 if (intent != null && intent.hasFileDescriptors()) {
3638 throw new IllegalArgumentException("File descriptors passed in Intent");
3639 }
3640
The Android Open Source Project4df24232009-03-05 14:34:35 -08003641 final boolean componentSpecified = intent.getComponent() != null;
3642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003643 // Don't modify the client's object!
3644 intent = new Intent(intent);
3645
3646 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 ActivityInfo aInfo;
3648 try {
3649 ResolveInfo rInfo =
3650 ActivityThread.getPackageManager().resolveIntent(
3651 intent, resolvedType,
3652 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003653 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654 aInfo = rInfo != null ? rInfo.activityInfo : null;
3655 } catch (RemoteException e) {
3656 aInfo = null;
3657 }
3658
3659 if (aInfo != null) {
3660 // Store the found target back into the intent, because now that
3661 // we have it we never want to do this again. For example, if the
3662 // user navigates back to this point in the history, we should
3663 // always restart the exact same activity.
3664 intent.setComponent(new ComponentName(
3665 aInfo.applicationInfo.packageName, aInfo.name));
3666
3667 // Don't debug things in the system process
3668 if (debug) {
3669 if (!aInfo.processName.equals("system")) {
3670 setDebugApp(aInfo.processName, true, false);
3671 }
3672 }
3673 }
3674
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003675 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003676 int callingPid;
3677 int callingUid;
3678 if (caller == null) {
3679 callingPid = Binder.getCallingPid();
3680 callingUid = Binder.getCallingUid();
3681 } else {
3682 callingPid = callingUid = -1;
3683 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003684
3685 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003686 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3687 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 int res = startActivityLocked(caller, intent, resolvedType,
3692 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003693 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003694 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003695
Dianne Hackborne2522462010-03-29 18:41:30 -07003696 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003697 // If the caller also wants to switch to a new configuration,
3698 // do so now. This allows a clean switch, as we are waiting
3699 // for the current activity to pause (so we will not destroy
3700 // it), and have not yet started the next activity.
3701 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3702 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003703 mConfigWillChange = false;
3704 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3705 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003706 updateConfigurationLocked(config, null);
3707 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003709 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003710
3711 if (outResult != null) {
3712 outResult.result = res;
3713 if (res == IActivityManager.START_SUCCESS) {
3714 mWaitingActivityLaunched.add(outResult);
3715 do {
3716 try {
3717 wait();
3718 } catch (InterruptedException e) {
3719 }
3720 } while (!outResult.timeout && outResult.who == null);
3721 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3722 HistoryRecord r = this.topRunningActivityLocked(null);
3723 if (r.nowVisible) {
3724 outResult.timeout = false;
3725 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3726 outResult.totalTime = 0;
3727 outResult.thisTime = 0;
3728 } else {
3729 outResult.thisTime = SystemClock.uptimeMillis();
3730 mWaitingActivityVisible.add(outResult);
3731 do {
3732 try {
3733 wait();
3734 } catch (InterruptedException e) {
3735 }
3736 } while (!outResult.timeout && outResult.who == null);
3737 }
3738 }
3739 }
3740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 return res;
3742 }
3743 }
3744
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003745 public final int startActivity(IApplicationThread caller,
3746 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3747 int grantedMode, IBinder resultTo,
3748 String resultWho, int requestCode, boolean onlyIfNeeded,
3749 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003750 return startActivityMayWait(caller, intent, resolvedType,
3751 grantedUriPermissions, grantedMode, resultTo, resultWho,
3752 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003753 }
3754
3755 public final WaitResult startActivityAndWait(IApplicationThread caller,
3756 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3757 int grantedMode, IBinder resultTo,
3758 String resultWho, int requestCode, boolean onlyIfNeeded,
3759 boolean debug) {
3760 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003761 startActivityMayWait(caller, intent, resolvedType,
3762 grantedUriPermissions, grantedMode, resultTo, resultWho,
3763 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003764 return res;
3765 }
3766
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003767 public final int startActivityWithConfig(IApplicationThread caller,
3768 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3769 int grantedMode, IBinder resultTo,
3770 String resultWho, int requestCode, boolean onlyIfNeeded,
3771 boolean debug, Configuration config) {
3772 return startActivityMayWait(caller, intent, resolvedType,
3773 grantedUriPermissions, grantedMode, resultTo, resultWho,
3774 requestCode, onlyIfNeeded, debug, null, config);
3775 }
3776
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003777 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003778 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003779 IBinder resultTo, String resultWho, int requestCode,
3780 int flagsMask, int flagsValues) {
3781 // Refuse possible leaked file descriptors
3782 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3783 throw new IllegalArgumentException("File descriptors passed in Intent");
3784 }
3785
3786 IIntentSender sender = intent.getTarget();
3787 if (!(sender instanceof PendingIntentRecord)) {
3788 throw new IllegalArgumentException("Bad PendingIntent object");
3789 }
3790
3791 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003792
3793 synchronized (this) {
3794 // If this is coming from the currently resumed activity, it is
3795 // effectively saying that app switches are allowed at this point.
3796 if (mResumedActivity != null
3797 && mResumedActivity.info.applicationInfo.uid ==
3798 Binder.getCallingUid()) {
3799 mAppSwitchesAllowedTime = 0;
3800 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003801 }
3802
3803 return pir.sendInner(0, fillInIntent, resolvedType,
3804 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3805 }
3806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 public boolean startNextMatchingActivity(IBinder callingActivity,
3808 Intent intent) {
3809 // Refuse possible leaked file descriptors
3810 if (intent != null && intent.hasFileDescriptors() == true) {
3811 throw new IllegalArgumentException("File descriptors passed in Intent");
3812 }
3813
3814 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003815 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 if (index < 0) {
3817 return false;
3818 }
3819 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3820 if (r.app == null || r.app.thread == null) {
3821 // The caller is not running... d'oh!
3822 return false;
3823 }
3824 intent = new Intent(intent);
3825 // The caller is not allowed to change the data.
3826 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3827 // And we are resetting to find the next component...
3828 intent.setComponent(null);
3829
3830 ActivityInfo aInfo = null;
3831 try {
3832 List<ResolveInfo> resolves =
3833 ActivityThread.getPackageManager().queryIntentActivities(
3834 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003835 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836
3837 // Look for the original activity in the list...
3838 final int N = resolves != null ? resolves.size() : 0;
3839 for (int i=0; i<N; i++) {
3840 ResolveInfo rInfo = resolves.get(i);
3841 if (rInfo.activityInfo.packageName.equals(r.packageName)
3842 && rInfo.activityInfo.name.equals(r.info.name)) {
3843 // We found the current one... the next matching is
3844 // after it.
3845 i++;
3846 if (i<N) {
3847 aInfo = resolves.get(i).activityInfo;
3848 }
3849 break;
3850 }
3851 }
3852 } catch (RemoteException e) {
3853 }
3854
3855 if (aInfo == null) {
3856 // Nobody who is next!
3857 return false;
3858 }
3859
3860 intent.setComponent(new ComponentName(
3861 aInfo.applicationInfo.packageName, aInfo.name));
3862 intent.setFlags(intent.getFlags()&~(
3863 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3864 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3865 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3866 Intent.FLAG_ACTIVITY_NEW_TASK));
3867
3868 // Okay now we need to start the new activity, replacing the
3869 // currently running activity. This is a little tricky because
3870 // we want to start the new one as if the current one is finished,
3871 // but not finish the current one first so that there is no flicker.
3872 // And thus...
3873 final boolean wasFinishing = r.finishing;
3874 r.finishing = true;
3875
3876 // Propagate reply information over to the new activity.
3877 final HistoryRecord resultTo = r.resultTo;
3878 final String resultWho = r.resultWho;
3879 final int requestCode = r.requestCode;
3880 r.resultTo = null;
3881 if (resultTo != null) {
3882 resultTo.removeResultsLocked(r, resultWho, requestCode);
3883 }
3884
3885 final long origId = Binder.clearCallingIdentity();
3886 // XXX we are not dealing with propagating grantedUriPermissions...
3887 // those are not yet exposed to user code, so there is no need.
3888 int res = startActivityLocked(r.app.thread, intent,
3889 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003890 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003891 Binder.restoreCallingIdentity(origId);
3892
3893 r.finishing = wasFinishing;
3894 if (res != START_SUCCESS) {
3895 return false;
3896 }
3897 return true;
3898 }
3899 }
3900
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003901 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003902 Intent intent, String resolvedType, IBinder resultTo,
3903 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003904
3905 // This is so super not safe, that only the system (or okay root)
3906 // can do it.
3907 final int callingUid = Binder.getCallingUid();
3908 if (callingUid != 0 && callingUid != Process.myUid()) {
3909 throw new SecurityException(
3910 "startActivityInPackage only available to the system");
3911 }
3912
The Android Open Source Project4df24232009-03-05 14:34:35 -08003913 final boolean componentSpecified = intent.getComponent() != null;
3914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003915 // Don't modify the client's object!
3916 intent = new Intent(intent);
3917
3918 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919 ActivityInfo aInfo;
3920 try {
3921 ResolveInfo rInfo =
3922 ActivityThread.getPackageManager().resolveIntent(
3923 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003924 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 aInfo = rInfo != null ? rInfo.activityInfo : null;
3926 } catch (RemoteException e) {
3927 aInfo = null;
3928 }
3929
3930 if (aInfo != null) {
3931 // Store the found target back into the intent, because now that
3932 // we have it we never want to do this again. For example, if the
3933 // user navigates back to this point in the history, we should
3934 // always restart the exact same activity.
3935 intent.setComponent(new ComponentName(
3936 aInfo.applicationInfo.packageName, aInfo.name));
3937 }
3938
3939 synchronized(this) {
3940 return startActivityLocked(null, intent, resolvedType,
3941 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003942 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 }
3944 }
3945
Josh Bartel7f208742010-02-25 11:01:44 -06003946 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003947 // Remove any existing entries that are the same kind of task.
3948 int N = mRecentTasks.size();
3949 for (int i=0; i<N; i++) {
3950 TaskRecord tr = mRecentTasks.get(i);
3951 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3952 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3953 mRecentTasks.remove(i);
3954 i--;
3955 N--;
3956 if (task.intent == null) {
3957 // If the new recent task we are adding is not fully
3958 // specified, then replace it with the existing recent task.
3959 task = tr;
3960 }
3961 }
3962 }
3963 if (N >= MAX_RECENT_TASKS) {
3964 mRecentTasks.remove(N-1);
3965 }
3966 mRecentTasks.add(0, task);
3967 }
3968
3969 public void setRequestedOrientation(IBinder token,
3970 int requestedOrientation) {
3971 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003972 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003973 if (index < 0) {
3974 return;
3975 }
3976 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3977 final long origId = Binder.clearCallingIdentity();
3978 mWindowManager.setAppOrientation(r, requestedOrientation);
3979 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003980 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003981 r.mayFreezeScreenLocked(r.app) ? r : null);
3982 if (config != null) {
3983 r.frozenBeforeDestroy = true;
3984 if (!updateConfigurationLocked(config, r)) {
3985 resumeTopActivityLocked(null);
3986 }
3987 }
3988 Binder.restoreCallingIdentity(origId);
3989 }
3990 }
3991
3992 public int getRequestedOrientation(IBinder token) {
3993 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003994 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 if (index < 0) {
3996 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3997 }
3998 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3999 return mWindowManager.getAppOrientation(r);
4000 }
4001 }
4002
4003 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004004 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004005 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4006 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4007 if (!r.finishing) {
4008 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4009 "no-history");
4010 }
4011 } else if (r.app != null && r.app.thread != null) {
4012 if (mFocusedActivity == r) {
4013 setFocusedActivityLocked(topRunningActivityLocked(null));
4014 }
4015 r.resumeKeyDispatchingLocked();
4016 try {
4017 r.stopped = false;
4018 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004019 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004020 TAG, "Stopping visible=" + r.visible + " for " + r);
4021 if (!r.visible) {
4022 mWindowManager.setAppVisibility(r, false);
4023 }
4024 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4025 } catch (Exception e) {
4026 // Maybe just ignore exceptions here... if the process
4027 // has crashed, our death notification will clean things
4028 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004029 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 // Just in case, assume it to be stopped.
4031 r.stopped = true;
4032 r.state = ActivityState.STOPPED;
4033 if (r.configDestroy) {
4034 destroyActivityLocked(r, true);
4035 }
4036 }
4037 }
4038 }
4039
4040 /**
4041 * @return Returns true if the activity is being finished, false if for
4042 * some reason it is being left as-is.
4043 */
4044 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4045 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004046 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004047 TAG, "Finishing activity: token=" + token
4048 + ", result=" + resultCode + ", data=" + resultData);
4049
Dianne Hackborn75b03852009-06-12 15:43:26 -07004050 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004051 if (index < 0) {
4052 return false;
4053 }
4054 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4055
4056 // Is this the last activity left?
4057 boolean lastActivity = true;
4058 for (int i=mHistory.size()-1; i>=0; i--) {
4059 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4060 if (!p.finishing && p != r) {
4061 lastActivity = false;
4062 break;
4063 }
4064 }
4065
4066 // If this is the last activity, but it is the home activity, then
4067 // just don't finish it.
4068 if (lastActivity) {
4069 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4070 return false;
4071 }
4072 }
4073
4074 finishActivityLocked(r, index, resultCode, resultData, reason);
4075 return true;
4076 }
4077
4078 /**
4079 * @return Returns true if this activity has been removed from the history
4080 * list, or false if it is still in the list and will be removed later.
4081 */
4082 private final boolean finishActivityLocked(HistoryRecord r, int index,
4083 int resultCode, Intent resultData, String reason) {
4084 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004085 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086 return false;
4087 }
4088
4089 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004090 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 System.identityHashCode(r),
4092 r.task.taskId, r.shortComponentName, reason);
4093 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004094 if (index < (mHistory.size()-1)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004095 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4096 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004097 if (r.frontOfTask) {
4098 // The next activity is now the front of the task.
4099 next.frontOfTask = true;
4100 }
4101 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4102 // If the caller asked that this activity (and all above it)
4103 // be cleared when the task is reset, don't lose that information,
4104 // but propagate it up to the next activity.
4105 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 }
4108 }
4109
4110 r.pauseKeyDispatchingLocked();
4111 if (mFocusedActivity == r) {
4112 setFocusedActivityLocked(topRunningActivityLocked(null));
4113 }
4114
4115 // send the result
4116 HistoryRecord resultTo = r.resultTo;
4117 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004118 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004119 + " who=" + r.resultWho + " req=" + r.requestCode
4120 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 if (r.info.applicationInfo.uid > 0) {
4122 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4123 r.packageName, resultData, r);
4124 }
4125 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4126 resultData);
4127 r.resultTo = null;
4128 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004129 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130
4131 // Make sure this HistoryRecord is not holding on to other resources,
4132 // because clients have remote IPC references to this object so we
4133 // can't assume that will go away and want to avoid circular IPC refs.
4134 r.results = null;
4135 r.pendingResults = null;
4136 r.newIntents = null;
4137 r.icicle = null;
4138
4139 if (mPendingThumbnails.size() > 0) {
4140 // There are clients waiting to receive thumbnails so, in case
4141 // this is an activity that someone is waiting for, add it
4142 // to the pending list so we can correctly update the clients.
4143 mCancelledThumbnails.add(r);
4144 }
4145
4146 if (mResumedActivity == r) {
4147 boolean endTask = index <= 0
4148 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004149 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 "Prepare close transition: finishing " + r);
4151 mWindowManager.prepareAppTransition(endTask
4152 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4153 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4154
4155 // Tell window manager to prepare for this one to be removed.
4156 mWindowManager.setAppVisibility(r, false);
4157
4158 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004159 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4160 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 startPausingLocked(false, false);
4162 }
4163
4164 } else if (r.state != ActivityState.PAUSING) {
4165 // If the activity is PAUSING, we will complete the finish once
4166 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004167 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 return finishCurrentActivityLocked(r, index,
4169 FINISH_AFTER_PAUSE) == null;
4170 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004171 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 }
4173
4174 return false;
4175 }
4176
4177 private static final int FINISH_IMMEDIATELY = 0;
4178 private static final int FINISH_AFTER_PAUSE = 1;
4179 private static final int FINISH_AFTER_VISIBLE = 2;
4180
4181 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4182 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004183 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004184 if (index < 0) {
4185 return null;
4186 }
4187
4188 return finishCurrentActivityLocked(r, index, mode);
4189 }
4190
4191 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4192 int index, int mode) {
4193 // First things first: if this activity is currently visible,
4194 // and the resumed activity is not yet visible, then hold off on
4195 // finishing until the resumed one becomes visible.
4196 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4197 if (!mStoppingActivities.contains(r)) {
4198 mStoppingActivities.add(r);
4199 if (mStoppingActivities.size() > 3) {
4200 // If we already have a few activities waiting to stop,
4201 // then give up on things going idle and start clearing
4202 // them out.
4203 Message msg = Message.obtain();
4204 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4205 mHandler.sendMessage(msg);
4206 }
4207 }
4208 r.state = ActivityState.STOPPING;
4209 updateOomAdjLocked();
4210 return r;
4211 }
4212
4213 // make sure the record is cleaned out of other places.
4214 mStoppingActivities.remove(r);
4215 mWaitingVisibleActivities.remove(r);
4216 if (mResumedActivity == r) {
4217 mResumedActivity = null;
4218 }
4219 final ActivityState prevState = r.state;
4220 r.state = ActivityState.FINISHING;
4221
4222 if (mode == FINISH_IMMEDIATELY
4223 || prevState == ActivityState.STOPPED
4224 || prevState == ActivityState.INITIALIZING) {
4225 // If this activity is already stopped, we can just finish
4226 // it right now.
4227 return destroyActivityLocked(r, true) ? null : r;
4228 } else {
4229 // Need to go through the full pause cycle to get this
4230 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004231 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 mFinishingActivities.add(r);
4233 resumeTopActivityLocked(null);
4234 }
4235 return r;
4236 }
4237
4238 /**
4239 * This is the internal entry point for handling Activity.finish().
4240 *
4241 * @param token The Binder token referencing the Activity we want to finish.
4242 * @param resultCode Result code, if any, from this Activity.
4243 * @param resultData Result data (Intent), if any, from this Activity.
4244 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004245 * @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 -08004246 */
4247 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4248 // Refuse possible leaked file descriptors
4249 if (resultData != null && resultData.hasFileDescriptors() == true) {
4250 throw new IllegalArgumentException("File descriptors passed in Intent");
4251 }
4252
4253 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004254 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004255 // Find the first activity that is not finishing.
4256 HistoryRecord next = topRunningActivityLocked(token, 0);
4257 if (next != null) {
4258 // ask watcher if this is allowed
4259 boolean resumeOK = true;
4260 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004261 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004262 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004263 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004264 }
4265
4266 if (!resumeOK) {
4267 return false;
4268 }
4269 }
4270 }
4271 final long origId = Binder.clearCallingIdentity();
4272 boolean res = requestFinishActivityLocked(token, resultCode,
4273 resultData, "app-request");
4274 Binder.restoreCallingIdentity(origId);
4275 return res;
4276 }
4277 }
4278
4279 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4280 String resultWho, int requestCode, int resultCode, Intent data) {
4281
4282 if (callingUid > 0) {
4283 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4284 data, r);
4285 }
4286
Joe Onorato8a9b2202010-02-26 18:56:32 -08004287 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004288 + " : who=" + resultWho + " req=" + requestCode
4289 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4291 try {
4292 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4293 list.add(new ResultInfo(resultWho, requestCode,
4294 resultCode, data));
4295 r.app.thread.scheduleSendResult(r, list);
4296 return;
4297 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004298 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004299 }
4300 }
4301
4302 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4303 }
4304
4305 public final void finishSubActivity(IBinder token, String resultWho,
4306 int requestCode) {
4307 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004308 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004309 if (index < 0) {
4310 return;
4311 }
4312 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4313
4314 final long origId = Binder.clearCallingIdentity();
4315
4316 int i;
4317 for (i=mHistory.size()-1; i>=0; i--) {
4318 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4319 if (r.resultTo == self && r.requestCode == requestCode) {
4320 if ((r.resultWho == null && resultWho == null) ||
4321 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4322 finishActivityLocked(r, i,
4323 Activity.RESULT_CANCELED, null, "request-sub");
4324 }
4325 }
4326 }
4327
4328 Binder.restoreCallingIdentity(origId);
4329 }
4330 }
4331
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004332 public boolean willActivityBeVisible(IBinder token) {
4333 synchronized(this) {
4334 int i;
4335 for (i=mHistory.size()-1; i>=0; i--) {
4336 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4337 if (r == token) {
4338 return true;
4339 }
4340 if (r.fullscreen && !r.finishing) {
4341 return false;
4342 }
4343 }
4344 return true;
4345 }
4346 }
4347
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004348 public void overridePendingTransition(IBinder token, String packageName,
4349 int enterAnim, int exitAnim) {
4350 synchronized(this) {
4351 int index = indexOfTokenLocked(token);
4352 if (index < 0) {
4353 return;
4354 }
4355 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4356
4357 final long origId = Binder.clearCallingIdentity();
4358
4359 if (self.state == ActivityState.RESUMED
4360 || self.state == ActivityState.PAUSING) {
4361 mWindowManager.overridePendingAppTransition(packageName,
4362 enterAnim, exitAnim);
4363 }
4364
4365 Binder.restoreCallingIdentity(origId);
4366 }
4367 }
4368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 /**
4370 * Perform clean-up of service connections in an activity record.
4371 */
4372 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4373 // Throw away any services that have been bound by this activity.
4374 if (r.connections != null) {
4375 Iterator<ConnectionRecord> it = r.connections.iterator();
4376 while (it.hasNext()) {
4377 ConnectionRecord c = it.next();
4378 removeConnectionLocked(c, null, r);
4379 }
4380 r.connections = null;
4381 }
4382 }
4383
4384 /**
4385 * Perform the common clean-up of an activity record. This is called both
4386 * as part of destroyActivityLocked() (when destroying the client-side
4387 * representation) and cleaning things up as a result of its hosting
4388 * processing going away, in which case there is no remaining client-side
4389 * state to destroy so only the cleanup here is needed.
4390 */
4391 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4392 if (mResumedActivity == r) {
4393 mResumedActivity = null;
4394 }
4395 if (mFocusedActivity == r) {
4396 mFocusedActivity = null;
4397 }
4398
4399 r.configDestroy = false;
4400 r.frozenBeforeDestroy = false;
4401
4402 // Make sure this record is no longer in the pending finishes list.
4403 // This could happen, for example, if we are trimming activities
4404 // down to the max limit while they are still waiting to finish.
4405 mFinishingActivities.remove(r);
4406 mWaitingVisibleActivities.remove(r);
4407
4408 // Remove any pending results.
4409 if (r.finishing && r.pendingResults != null) {
4410 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4411 PendingIntentRecord rec = apr.get();
4412 if (rec != null) {
4413 cancelIntentSenderLocked(rec, false);
4414 }
4415 }
4416 r.pendingResults = null;
4417 }
4418
4419 if (cleanServices) {
4420 cleanUpActivityServicesLocked(r);
4421 }
4422
4423 if (mPendingThumbnails.size() > 0) {
4424 // There are clients waiting to receive thumbnails so, in case
4425 // this is an activity that someone is waiting for, add it
4426 // to the pending list so we can correctly update the clients.
4427 mCancelledThumbnails.add(r);
4428 }
4429
4430 // Get rid of any pending idle timeouts.
4431 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4432 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4433 }
4434
4435 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4436 if (r.state != ActivityState.DESTROYED) {
4437 mHistory.remove(r);
4438 r.inHistory = false;
4439 r.state = ActivityState.DESTROYED;
4440 mWindowManager.removeAppToken(r);
4441 if (VALIDATE_TOKENS) {
4442 mWindowManager.validateAppTokens(mHistory);
4443 }
4444 cleanUpActivityServicesLocked(r);
4445 removeActivityUriPermissionsLocked(r);
4446 }
4447 }
4448
4449 /**
4450 * Destroy the current CLIENT SIDE instance of an activity. This may be
4451 * called both when actually finishing an activity, or when performing
4452 * a configuration switch where we destroy the current client-side object
4453 * but then create a new client-side object for this same HistoryRecord.
4454 */
4455 private final boolean destroyActivityLocked(HistoryRecord r,
4456 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004457 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 TAG, "Removing activity: token=" + r
4459 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004460 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 System.identityHashCode(r),
4462 r.task.taskId, r.shortComponentName);
4463
4464 boolean removedFromHistory = false;
4465
4466 cleanUpActivityLocked(r, false);
4467
Dianne Hackborn03abb812010-01-04 18:43:19 -08004468 final boolean hadApp = r.app != null;
4469
4470 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004471 if (removeFromApp) {
4472 int idx = r.app.activities.indexOf(r);
4473 if (idx >= 0) {
4474 r.app.activities.remove(idx);
4475 }
4476 if (r.persistent) {
4477 decPersistentCountLocked(r.app);
4478 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004479 if (r.app.activities.size() == 0) {
4480 // No longer have activities, so update location in
4481 // LRU list.
4482 updateLruProcessLocked(r.app, true, false);
4483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 }
4485
4486 boolean skipDestroy = false;
4487
4488 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004489 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4491 r.configChangeFlags);
4492 } catch (Exception e) {
4493 // We can just ignore exceptions here... if the process
4494 // has crashed, our death notification will clean things
4495 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004496 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 if (r.finishing) {
4498 removeActivityFromHistoryLocked(r);
4499 removedFromHistory = true;
4500 skipDestroy = true;
4501 }
4502 }
4503
4504 r.app = null;
4505 r.nowVisible = false;
4506
4507 if (r.finishing && !skipDestroy) {
4508 r.state = ActivityState.DESTROYING;
4509 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4510 msg.obj = r;
4511 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4512 } else {
4513 r.state = ActivityState.DESTROYED;
4514 }
4515 } else {
4516 // remove this record from the history.
4517 if (r.finishing) {
4518 removeActivityFromHistoryLocked(r);
4519 removedFromHistory = true;
4520 } else {
4521 r.state = ActivityState.DESTROYED;
4522 }
4523 }
4524
4525 r.configChangeFlags = 0;
4526
Dianne Hackborn03abb812010-01-04 18:43:19 -08004527 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004528 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004529 }
4530
4531 return removedFromHistory;
4532 }
4533
Dianne Hackborn03abb812010-01-04 18:43:19 -08004534 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004535 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004536 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537 TAG, "Removing app " + app + " from list " + list
4538 + " with " + i + " entries");
4539 while (i > 0) {
4540 i--;
4541 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004542 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004543 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4544 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004545 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004546 list.remove(i);
4547 }
4548 }
4549 }
4550
4551 /**
4552 * Main function for removing an existing process from the activity manager
4553 * as a result of that process going away. Clears out all connections
4554 * to the process.
4555 */
4556 private final void handleAppDiedLocked(ProcessRecord app,
4557 boolean restarting) {
4558 cleanUpApplicationRecordLocked(app, restarting, -1);
4559 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004560 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 }
4562
4563 // Just in case...
4564 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004565 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004566 mPausingActivity = null;
4567 }
4568 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4569 mLastPausedActivity = null;
4570 }
4571
4572 // Remove this application's activities from active lists.
4573 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4574 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4575 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4576 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4577
4578 boolean atTop = true;
4579 boolean hasVisibleActivities = false;
4580
4581 // Clean out the history list.
4582 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004583 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584 TAG, "Removing app " + app + " from history with " + i + " entries");
4585 while (i > 0) {
4586 i--;
4587 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004588 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004589 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4590 if (r.app == app) {
4591 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004592 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 TAG, "Removing this entry! frozen=" + r.haveState
4594 + " finishing=" + r.finishing);
4595 mHistory.remove(i);
4596
4597 r.inHistory = false;
4598 mWindowManager.removeAppToken(r);
4599 if (VALIDATE_TOKENS) {
4600 mWindowManager.validateAppTokens(mHistory);
4601 }
4602 removeActivityUriPermissionsLocked(r);
4603
4604 } else {
4605 // We have the current state for this activity, so
4606 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004607 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 TAG, "Keeping entry, setting app to null");
4609 if (r.visible) {
4610 hasVisibleActivities = true;
4611 }
4612 r.app = null;
4613 r.nowVisible = false;
4614 if (!r.haveState) {
4615 r.icicle = null;
4616 }
4617 }
4618
4619 cleanUpActivityLocked(r, true);
4620 r.state = ActivityState.STOPPED;
4621 }
4622 atTop = false;
4623 }
4624
4625 app.activities.clear();
4626
4627 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004628 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 + " running instrumentation " + app.instrumentationClass);
4630 Bundle info = new Bundle();
4631 info.putString("shortMsg", "Process crashed.");
4632 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4633 }
4634
4635 if (!restarting) {
4636 if (!resumeTopActivityLocked(null)) {
4637 // If there was nothing to resume, and we are not already
4638 // restarting this process, but there is a visible activity that
4639 // is hosted by the process... then make sure all visible
4640 // activities are running, taking care of restarting this
4641 // process.
4642 if (hasVisibleActivities) {
4643 ensureActivitiesVisibleLocked(null, 0);
4644 }
4645 }
4646 }
4647 }
4648
4649 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4650 IBinder threadBinder = thread.asBinder();
4651
4652 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004653 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4654 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4656 return i;
4657 }
4658 }
4659 return -1;
4660 }
4661
4662 private final ProcessRecord getRecordForAppLocked(
4663 IApplicationThread thread) {
4664 if (thread == null) {
4665 return null;
4666 }
4667
4668 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004669 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 }
4671
4672 private final void appDiedLocked(ProcessRecord app, int pid,
4673 IApplicationThread thread) {
4674
4675 mProcDeaths[0]++;
4676
Magnus Edlund7bb25812010-02-24 15:45:06 +01004677 // Clean up already done if the process has been re-started.
4678 if (app.pid == pid && app.thread != null &&
4679 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004680 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004681 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004682 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004683 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 TAG, "Dying app: " + app + ", pid: " + pid
4685 + ", thread: " + thread.asBinder());
4686 boolean doLowMem = app.instrumentationClass == null;
4687 handleAppDiedLocked(app, false);
4688
4689 if (doLowMem) {
4690 // If there are no longer any background processes running,
4691 // and the app that died was not running instrumentation,
4692 // then tell everyone we are now low on memory.
4693 boolean haveBg = false;
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.setAdj >= HIDDEN_APP_MIN_ADJ) {
4697 haveBg = true;
4698 break;
4699 }
4700 }
4701
4702 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004703 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004704 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004705 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004706 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4707 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004708 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004709 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4710 // The low memory report is overriding any current
4711 // state for a GC request. Make sure to do
4712 // visible/foreground processes first.
4713 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4714 rec.lastRequestedGc = 0;
4715 } else {
4716 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004718 rec.reportLowMemory = true;
4719 rec.lastLowMemory = now;
4720 mProcessesToGc.remove(rec);
4721 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 }
4723 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004724 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004725 }
4726 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004727 } else if (app.pid != pid) {
4728 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004729 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004730 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004731 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004732 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004733 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 + thread.asBinder());
4735 }
4736 }
4737
Dan Egnor42471dd2010-01-07 17:25:22 -08004738 /**
4739 * If a stack trace dump file is configured, dump process stack traces.
4740 * @param pids of dalvik VM processes to dump stack traces for
4741 * @return file containing stack traces, or null if no dump file is configured
4742 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004743 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004744 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4745 if (tracesPath == null || tracesPath.length() == 0) {
4746 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004748
4749 File tracesFile = new File(tracesPath);
4750 try {
4751 File tracesDir = tracesFile.getParentFile();
4752 if (!tracesDir.exists()) tracesFile.mkdirs();
4753 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4754
4755 if (tracesFile.exists()) tracesFile.delete();
4756 tracesFile.createNewFile();
4757 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4758 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004759 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004760 return null;
4761 }
4762
4763 // Use a FileObserver to detect when traces finish writing.
4764 // The order of traces is considered important to maintain for legibility.
4765 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4766 public synchronized void onEvent(int event, String path) { notify(); }
4767 };
4768
4769 try {
4770 observer.startWatching();
4771 int num = pids.size();
4772 for (int i = 0; i < num; i++) {
4773 synchronized (observer) {
4774 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4775 observer.wait(200); // Wait for write-close, give up after 200msec
4776 }
4777 }
4778 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004779 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004780 } finally {
4781 observer.stopWatching();
4782 }
4783
4784 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004785 }
4786
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004787 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08004788 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004789 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004790
4791 synchronized (this) {
4792 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4793 if (mShuttingDown) {
4794 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
4795 return;
4796 } else if (app.notResponding) {
4797 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
4798 return;
4799 } else if (app.crashing) {
4800 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
4801 return;
4802 }
4803
4804 // In case we come through here for the same app before completing
4805 // this one, mark as anring now so we will bail out.
4806 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08004807
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004808 // Log the ANR to the event log.
4809 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4810 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08004811
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004812 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4813 pids.add(app.pid);
4814
4815 int parentPid = app.pid;
4816 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4817 if (parentPid != app.pid) pids.add(parentPid);
4818
4819 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08004820
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004821 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4822 ProcessRecord r = mLruProcesses.get(i);
4823 if (r != null && r.thread != null) {
4824 int pid = r.pid;
4825 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
4826 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 }
4828 }
4829
Dan Egnor42471dd2010-01-07 17:25:22 -08004830 File tracesFile = dumpStackTraces(pids);
4831
4832 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004833 StringBuilder info = mStringBuilder;
4834 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004835 info.append("ANR in ").append(app.processName);
4836 if (activity != null && activity.shortComponentName != null) {
4837 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004838 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004839 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004841 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004842 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004843 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004844 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004846
Dan Egnor42471dd2010-01-07 17:25:22 -08004847 String cpuInfo = null;
4848 if (MONITOR_CPU_USAGE) {
4849 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004850 synchronized (mProcessStatsThread) {
4851 cpuInfo = mProcessStats.printCurrentState();
4852 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004853 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004854 }
4855
Joe Onorato8a9b2202010-02-26 18:56:32 -08004856 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004857 if (tracesFile == null) {
4858 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4859 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4860 }
4861
4862 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4863
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004864 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004866 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4867 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004869 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4870 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004871 }
4872 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004873 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 }
4875 }
4876
Dan Egnor42471dd2010-01-07 17:25:22 -08004877 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4878 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4879 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004880
4881 synchronized (this) {
4882 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4883 Process.killProcess(app.pid);
4884 return;
4885 }
4886
4887 // Set the app's notResponding state, and look up the errorReportReceiver
4888 makeAppNotRespondingLocked(app,
4889 activity != null ? activity.shortComponentName : null,
4890 annotation != null ? "ANR " + annotation : "ANR",
4891 info.toString());
4892
4893 // Bring up the infamous App Not Responding dialog
4894 Message msg = Message.obtain();
4895 HashMap map = new HashMap();
4896 msg.what = SHOW_NOT_RESPONDING_MSG;
4897 msg.obj = map;
4898 map.put("app", app);
4899 if (activity != null) {
4900 map.put("activity", activity);
4901 }
4902
4903 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08004904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004905 }
4906
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004907 private final void decPersistentCountLocked(ProcessRecord app)
4908 {
4909 app.persistentActivities--;
4910 if (app.persistentActivities > 0) {
4911 // Still more of 'em...
4912 return;
4913 }
4914 if (app.persistent) {
4915 // Ah, but the application itself is persistent. Whatever!
4916 return;
4917 }
4918
4919 // App is no longer persistent... make sure it and the ones
4920 // following it in the LRU list have the correc oom_adj.
4921 updateOomAdjLocked();
4922 }
4923
4924 public void setPersistent(IBinder token, boolean isPersistent) {
4925 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4926 != PackageManager.PERMISSION_GRANTED) {
4927 String msg = "Permission Denial: setPersistent() from pid="
4928 + Binder.getCallingPid()
4929 + ", uid=" + Binder.getCallingUid()
4930 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004931 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004932 throw new SecurityException(msg);
4933 }
4934
4935 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004936 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 if (index < 0) {
4938 return;
4939 }
4940 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4941 ProcessRecord app = r.app;
4942
Joe Onorato8a9b2202010-02-26 18:56:32 -08004943 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 TAG, "Setting persistence " + isPersistent + ": " + r);
4945
4946 if (isPersistent) {
4947 if (r.persistent) {
4948 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004949 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950 return;
4951 }
4952 r.persistent = true;
4953 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004954 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004955 if (app.persistentActivities > 1) {
4956 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004957 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958 return;
4959 }
4960 if (app.persistent) {
4961 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004962 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 return;
4964 }
4965
4966 // App is now persistent... make sure it and the ones
4967 // following it now have the correct oom_adj.
4968 final long origId = Binder.clearCallingIdentity();
4969 updateOomAdjLocked();
4970 Binder.restoreCallingIdentity(origId);
4971
4972 } else {
4973 if (!r.persistent) {
4974 // Okay okay, I heard you already!
4975 return;
4976 }
4977 r.persistent = false;
4978 final long origId = Binder.clearCallingIdentity();
4979 decPersistentCountLocked(app);
4980 Binder.restoreCallingIdentity(origId);
4981
4982 }
4983 }
4984 }
4985
4986 public boolean clearApplicationUserData(final String packageName,
4987 final IPackageDataObserver observer) {
4988 int uid = Binder.getCallingUid();
4989 int pid = Binder.getCallingPid();
4990 long callingId = Binder.clearCallingIdentity();
4991 try {
4992 IPackageManager pm = ActivityThread.getPackageManager();
4993 int pkgUid = -1;
4994 synchronized(this) {
4995 try {
4996 pkgUid = pm.getPackageUid(packageName);
4997 } catch (RemoteException e) {
4998 }
4999 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005000 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 return false;
5002 }
5003 if (uid == pkgUid || checkComponentPermission(
5004 android.Manifest.permission.CLEAR_APP_USER_DATA,
5005 pid, uid, -1)
5006 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005007 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 } else {
5009 throw new SecurityException(pid+" does not have permission:"+
5010 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5011 "for process:"+packageName);
5012 }
5013 }
5014
5015 try {
5016 //clear application user data
5017 pm.clearApplicationUserData(packageName, observer);
5018 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5019 Uri.fromParts("package", packageName, null));
5020 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005021 synchronized (this) {
5022 broadcastIntentLocked(null, null, intent,
5023 null, null, 0, null, null, null,
5024 false, false, MY_PID, Process.SYSTEM_UID);
5025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 } catch (RemoteException e) {
5027 }
5028 } finally {
5029 Binder.restoreCallingIdentity(callingId);
5030 }
5031 return true;
5032 }
5033
Dianne Hackborn03abb812010-01-04 18:43:19 -08005034 public void killBackgroundProcesses(final String packageName) {
5035 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5036 != PackageManager.PERMISSION_GRANTED &&
5037 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5038 != PackageManager.PERMISSION_GRANTED) {
5039 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005040 + Binder.getCallingPid()
5041 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005042 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005043 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005044 throw new SecurityException(msg);
5045 }
5046
5047 long callingId = Binder.clearCallingIdentity();
5048 try {
5049 IPackageManager pm = ActivityThread.getPackageManager();
5050 int pkgUid = -1;
5051 synchronized(this) {
5052 try {
5053 pkgUid = pm.getPackageUid(packageName);
5054 } catch (RemoteException e) {
5055 }
5056 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005057 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058 return;
5059 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005060 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005061 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005062 }
5063 } finally {
5064 Binder.restoreCallingIdentity(callingId);
5065 }
5066 }
5067
5068 public void forceStopPackage(final String packageName) {
5069 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5070 != PackageManager.PERMISSION_GRANTED) {
5071 String msg = "Permission Denial: forceStopPackage() from pid="
5072 + Binder.getCallingPid()
5073 + ", uid=" + Binder.getCallingUid()
5074 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005075 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005076 throw new SecurityException(msg);
5077 }
5078
5079 long callingId = Binder.clearCallingIdentity();
5080 try {
5081 IPackageManager pm = ActivityThread.getPackageManager();
5082 int pkgUid = -1;
5083 synchronized(this) {
5084 try {
5085 pkgUid = pm.getPackageUid(packageName);
5086 } catch (RemoteException e) {
5087 }
5088 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005089 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005090 return;
5091 }
5092 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 }
5094 } finally {
5095 Binder.restoreCallingIdentity(callingId);
5096 }
5097 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005098
5099 /*
5100 * The pkg name and uid have to be specified.
5101 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5102 */
5103 public void killApplicationWithUid(String pkg, int uid) {
5104 if (pkg == null) {
5105 return;
5106 }
5107 // Make sure the uid is valid.
5108 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005109 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005110 return;
5111 }
5112 int callerUid = Binder.getCallingUid();
5113 // Only the system server can kill an application
5114 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005115 // Post an aysnc message to kill the application
5116 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5117 msg.arg1 = uid;
5118 msg.arg2 = 0;
5119 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005120 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005121 } else {
5122 throw new SecurityException(callerUid + " cannot kill pkg: " +
5123 pkg);
5124 }
5125 }
5126
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005127 public void closeSystemDialogs(String reason) {
5128 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5129 if (reason != null) {
5130 intent.putExtra("reason", reason);
5131 }
5132
5133 final int uid = Binder.getCallingUid();
5134 final long origId = Binder.clearCallingIdentity();
5135 synchronized (this) {
5136 int i = mWatchers.beginBroadcast();
5137 while (i > 0) {
5138 i--;
5139 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5140 if (w != null) {
5141 try {
5142 w.closingSystemDialogs(reason);
5143 } catch (RemoteException e) {
5144 }
5145 }
5146 }
5147 mWatchers.finishBroadcast();
5148
Dianne Hackbornffa42482009-09-23 22:20:11 -07005149 mWindowManager.closeSystemDialogs(reason);
5150
5151 for (i=mHistory.size()-1; i>=0; i--) {
5152 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5153 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5154 finishActivityLocked(r, i,
5155 Activity.RESULT_CANCELED, null, "close-sys");
5156 }
5157 }
5158
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005159 broadcastIntentLocked(null, null, intent, null,
5160 null, 0, null, null, null, false, false, -1, uid);
5161 }
5162 Binder.restoreCallingIdentity(origId);
5163 }
5164
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005165 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005166 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005167 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5168 for (int i=pids.length-1; i>=0; i--) {
5169 infos[i] = new Debug.MemoryInfo();
5170 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005171 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005172 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005173 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005174
5175 public void killApplicationProcess(String processName, int uid) {
5176 if (processName == null) {
5177 return;
5178 }
5179
5180 int callerUid = Binder.getCallingUid();
5181 // Only the system server can kill an application
5182 if (callerUid == Process.SYSTEM_UID) {
5183 synchronized (this) {
5184 ProcessRecord app = getProcessRecordLocked(processName, uid);
5185 if (app != null) {
5186 try {
5187 app.thread.scheduleSuicide();
5188 } catch (RemoteException e) {
5189 // If the other end already died, then our work here is done.
5190 }
5191 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005192 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005193 + processName + " / " + uid);
5194 }
5195 }
5196 } else {
5197 throw new SecurityException(callerUid + " cannot kill app process: " +
5198 processName);
5199 }
5200 }
5201
Dianne Hackborn03abb812010-01-04 18:43:19 -08005202 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005203 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5205 Uri.fromParts("package", packageName, null));
5206 intent.putExtra(Intent.EXTRA_UID, uid);
5207 broadcastIntentLocked(null, null, intent,
5208 null, null, 0, null, null, null,
5209 false, false, MY_PID, Process.SYSTEM_UID);
5210 }
5211
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005212 private final boolean killPackageProcessesLocked(String packageName, int uid,
5213 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005214 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005215
Dianne Hackborn03abb812010-01-04 18:43:19 -08005216 // Remove all processes this package may have touched: all with the
5217 // same UID (except for the system or root user), and all whose name
5218 // matches the package name.
5219 final String procNamePrefix = packageName + ":";
5220 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5221 final int NA = apps.size();
5222 for (int ia=0; ia<NA; ia++) {
5223 ProcessRecord app = apps.valueAt(ia);
5224 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005225 if (doit) {
5226 procs.add(app);
5227 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005228 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5229 || app.processName.equals(packageName)
5230 || app.processName.startsWith(procNamePrefix)) {
5231 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005232 if (!doit) {
5233 return true;
5234 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005235 app.removed = true;
5236 procs.add(app);
5237 }
5238 }
5239 }
5240 }
5241
5242 int N = procs.size();
5243 for (int i=0; i<N; i++) {
5244 removeProcessLocked(procs.get(i), callerWillRestart);
5245 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005246 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005247 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005248
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005249 private final boolean forceStopPackageLocked(String name, int uid,
5250 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 int i, N;
5252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005253 if (uid < 0) {
5254 try {
5255 uid = ActivityThread.getPackageManager().getPackageUid(name);
5256 } catch (RemoteException e) {
5257 }
5258 }
5259
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005260 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005261 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005262
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005263 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5264 while (badApps.hasNext()) {
5265 SparseArray<Long> ba = badApps.next();
5266 if (ba.get(uid) != null) {
5267 badApps.remove();
5268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 }
5270 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005271
5272 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5273 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274
5275 for (i=mHistory.size()-1; i>=0; i--) {
5276 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5277 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005278 if (!doit) {
5279 return true;
5280 }
5281 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005282 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 if (r.app != null) {
5284 r.app.removed = true;
5285 }
5286 r.app = null;
5287 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5288 }
5289 }
5290
5291 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5292 for (ServiceRecord service : mServices.values()) {
5293 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005294 if (!doit) {
5295 return true;
5296 }
5297 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005298 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 if (service.app != null) {
5300 service.app.removed = true;
5301 }
5302 service.app = null;
5303 services.add(service);
5304 }
5305 }
5306
5307 N = services.size();
5308 for (i=0; i<N; i++) {
5309 bringDownServiceLocked(services.get(i), true);
5310 }
5311
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005312 if (doit) {
5313 if (purgeCache) {
5314 AttributeCache ac = AttributeCache.instance();
5315 if (ac != null) {
5316 ac.removePackage(name);
5317 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005318 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005319 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005320 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005321
5322 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 }
5324
5325 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5326 final String name = app.processName;
5327 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005328 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 TAG, "Force removing process " + app + " (" + name
5330 + "/" + uid + ")");
5331
5332 mProcessNames.remove(name, uid);
5333 boolean needRestart = false;
5334 if (app.pid > 0 && app.pid != MY_PID) {
5335 int pid = app.pid;
5336 synchronized (mPidsSelfLocked) {
5337 mPidsSelfLocked.remove(pid);
5338 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5339 }
5340 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005341 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 Process.killProcess(pid);
5343
5344 if (app.persistent) {
5345 if (!callerWillRestart) {
5346 addAppLocked(app.info);
5347 } else {
5348 needRestart = true;
5349 }
5350 }
5351 } else {
5352 mRemovedProcesses.add(app);
5353 }
5354
5355 return needRestart;
5356 }
5357
5358 private final void processStartTimedOutLocked(ProcessRecord app) {
5359 final int pid = app.pid;
5360 boolean gone = false;
5361 synchronized (mPidsSelfLocked) {
5362 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5363 if (knownApp != null && knownApp.thread == null) {
5364 mPidsSelfLocked.remove(pid);
5365 gone = true;
5366 }
5367 }
5368
5369 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005370 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005371 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005372 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005373 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005374 // Take care of any launching providers waiting for this process.
5375 checkAppInLaunchingProvidersLocked(app, true);
5376 // Take care of any services that are waiting for the process.
5377 for (int i=0; i<mPendingServices.size(); i++) {
5378 ServiceRecord sr = mPendingServices.get(i);
5379 if (app.info.uid == sr.appInfo.uid
5380 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005381 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005382 mPendingServices.remove(i);
5383 i--;
5384 bringDownServiceLocked(sr, true);
5385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005387 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005388 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005389 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005390 try {
5391 IBackupManager bm = IBackupManager.Stub.asInterface(
5392 ServiceManager.getService(Context.BACKUP_SERVICE));
5393 bm.agentDisconnected(app.info.packageName);
5394 } catch (RemoteException e) {
5395 // Can't happen; the backup manager is local
5396 }
5397 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005398 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005399 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005400 mPendingBroadcast = null;
5401 scheduleBroadcastsLocked();
5402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005403 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005404 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005405 }
5406 }
5407
5408 private final boolean attachApplicationLocked(IApplicationThread thread,
5409 int pid) {
5410
5411 // Find the application record that is being attached... either via
5412 // the pid if we are running in multiple processes, or just pull the
5413 // next app record if we are emulating process with anonymous threads.
5414 ProcessRecord app;
5415 if (pid != MY_PID && pid >= 0) {
5416 synchronized (mPidsSelfLocked) {
5417 app = mPidsSelfLocked.get(pid);
5418 }
5419 } else if (mStartingProcesses.size() > 0) {
5420 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005421 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005422 } else {
5423 app = null;
5424 }
5425
5426 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005427 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005428 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005429 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005430 if (pid > 0 && pid != MY_PID) {
5431 Process.killProcess(pid);
5432 } else {
5433 try {
5434 thread.scheduleExit();
5435 } catch (Exception e) {
5436 // Ignore exceptions.
5437 }
5438 }
5439 return false;
5440 }
5441
5442 // If this application record is still attached to a previous
5443 // process, clean it up now.
5444 if (app.thread != null) {
5445 handleAppDiedLocked(app, true);
5446 }
5447
5448 // Tell the process all about itself.
5449
Joe Onorato8a9b2202010-02-26 18:56:32 -08005450 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 TAG, "Binding process pid " + pid + " to record " + app);
5452
5453 String processName = app.processName;
5454 try {
5455 thread.asBinder().linkToDeath(new AppDeathRecipient(
5456 app, pid, thread), 0);
5457 } catch (RemoteException e) {
5458 app.resetPackageList();
5459 startProcessLocked(app, "link fail", processName);
5460 return false;
5461 }
5462
Doug Zongker2bec3d42009-12-04 12:52:44 -08005463 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005464
5465 app.thread = thread;
5466 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005467 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5468 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 app.forcingToForeground = null;
5470 app.foregroundServices = false;
5471 app.debugging = false;
5472
5473 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5474
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005475 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5476 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005477
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005478 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005479 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005480 }
5481
Joe Onorato8a9b2202010-02-26 18:56:32 -08005482 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005483 TAG, "New app record " + app
5484 + " thread=" + thread.asBinder() + " pid=" + pid);
5485 try {
5486 int testMode = IApplicationThread.DEBUG_OFF;
5487 if (mDebugApp != null && mDebugApp.equals(processName)) {
5488 testMode = mWaitForDebugger
5489 ? IApplicationThread.DEBUG_WAIT
5490 : IApplicationThread.DEBUG_ON;
5491 app.debugging = true;
5492 if (mDebugTransient) {
5493 mDebugApp = mOrigDebugApp;
5494 mWaitForDebugger = mOrigWaitForDebugger;
5495 }
5496 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005497
Christopher Tate181fafa2009-05-14 11:12:14 -07005498 // If the app is being launched for restore or full backup, set it up specially
5499 boolean isRestrictedBackupMode = false;
5500 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5501 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5502 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5503 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005504
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005505 ensurePackageDexOpt(app.instrumentationInfo != null
5506 ? app.instrumentationInfo.packageName
5507 : app.info.packageName);
5508 if (app.instrumentationClass != null) {
5509 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005510 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005511 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005512 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005513 thread.bindApplication(processName, app.instrumentationInfo != null
5514 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005515 app.instrumentationClass, app.instrumentationProfileFile,
5516 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005517 isRestrictedBackupMode || !normalMode,
5518 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005519 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005520 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 } catch (Exception e) {
5522 // todo: Yikes! What should we do? For now we will try to
5523 // start another process, but that could easily get us in
5524 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005525 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526
5527 app.resetPackageList();
5528 startProcessLocked(app, "bind fail", processName);
5529 return false;
5530 }
5531
5532 // Remove this record from the list of starting applications.
5533 mPersistentStartingProcesses.remove(app);
5534 mProcessesOnHold.remove(app);
5535
5536 boolean badApp = false;
5537 boolean didSomething = false;
5538
5539 // See if the top visible activity is waiting to run in this process...
5540 HistoryRecord hr = topRunningActivityLocked(null);
5541 if (hr != null) {
5542 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5543 && processName.equals(hr.processName)) {
5544 try {
5545 if (realStartActivityLocked(hr, app, true, true)) {
5546 didSomething = true;
5547 }
5548 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005549 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005550 + hr.intent.getComponent().flattenToShortString(), e);
5551 badApp = true;
5552 }
5553 } else {
5554 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5555 }
5556 }
5557
5558 // Find any services that should be running in this process...
5559 if (!badApp && mPendingServices.size() > 0) {
5560 ServiceRecord sr = null;
5561 try {
5562 for (int i=0; i<mPendingServices.size(); i++) {
5563 sr = mPendingServices.get(i);
5564 if (app.info.uid != sr.appInfo.uid
5565 || !processName.equals(sr.processName)) {
5566 continue;
5567 }
5568
5569 mPendingServices.remove(i);
5570 i--;
5571 realStartServiceLocked(sr, app);
5572 didSomething = true;
5573 }
5574 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005575 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 + sr.shortName, e);
5577 badApp = true;
5578 }
5579 }
5580
5581 // Check if the next broadcast receiver is in this process...
5582 BroadcastRecord br = mPendingBroadcast;
5583 if (!badApp && br != null && br.curApp == app) {
5584 try {
5585 mPendingBroadcast = null;
5586 processCurBroadcastLocked(br, app);
5587 didSomething = true;
5588 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005589 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005590 + br.curComponent.flattenToShortString(), e);
5591 badApp = true;
5592 logBroadcastReceiverDiscard(br);
5593 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5594 br.resultExtras, br.resultAbort, true);
5595 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005596 // We need to reset the state if we fails to start the receiver.
5597 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005598 }
5599 }
5600
Christopher Tate181fafa2009-05-14 11:12:14 -07005601 // Check whether the next backup agent is in this process...
5602 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005603 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005604 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005605 try {
5606 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5607 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005608 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005609 e.printStackTrace();
5610 }
5611 }
5612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 if (badApp) {
5614 // todo: Also need to kill application to deal with all
5615 // kinds of exceptions.
5616 handleAppDiedLocked(app, false);
5617 return false;
5618 }
5619
5620 if (!didSomething) {
5621 updateOomAdjLocked();
5622 }
5623
5624 return true;
5625 }
5626
5627 public final void attachApplication(IApplicationThread thread) {
5628 synchronized (this) {
5629 int callingPid = Binder.getCallingPid();
5630 final long origId = Binder.clearCallingIdentity();
5631 attachApplicationLocked(thread, callingPid);
5632 Binder.restoreCallingIdentity(origId);
5633 }
5634 }
5635
Dianne Hackborne88846e2009-09-30 21:34:25 -07005636 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005637 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005638 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005639 Binder.restoreCallingIdentity(origId);
5640 }
5641
5642 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5643 boolean remove) {
5644 int N = mStoppingActivities.size();
5645 if (N <= 0) return null;
5646
5647 ArrayList<HistoryRecord> stops = null;
5648
5649 final boolean nowVisible = mResumedActivity != null
5650 && mResumedActivity.nowVisible
5651 && !mResumedActivity.waitingVisible;
5652 for (int i=0; i<N; i++) {
5653 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005654 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 + nowVisible + " waitingVisible=" + s.waitingVisible
5656 + " finishing=" + s.finishing);
5657 if (s.waitingVisible && nowVisible) {
5658 mWaitingVisibleActivities.remove(s);
5659 s.waitingVisible = false;
5660 if (s.finishing) {
5661 // If this activity is finishing, it is sitting on top of
5662 // everyone else but we now know it is no longer needed...
5663 // so get rid of it. Otherwise, we need to go through the
5664 // normal flow and hide it once we determine that it is
5665 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005666 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667 mWindowManager.setAppVisibility(s, false);
5668 }
5669 }
5670 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005671 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 if (stops == null) {
5673 stops = new ArrayList<HistoryRecord>();
5674 }
5675 stops.add(s);
5676 mStoppingActivities.remove(i);
5677 N--;
5678 i--;
5679 }
5680 }
5681
5682 return stops;
5683 }
5684
5685 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005686 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005687 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005688 mWindowManager.enableScreenAfterBoot();
5689 }
5690
Dianne Hackborne88846e2009-09-30 21:34:25 -07005691 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5692 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005693 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005694
5695 ArrayList<HistoryRecord> stops = null;
5696 ArrayList<HistoryRecord> finishes = null;
5697 ArrayList<HistoryRecord> thumbnails = null;
5698 int NS = 0;
5699 int NF = 0;
5700 int NT = 0;
5701 IApplicationThread sendThumbnail = null;
5702 boolean booting = false;
5703 boolean enableScreen = false;
5704
5705 synchronized (this) {
5706 if (token != null) {
5707 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5708 }
5709
5710 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005711 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 if (index >= 0) {
5713 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5714
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005715 if (fromTimeout) {
5716 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5717 }
5718
Dianne Hackborne88846e2009-09-30 21:34:25 -07005719 // This is a hack to semi-deal with a race condition
5720 // in the client where it can be constructed with a
5721 // newer configuration from when we asked it to launch.
5722 // We'll update with whatever configuration it now says
5723 // it used to launch.
5724 if (config != null) {
5725 r.configuration = config;
5726 }
5727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005728 // No longer need to keep the device awake.
5729 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5730 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5731 mLaunchingActivity.release();
5732 }
5733
5734 // We are now idle. If someone is waiting for a thumbnail from
5735 // us, we can now deliver.
5736 r.idle = true;
5737 scheduleAppGcsLocked();
5738 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5739 sendThumbnail = r.app.thread;
5740 r.thumbnailNeeded = false;
5741 }
5742
5743 // If this activity is fullscreen, set up to hide those under it.
5744
Joe Onorato8a9b2202010-02-26 18:56:32 -08005745 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005746 ensureActivitiesVisibleLocked(null, 0);
5747
Joe Onorato8a9b2202010-02-26 18:56:32 -08005748 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005749 if (!mBooted && !fromTimeout) {
5750 mBooted = true;
5751 enableScreen = true;
5752 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005753
5754 } else if (fromTimeout) {
5755 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005756 }
5757
5758 // Atomically retrieve all of the other things to do.
5759 stops = processStoppingActivitiesLocked(true);
5760 NS = stops != null ? stops.size() : 0;
5761 if ((NF=mFinishingActivities.size()) > 0) {
5762 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5763 mFinishingActivities.clear();
5764 }
5765 if ((NT=mCancelledThumbnails.size()) > 0) {
5766 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5767 mCancelledThumbnails.clear();
5768 }
5769
5770 booting = mBooting;
5771 mBooting = false;
5772 }
5773
5774 int i;
5775
5776 // Send thumbnail if requested.
5777 if (sendThumbnail != null) {
5778 try {
5779 sendThumbnail.requestThumbnail(token);
5780 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005781 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005782 sendPendingThumbnail(null, token, null, null, true);
5783 }
5784 }
5785
5786 // Stop any activities that are scheduled to do so but have been
5787 // waiting for the next one to start.
5788 for (i=0; i<NS; i++) {
5789 HistoryRecord r = (HistoryRecord)stops.get(i);
5790 synchronized (this) {
5791 if (r.finishing) {
5792 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5793 } else {
5794 stopActivityLocked(r);
5795 }
5796 }
5797 }
5798
5799 // Finish any activities that are scheduled to do so but have been
5800 // waiting for the next one to start.
5801 for (i=0; i<NF; i++) {
5802 HistoryRecord r = (HistoryRecord)finishes.get(i);
5803 synchronized (this) {
5804 destroyActivityLocked(r, true);
5805 }
5806 }
5807
5808 // Report back to any thumbnail receivers.
5809 for (i=0; i<NT; i++) {
5810 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5811 sendPendingThumbnail(r, null, null, null, true);
5812 }
5813
5814 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005815 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005816 }
5817
5818 trimApplications();
5819 //dump();
5820 //mWindowManager.dump();
5821
5822 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005823 enableScreenAfterBoot();
5824 }
5825 }
5826
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005827 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005828 IntentFilter pkgFilter = new IntentFilter();
5829 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5830 pkgFilter.addDataScheme("package");
5831 mContext.registerReceiver(new BroadcastReceiver() {
5832 @Override
5833 public void onReceive(Context context, Intent intent) {
5834 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5835 if (pkgs != null) {
5836 for (String pkg : pkgs) {
5837 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5838 setResultCode(Activity.RESULT_OK);
5839 return;
5840 }
5841 }
5842 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005843 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005844 }, pkgFilter);
5845
5846 synchronized (this) {
5847 // Ensure that any processes we had put on hold are now started
5848 // up.
5849 final int NP = mProcessesOnHold.size();
5850 if (NP > 0) {
5851 ArrayList<ProcessRecord> procs =
5852 new ArrayList<ProcessRecord>(mProcessesOnHold);
5853 for (int ip=0; ip<NP; ip++) {
5854 this.startProcessLocked(procs.get(ip), "on-hold", null);
5855 }
5856 }
5857
5858 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5859 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005860 broadcastIntentLocked(null, null,
5861 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5862 null, null, 0, null, null,
5863 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5864 false, false, MY_PID, Process.SYSTEM_UID);
5865 }
5866 }
5867 }
5868
5869 final void ensureBootCompleted() {
5870 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005871 boolean enableScreen;
5872 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005873 booting = mBooting;
5874 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005875 enableScreen = !mBooted;
5876 mBooted = true;
5877 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005878
5879 if (booting) {
5880 finishBooting();
5881 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005882
5883 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005884 enableScreenAfterBoot();
5885 }
5886 }
5887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005888 public final void activityPaused(IBinder token, Bundle icicle) {
5889 // Refuse possible leaked file descriptors
5890 if (icicle != null && icicle.hasFileDescriptors()) {
5891 throw new IllegalArgumentException("File descriptors passed in Bundle");
5892 }
5893
5894 final long origId = Binder.clearCallingIdentity();
5895 activityPaused(token, icicle, false);
5896 Binder.restoreCallingIdentity(origId);
5897 }
5898
5899 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005900 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005901 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5902 + ", timeout=" + timeout);
5903
5904 HistoryRecord r = null;
5905
5906 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005907 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005908 if (index >= 0) {
5909 r = (HistoryRecord)mHistory.get(index);
5910 if (!timeout) {
5911 r.icicle = icicle;
5912 r.haveState = true;
5913 }
5914 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5915 if (mPausingActivity == r) {
5916 r.state = ActivityState.PAUSED;
5917 completePauseLocked();
5918 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005919 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005920 System.identityHashCode(r), r.shortComponentName,
5921 mPausingActivity != null
5922 ? mPausingActivity.shortComponentName : "(none)");
5923 }
5924 }
5925 }
5926 }
5927
5928 public final void activityStopped(IBinder token, Bitmap thumbnail,
5929 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005930 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 TAG, "Activity stopped: token=" + token);
5932
5933 HistoryRecord r = null;
5934
5935 final long origId = Binder.clearCallingIdentity();
5936
5937 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005938 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005939 if (index >= 0) {
5940 r = (HistoryRecord)mHistory.get(index);
5941 r.thumbnail = thumbnail;
5942 r.description = description;
5943 r.stopped = true;
5944 r.state = ActivityState.STOPPED;
5945 if (!r.finishing) {
5946 if (r.configDestroy) {
5947 destroyActivityLocked(r, true);
5948 resumeTopActivityLocked(null);
5949 }
5950 }
5951 }
5952 }
5953
5954 if (r != null) {
5955 sendPendingThumbnail(r, null, null, null, false);
5956 }
5957
5958 trimApplications();
5959
5960 Binder.restoreCallingIdentity(origId);
5961 }
5962
5963 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005964 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005965 synchronized (this) {
5966 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5967
Dianne Hackborn75b03852009-06-12 15:43:26 -07005968 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005969 if (index >= 0) {
5970 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5971 if (r.state == ActivityState.DESTROYING) {
5972 final long origId = Binder.clearCallingIdentity();
5973 removeActivityFromHistoryLocked(r);
5974 Binder.restoreCallingIdentity(origId);
5975 }
5976 }
5977 }
5978 }
5979
5980 public String getCallingPackage(IBinder token) {
5981 synchronized (this) {
5982 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005983 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 }
5985 }
5986
5987 public ComponentName getCallingActivity(IBinder token) {
5988 synchronized (this) {
5989 HistoryRecord r = getCallingRecordLocked(token);
5990 return r != null ? r.intent.getComponent() : null;
5991 }
5992 }
5993
5994 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005995 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 if (index >= 0) {
5997 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5998 if (r != null) {
5999 return r.resultTo;
6000 }
6001 }
6002 return null;
6003 }
6004
6005 public ComponentName getActivityClassForToken(IBinder token) {
6006 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006007 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006008 if (index >= 0) {
6009 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6010 return r.intent.getComponent();
6011 }
6012 return null;
6013 }
6014 }
6015
6016 public String getPackageForToken(IBinder token) {
6017 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006018 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006019 if (index >= 0) {
6020 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6021 return r.packageName;
6022 }
6023 return null;
6024 }
6025 }
6026
6027 public IIntentSender getIntentSender(int type,
6028 String packageName, IBinder token, String resultWho,
6029 int requestCode, Intent intent, String resolvedType, int flags) {
6030 // Refuse possible leaked file descriptors
6031 if (intent != null && intent.hasFileDescriptors() == true) {
6032 throw new IllegalArgumentException("File descriptors passed in Intent");
6033 }
6034
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006035 if (type == INTENT_SENDER_BROADCAST) {
6036 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6037 throw new IllegalArgumentException(
6038 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6039 }
6040 }
6041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 synchronized(this) {
6043 int callingUid = Binder.getCallingUid();
6044 try {
6045 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6046 Process.supportsProcesses()) {
6047 int uid = ActivityThread.getPackageManager()
6048 .getPackageUid(packageName);
6049 if (uid != Binder.getCallingUid()) {
6050 String msg = "Permission Denial: getIntentSender() from pid="
6051 + Binder.getCallingPid()
6052 + ", uid=" + Binder.getCallingUid()
6053 + ", (need uid=" + uid + ")"
6054 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006055 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 throw new SecurityException(msg);
6057 }
6058 }
6059 } catch (RemoteException e) {
6060 throw new SecurityException(e);
6061 }
6062 HistoryRecord activity = null;
6063 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006064 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006065 if (index < 0) {
6066 return null;
6067 }
6068 activity = (HistoryRecord)mHistory.get(index);
6069 if (activity.finishing) {
6070 return null;
6071 }
6072 }
6073
6074 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6075 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6076 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6077 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6078 |PendingIntent.FLAG_UPDATE_CURRENT);
6079
6080 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6081 type, packageName, activity, resultWho,
6082 requestCode, intent, resolvedType, flags);
6083 WeakReference<PendingIntentRecord> ref;
6084 ref = mIntentSenderRecords.get(key);
6085 PendingIntentRecord rec = ref != null ? ref.get() : null;
6086 if (rec != null) {
6087 if (!cancelCurrent) {
6088 if (updateCurrent) {
6089 rec.key.requestIntent.replaceExtras(intent);
6090 }
6091 return rec;
6092 }
6093 rec.canceled = true;
6094 mIntentSenderRecords.remove(key);
6095 }
6096 if (noCreate) {
6097 return rec;
6098 }
6099 rec = new PendingIntentRecord(this, key, callingUid);
6100 mIntentSenderRecords.put(key, rec.ref);
6101 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6102 if (activity.pendingResults == null) {
6103 activity.pendingResults
6104 = new HashSet<WeakReference<PendingIntentRecord>>();
6105 }
6106 activity.pendingResults.add(rec.ref);
6107 }
6108 return rec;
6109 }
6110 }
6111
6112 public void cancelIntentSender(IIntentSender sender) {
6113 if (!(sender instanceof PendingIntentRecord)) {
6114 return;
6115 }
6116 synchronized(this) {
6117 PendingIntentRecord rec = (PendingIntentRecord)sender;
6118 try {
6119 int uid = ActivityThread.getPackageManager()
6120 .getPackageUid(rec.key.packageName);
6121 if (uid != Binder.getCallingUid()) {
6122 String msg = "Permission Denial: cancelIntentSender() from pid="
6123 + Binder.getCallingPid()
6124 + ", uid=" + Binder.getCallingUid()
6125 + " is not allowed to cancel packges "
6126 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006127 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006128 throw new SecurityException(msg);
6129 }
6130 } catch (RemoteException e) {
6131 throw new SecurityException(e);
6132 }
6133 cancelIntentSenderLocked(rec, true);
6134 }
6135 }
6136
6137 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6138 rec.canceled = true;
6139 mIntentSenderRecords.remove(rec.key);
6140 if (cleanActivity && rec.key.activity != null) {
6141 rec.key.activity.pendingResults.remove(rec.ref);
6142 }
6143 }
6144
6145 public String getPackageForIntentSender(IIntentSender pendingResult) {
6146 if (!(pendingResult instanceof PendingIntentRecord)) {
6147 return null;
6148 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006149 try {
6150 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6151 return res.key.packageName;
6152 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006153 }
6154 return null;
6155 }
6156
6157 public void setProcessLimit(int max) {
6158 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6159 "setProcessLimit()");
6160 mProcessLimit = max;
6161 }
6162
6163 public int getProcessLimit() {
6164 return mProcessLimit;
6165 }
6166
6167 void foregroundTokenDied(ForegroundToken token) {
6168 synchronized (ActivityManagerService.this) {
6169 synchronized (mPidsSelfLocked) {
6170 ForegroundToken cur
6171 = mForegroundProcesses.get(token.pid);
6172 if (cur != token) {
6173 return;
6174 }
6175 mForegroundProcesses.remove(token.pid);
6176 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6177 if (pr == null) {
6178 return;
6179 }
6180 pr.forcingToForeground = null;
6181 pr.foregroundServices = false;
6182 }
6183 updateOomAdjLocked();
6184 }
6185 }
6186
6187 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6188 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6189 "setProcessForeground()");
6190 synchronized(this) {
6191 boolean changed = false;
6192
6193 synchronized (mPidsSelfLocked) {
6194 ProcessRecord pr = mPidsSelfLocked.get(pid);
6195 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006196 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006197 return;
6198 }
6199 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6200 if (oldToken != null) {
6201 oldToken.token.unlinkToDeath(oldToken, 0);
6202 mForegroundProcesses.remove(pid);
6203 pr.forcingToForeground = null;
6204 changed = true;
6205 }
6206 if (isForeground && token != null) {
6207 ForegroundToken newToken = new ForegroundToken() {
6208 public void binderDied() {
6209 foregroundTokenDied(this);
6210 }
6211 };
6212 newToken.pid = pid;
6213 newToken.token = token;
6214 try {
6215 token.linkToDeath(newToken, 0);
6216 mForegroundProcesses.put(pid, newToken);
6217 pr.forcingToForeground = token;
6218 changed = true;
6219 } catch (RemoteException e) {
6220 // If the process died while doing this, we will later
6221 // do the cleanup with the process death link.
6222 }
6223 }
6224 }
6225
6226 if (changed) {
6227 updateOomAdjLocked();
6228 }
6229 }
6230 }
6231
6232 // =========================================================
6233 // PERMISSIONS
6234 // =========================================================
6235
6236 static class PermissionController extends IPermissionController.Stub {
6237 ActivityManagerService mActivityManagerService;
6238 PermissionController(ActivityManagerService activityManagerService) {
6239 mActivityManagerService = activityManagerService;
6240 }
6241
6242 public boolean checkPermission(String permission, int pid, int uid) {
6243 return mActivityManagerService.checkPermission(permission, pid,
6244 uid) == PackageManager.PERMISSION_GRANTED;
6245 }
6246 }
6247
6248 /**
6249 * This can be called with or without the global lock held.
6250 */
6251 int checkComponentPermission(String permission, int pid, int uid,
6252 int reqUid) {
6253 // We might be performing an operation on behalf of an indirect binder
6254 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6255 // client identity accordingly before proceeding.
6256 Identity tlsIdentity = sCallerIdentity.get();
6257 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006258 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006259 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6260 uid = tlsIdentity.uid;
6261 pid = tlsIdentity.pid;
6262 }
6263
6264 // Root, system server and our own process get to do everything.
6265 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6266 !Process.supportsProcesses()) {
6267 return PackageManager.PERMISSION_GRANTED;
6268 }
6269 // If the target requires a specific UID, always fail for others.
6270 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006271 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006272 return PackageManager.PERMISSION_DENIED;
6273 }
6274 if (permission == null) {
6275 return PackageManager.PERMISSION_GRANTED;
6276 }
6277 try {
6278 return ActivityThread.getPackageManager()
6279 .checkUidPermission(permission, uid);
6280 } catch (RemoteException e) {
6281 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006282 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006283 }
6284 return PackageManager.PERMISSION_DENIED;
6285 }
6286
6287 /**
6288 * As the only public entry point for permissions checking, this method
6289 * can enforce the semantic that requesting a check on a null global
6290 * permission is automatically denied. (Internally a null permission
6291 * string is used when calling {@link #checkComponentPermission} in cases
6292 * when only uid-based security is needed.)
6293 *
6294 * This can be called with or without the global lock held.
6295 */
6296 public int checkPermission(String permission, int pid, int uid) {
6297 if (permission == null) {
6298 return PackageManager.PERMISSION_DENIED;
6299 }
6300 return checkComponentPermission(permission, pid, uid, -1);
6301 }
6302
6303 /**
6304 * Binder IPC calls go through the public entry point.
6305 * This can be called with or without the global lock held.
6306 */
6307 int checkCallingPermission(String permission) {
6308 return checkPermission(permission,
6309 Binder.getCallingPid(),
6310 Binder.getCallingUid());
6311 }
6312
6313 /**
6314 * This can be called with or without the global lock held.
6315 */
6316 void enforceCallingPermission(String permission, String func) {
6317 if (checkCallingPermission(permission)
6318 == PackageManager.PERMISSION_GRANTED) {
6319 return;
6320 }
6321
6322 String msg = "Permission Denial: " + func + " from pid="
6323 + Binder.getCallingPid()
6324 + ", uid=" + Binder.getCallingUid()
6325 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006326 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 throw new SecurityException(msg);
6328 }
6329
6330 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6331 ProviderInfo pi, int uid, int modeFlags) {
6332 try {
6333 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6334 if ((pi.readPermission != null) &&
6335 (pm.checkUidPermission(pi.readPermission, uid)
6336 != PackageManager.PERMISSION_GRANTED)) {
6337 return false;
6338 }
6339 }
6340 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6341 if ((pi.writePermission != null) &&
6342 (pm.checkUidPermission(pi.writePermission, uid)
6343 != PackageManager.PERMISSION_GRANTED)) {
6344 return false;
6345 }
6346 }
6347 return true;
6348 } catch (RemoteException e) {
6349 return false;
6350 }
6351 }
6352
6353 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6354 int modeFlags) {
6355 // Root gets to do everything.
6356 if (uid == 0 || !Process.supportsProcesses()) {
6357 return true;
6358 }
6359 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6360 if (perms == null) return false;
6361 UriPermission perm = perms.get(uri);
6362 if (perm == null) return false;
6363 return (modeFlags&perm.modeFlags) == modeFlags;
6364 }
6365
6366 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6367 // Another redirected-binder-call permissions check as in
6368 // {@link checkComponentPermission}.
6369 Identity tlsIdentity = sCallerIdentity.get();
6370 if (tlsIdentity != null) {
6371 uid = tlsIdentity.uid;
6372 pid = tlsIdentity.pid;
6373 }
6374
6375 // Our own process gets to do everything.
6376 if (pid == MY_PID) {
6377 return PackageManager.PERMISSION_GRANTED;
6378 }
6379 synchronized(this) {
6380 return checkUriPermissionLocked(uri, uid, modeFlags)
6381 ? PackageManager.PERMISSION_GRANTED
6382 : PackageManager.PERMISSION_DENIED;
6383 }
6384 }
6385
6386 private void grantUriPermissionLocked(int callingUid,
6387 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6388 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6389 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6390 if (modeFlags == 0) {
6391 return;
6392 }
6393
Joe Onorato8a9b2202010-02-26 18:56:32 -08006394 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006395 "Requested grant " + targetPkg + " permission to " + uri);
6396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006397 final IPackageManager pm = ActivityThread.getPackageManager();
6398
6399 // If this is not a content: uri, we can't do anything with it.
6400 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006401 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006402 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 return;
6404 }
6405
6406 String name = uri.getAuthority();
6407 ProviderInfo pi = null;
6408 ContentProviderRecord cpr
6409 = (ContentProviderRecord)mProvidersByName.get(name);
6410 if (cpr != null) {
6411 pi = cpr.info;
6412 } else {
6413 try {
6414 pi = pm.resolveContentProvider(name,
6415 PackageManager.GET_URI_PERMISSION_PATTERNS);
6416 } catch (RemoteException ex) {
6417 }
6418 }
6419 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006420 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006421 return;
6422 }
6423
6424 int targetUid;
6425 try {
6426 targetUid = pm.getPackageUid(targetPkg);
6427 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006428 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006429 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006430 return;
6431 }
6432 } catch (RemoteException ex) {
6433 return;
6434 }
6435
6436 // First... does the target actually need this permission?
6437 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6438 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006439 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006440 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006441 return;
6442 }
6443
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006444 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 if (!pi.grantUriPermissions) {
6446 throw new SecurityException("Provider " + pi.packageName
6447 + "/" + pi.name
6448 + " does not allow granting of Uri permissions (uri "
6449 + uri + ")");
6450 }
6451 if (pi.uriPermissionPatterns != null) {
6452 final int N = pi.uriPermissionPatterns.length;
6453 boolean allowed = false;
6454 for (int i=0; i<N; i++) {
6455 if (pi.uriPermissionPatterns[i] != null
6456 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6457 allowed = true;
6458 break;
6459 }
6460 }
6461 if (!allowed) {
6462 throw new SecurityException("Provider " + pi.packageName
6463 + "/" + pi.name
6464 + " does not allow granting of permission to path of Uri "
6465 + uri);
6466 }
6467 }
6468
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006469 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006470 // this uri?
6471 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6472 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6473 throw new SecurityException("Uid " + callingUid
6474 + " does not have permission to uri " + uri);
6475 }
6476 }
6477
6478 // Okay! So here we are: the caller has the assumed permission
6479 // to the uri, and the target doesn't. Let's now give this to
6480 // the target.
6481
Joe Onorato8a9b2202010-02-26 18:56:32 -08006482 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006483 "Granting " + targetPkg + " permission to " + uri);
6484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006485 HashMap<Uri, UriPermission> targetUris
6486 = mGrantedUriPermissions.get(targetUid);
6487 if (targetUris == null) {
6488 targetUris = new HashMap<Uri, UriPermission>();
6489 mGrantedUriPermissions.put(targetUid, targetUris);
6490 }
6491
6492 UriPermission perm = targetUris.get(uri);
6493 if (perm == null) {
6494 perm = new UriPermission(targetUid, uri);
6495 targetUris.put(uri, perm);
6496
6497 }
6498 perm.modeFlags |= modeFlags;
6499 if (activity == null) {
6500 perm.globalModeFlags |= modeFlags;
6501 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6502 perm.readActivities.add(activity);
6503 if (activity.readUriPermissions == null) {
6504 activity.readUriPermissions = new HashSet<UriPermission>();
6505 }
6506 activity.readUriPermissions.add(perm);
6507 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6508 perm.writeActivities.add(activity);
6509 if (activity.writeUriPermissions == null) {
6510 activity.writeUriPermissions = new HashSet<UriPermission>();
6511 }
6512 activity.writeUriPermissions.add(perm);
6513 }
6514 }
6515
6516 private void grantUriPermissionFromIntentLocked(int callingUid,
6517 String targetPkg, Intent intent, HistoryRecord activity) {
6518 if (intent == null) {
6519 return;
6520 }
6521 Uri data = intent.getData();
6522 if (data == null) {
6523 return;
6524 }
6525 grantUriPermissionLocked(callingUid, targetPkg, data,
6526 intent.getFlags(), activity);
6527 }
6528
6529 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6530 Uri uri, int modeFlags) {
6531 synchronized(this) {
6532 final ProcessRecord r = getRecordForAppLocked(caller);
6533 if (r == null) {
6534 throw new SecurityException("Unable to find app for caller "
6535 + caller
6536 + " when granting permission to uri " + uri);
6537 }
6538 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006539 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006540 return;
6541 }
6542 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006543 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544 return;
6545 }
6546
6547 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6548 null);
6549 }
6550 }
6551
6552 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6553 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6554 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6555 HashMap<Uri, UriPermission> perms
6556 = mGrantedUriPermissions.get(perm.uid);
6557 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006558 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006559 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006560 perms.remove(perm.uri);
6561 if (perms.size() == 0) {
6562 mGrantedUriPermissions.remove(perm.uid);
6563 }
6564 }
6565 }
6566 }
6567
6568 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6569 if (activity.readUriPermissions != null) {
6570 for (UriPermission perm : activity.readUriPermissions) {
6571 perm.readActivities.remove(activity);
6572 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6573 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6574 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6575 removeUriPermissionIfNeededLocked(perm);
6576 }
6577 }
6578 }
6579 if (activity.writeUriPermissions != null) {
6580 for (UriPermission perm : activity.writeUriPermissions) {
6581 perm.writeActivities.remove(activity);
6582 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6583 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6584 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6585 removeUriPermissionIfNeededLocked(perm);
6586 }
6587 }
6588 }
6589 }
6590
6591 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6592 int modeFlags) {
6593 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6594 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6595 if (modeFlags == 0) {
6596 return;
6597 }
6598
Joe Onorato8a9b2202010-02-26 18:56:32 -08006599 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006600 "Revoking all granted permissions to " + uri);
6601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006602 final IPackageManager pm = ActivityThread.getPackageManager();
6603
6604 final String authority = uri.getAuthority();
6605 ProviderInfo pi = null;
6606 ContentProviderRecord cpr
6607 = (ContentProviderRecord)mProvidersByName.get(authority);
6608 if (cpr != null) {
6609 pi = cpr.info;
6610 } else {
6611 try {
6612 pi = pm.resolveContentProvider(authority,
6613 PackageManager.GET_URI_PERMISSION_PATTERNS);
6614 } catch (RemoteException ex) {
6615 }
6616 }
6617 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006618 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 return;
6620 }
6621
6622 // Does the caller have this permission on the URI?
6623 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6624 // Right now, if you are not the original owner of the permission,
6625 // you are not allowed to revoke it.
6626 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6627 throw new SecurityException("Uid " + callingUid
6628 + " does not have permission to uri " + uri);
6629 //}
6630 }
6631
6632 // Go through all of the permissions and remove any that match.
6633 final List<String> SEGMENTS = uri.getPathSegments();
6634 if (SEGMENTS != null) {
6635 final int NS = SEGMENTS.size();
6636 int N = mGrantedUriPermissions.size();
6637 for (int i=0; i<N; i++) {
6638 HashMap<Uri, UriPermission> perms
6639 = mGrantedUriPermissions.valueAt(i);
6640 Iterator<UriPermission> it = perms.values().iterator();
6641 toploop:
6642 while (it.hasNext()) {
6643 UriPermission perm = it.next();
6644 Uri targetUri = perm.uri;
6645 if (!authority.equals(targetUri.getAuthority())) {
6646 continue;
6647 }
6648 List<String> targetSegments = targetUri.getPathSegments();
6649 if (targetSegments == null) {
6650 continue;
6651 }
6652 if (targetSegments.size() < NS) {
6653 continue;
6654 }
6655 for (int j=0; j<NS; j++) {
6656 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6657 continue toploop;
6658 }
6659 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006660 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006661 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 perm.clearModes(modeFlags);
6663 if (perm.modeFlags == 0) {
6664 it.remove();
6665 }
6666 }
6667 if (perms.size() == 0) {
6668 mGrantedUriPermissions.remove(
6669 mGrantedUriPermissions.keyAt(i));
6670 N--;
6671 i--;
6672 }
6673 }
6674 }
6675 }
6676
6677 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6678 int modeFlags) {
6679 synchronized(this) {
6680 final ProcessRecord r = getRecordForAppLocked(caller);
6681 if (r == null) {
6682 throw new SecurityException("Unable to find app for caller "
6683 + caller
6684 + " when revoking permission to uri " + uri);
6685 }
6686 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006687 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006688 return;
6689 }
6690
6691 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6692 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6693 if (modeFlags == 0) {
6694 return;
6695 }
6696
6697 final IPackageManager pm = ActivityThread.getPackageManager();
6698
6699 final String authority = uri.getAuthority();
6700 ProviderInfo pi = null;
6701 ContentProviderRecord cpr
6702 = (ContentProviderRecord)mProvidersByName.get(authority);
6703 if (cpr != null) {
6704 pi = cpr.info;
6705 } else {
6706 try {
6707 pi = pm.resolveContentProvider(authority,
6708 PackageManager.GET_URI_PERMISSION_PATTERNS);
6709 } catch (RemoteException ex) {
6710 }
6711 }
6712 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006713 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006714 return;
6715 }
6716
6717 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6718 }
6719 }
6720
6721 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6722 synchronized (this) {
6723 ProcessRecord app =
6724 who != null ? getRecordForAppLocked(who) : null;
6725 if (app == null) return;
6726
6727 Message msg = Message.obtain();
6728 msg.what = WAIT_FOR_DEBUGGER_MSG;
6729 msg.obj = app;
6730 msg.arg1 = waiting ? 1 : 0;
6731 mHandler.sendMessage(msg);
6732 }
6733 }
6734
6735 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6736 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006737 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006738 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006739 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006740 }
6741
6742 // =========================================================
6743 // TASK MANAGEMENT
6744 // =========================================================
6745
6746 public List getTasks(int maxNum, int flags,
6747 IThumbnailReceiver receiver) {
6748 ArrayList list = new ArrayList();
6749
6750 PendingThumbnailsRecord pending = null;
6751 IApplicationThread topThumbnail = null;
6752 HistoryRecord topRecord = null;
6753
6754 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006755 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006756 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6757 + ", receiver=" + receiver);
6758
6759 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6760 != PackageManager.PERMISSION_GRANTED) {
6761 if (receiver != null) {
6762 // If the caller wants to wait for pending thumbnails,
6763 // it ain't gonna get them.
6764 try {
6765 receiver.finished();
6766 } catch (RemoteException ex) {
6767 }
6768 }
6769 String msg = "Permission Denial: getTasks() from pid="
6770 + Binder.getCallingPid()
6771 + ", uid=" + Binder.getCallingUid()
6772 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006773 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 throw new SecurityException(msg);
6775 }
6776
6777 int pos = mHistory.size()-1;
6778 HistoryRecord next =
6779 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6780 HistoryRecord top = null;
6781 CharSequence topDescription = null;
6782 TaskRecord curTask = null;
6783 int numActivities = 0;
6784 int numRunning = 0;
6785 while (pos >= 0 && maxNum > 0) {
6786 final HistoryRecord r = next;
6787 pos--;
6788 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6789
6790 // Initialize state for next task if needed.
6791 if (top == null ||
6792 (top.state == ActivityState.INITIALIZING
6793 && top.task == r.task)) {
6794 top = r;
6795 topDescription = r.description;
6796 curTask = r.task;
6797 numActivities = numRunning = 0;
6798 }
6799
6800 // Add 'r' into the current task.
6801 numActivities++;
6802 if (r.app != null && r.app.thread != null) {
6803 numRunning++;
6804 }
6805 if (topDescription == null) {
6806 topDescription = r.description;
6807 }
6808
Joe Onorato8a9b2202010-02-26 18:56:32 -08006809 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006810 TAG, r.intent.getComponent().flattenToShortString()
6811 + ": task=" + r.task);
6812
6813 // If the next one is a different task, generate a new
6814 // TaskInfo entry for what we have.
6815 if (next == null || next.task != curTask) {
6816 ActivityManager.RunningTaskInfo ci
6817 = new ActivityManager.RunningTaskInfo();
6818 ci.id = curTask.taskId;
6819 ci.baseActivity = r.intent.getComponent();
6820 ci.topActivity = top.intent.getComponent();
6821 ci.thumbnail = top.thumbnail;
6822 ci.description = topDescription;
6823 ci.numActivities = numActivities;
6824 ci.numRunning = numRunning;
6825 //System.out.println(
6826 // "#" + maxNum + ": " + " descr=" + ci.description);
6827 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006828 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006829 TAG, "State=" + top.state + "Idle=" + top.idle
6830 + " app=" + top.app
6831 + " thr=" + (top.app != null ? top.app.thread : null));
6832 if (top.state == ActivityState.RESUMED
6833 || top.state == ActivityState.PAUSING) {
6834 if (top.idle && top.app != null
6835 && top.app.thread != null) {
6836 topRecord = top;
6837 topThumbnail = top.app.thread;
6838 } else {
6839 top.thumbnailNeeded = true;
6840 }
6841 }
6842 if (pending == null) {
6843 pending = new PendingThumbnailsRecord(receiver);
6844 }
6845 pending.pendingRecords.add(top);
6846 }
6847 list.add(ci);
6848 maxNum--;
6849 top = null;
6850 }
6851 }
6852
6853 if (pending != null) {
6854 mPendingThumbnails.add(pending);
6855 }
6856 }
6857
Joe Onorato8a9b2202010-02-26 18:56:32 -08006858 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006859
6860 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006861 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006862 try {
6863 topThumbnail.requestThumbnail(topRecord);
6864 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006865 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006866 sendPendingThumbnail(null, topRecord, null, null, true);
6867 }
6868 }
6869
6870 if (pending == null && receiver != null) {
6871 // In this case all thumbnails were available and the client
6872 // is being asked to be told when the remaining ones come in...
6873 // which is unusually, since the top-most currently running
6874 // activity should never have a canned thumbnail! Oh well.
6875 try {
6876 receiver.finished();
6877 } catch (RemoteException ex) {
6878 }
6879 }
6880
6881 return list;
6882 }
6883
6884 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6885 int flags) {
6886 synchronized (this) {
6887 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6888 "getRecentTasks()");
6889
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006890 IPackageManager pm = ActivityThread.getPackageManager();
6891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006892 final int N = mRecentTasks.size();
6893 ArrayList<ActivityManager.RecentTaskInfo> res
6894 = new ArrayList<ActivityManager.RecentTaskInfo>(
6895 maxNum < N ? maxNum : N);
6896 for (int i=0; i<N && maxNum > 0; i++) {
6897 TaskRecord tr = mRecentTasks.get(i);
6898 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6899 || (tr.intent == null)
6900 || ((tr.intent.getFlags()
6901 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6902 ActivityManager.RecentTaskInfo rti
6903 = new ActivityManager.RecentTaskInfo();
6904 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6905 rti.baseIntent = new Intent(
6906 tr.intent != null ? tr.intent : tr.affinityIntent);
6907 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006908
6909 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
6910 // Check whether this activity is currently available.
6911 try {
6912 if (rti.origActivity != null) {
6913 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
6914 continue;
6915 }
6916 } else if (rti.baseIntent != null) {
6917 if (pm.queryIntentActivities(rti.baseIntent,
6918 null, 0) == null) {
6919 continue;
6920 }
6921 }
6922 } catch (RemoteException e) {
6923 // Will never happen.
6924 }
6925 }
6926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006927 res.add(rti);
6928 maxNum--;
6929 }
6930 }
6931 return res;
6932 }
6933 }
6934
6935 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6936 int j;
6937 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6938 TaskRecord jt = startTask;
6939
6940 // First look backwards
6941 for (j=startIndex-1; j>=0; j--) {
6942 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6943 if (r.task != jt) {
6944 jt = r.task;
6945 if (affinity.equals(jt.affinity)) {
6946 return j;
6947 }
6948 }
6949 }
6950
6951 // Now look forwards
6952 final int N = mHistory.size();
6953 jt = startTask;
6954 for (j=startIndex+1; j<N; j++) {
6955 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6956 if (r.task != jt) {
6957 if (affinity.equals(jt.affinity)) {
6958 return j;
6959 }
6960 jt = r.task;
6961 }
6962 }
6963
6964 // Might it be at the top?
6965 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6966 return N-1;
6967 }
6968
6969 return -1;
6970 }
6971
6972 /**
6973 * Perform a reset of the given task, if needed as part of launching it.
6974 * Returns the new HistoryRecord at the top of the task.
6975 */
6976 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6977 HistoryRecord newActivity) {
6978 boolean forceReset = (newActivity.info.flags
6979 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6980 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6981 if ((newActivity.info.flags
6982 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6983 forceReset = true;
6984 }
6985 }
6986
6987 final TaskRecord task = taskTop.task;
6988
6989 // We are going to move through the history list so that we can look
6990 // at each activity 'target' with 'below' either the interesting
6991 // activity immediately below it in the stack or null.
6992 HistoryRecord target = null;
6993 int targetI = 0;
6994 int taskTopI = -1;
6995 int replyChainEnd = -1;
6996 int lastReparentPos = -1;
6997 for (int i=mHistory.size()-1; i>=-1; i--) {
6998 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6999
7000 if (below != null && below.finishing) {
7001 continue;
7002 }
7003 if (target == null) {
7004 target = below;
7005 targetI = i;
7006 // If we were in the middle of a reply chain before this
7007 // task, it doesn't appear like the root of the chain wants
7008 // anything interesting, so drop it.
7009 replyChainEnd = -1;
7010 continue;
7011 }
7012
7013 final int flags = target.info.flags;
7014
7015 final boolean finishOnTaskLaunch =
7016 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7017 final boolean allowTaskReparenting =
7018 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7019
7020 if (target.task == task) {
7021 // We are inside of the task being reset... we'll either
7022 // finish this activity, push it out for another task,
7023 // or leave it as-is. We only do this
7024 // for activities that are not the root of the task (since
7025 // if we finish the root, we may no longer have the task!).
7026 if (taskTopI < 0) {
7027 taskTopI = targetI;
7028 }
7029 if (below != null && below.task == task) {
7030 final boolean clearWhenTaskReset =
7031 (target.intent.getFlags()
7032 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007033 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007034 // If this activity is sending a reply to a previous
7035 // activity, we can't do anything with it now until
7036 // we reach the start of the reply chain.
7037 // XXX note that we are assuming the result is always
7038 // to the previous activity, which is almost always
7039 // the case but we really shouldn't count on.
7040 if (replyChainEnd < 0) {
7041 replyChainEnd = targetI;
7042 }
Ed Heyl73798232009-03-24 21:32:21 -07007043 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007044 && target.taskAffinity != null
7045 && !target.taskAffinity.equals(task.affinity)) {
7046 // If this activity has an affinity for another
7047 // task, then we need to move it out of here. We will
7048 // move it as far out of the way as possible, to the
7049 // bottom of the activity stack. This also keeps it
7050 // correctly ordered with any activities we previously
7051 // moved.
7052 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7053 if (target.taskAffinity != null
7054 && target.taskAffinity.equals(p.task.affinity)) {
7055 // If the activity currently at the bottom has the
7056 // same task affinity as the one we are moving,
7057 // then merge it into the same task.
7058 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007059 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060 + " out to bottom task " + p.task);
7061 } else {
7062 mCurTask++;
7063 if (mCurTask <= 0) {
7064 mCurTask = 1;
7065 }
7066 target.task = new TaskRecord(mCurTask, target.info, null,
7067 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7068 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007069 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007070 + " out to new task " + target.task);
7071 }
7072 mWindowManager.setAppGroupId(target, task.taskId);
7073 if (replyChainEnd < 0) {
7074 replyChainEnd = targetI;
7075 }
7076 int dstPos = 0;
7077 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7078 p = (HistoryRecord)mHistory.get(srcPos);
7079 if (p.finishing) {
7080 continue;
7081 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007082 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007083 + " out to target's task " + target.task);
7084 task.numActivities--;
7085 p.task = target.task;
7086 target.task.numActivities++;
7087 mHistory.remove(srcPos);
7088 mHistory.add(dstPos, p);
7089 mWindowManager.moveAppToken(dstPos, p);
7090 mWindowManager.setAppGroupId(p, p.task.taskId);
7091 dstPos++;
7092 if (VALIDATE_TOKENS) {
7093 mWindowManager.validateAppTokens(mHistory);
7094 }
7095 i++;
7096 }
7097 if (taskTop == p) {
7098 taskTop = below;
7099 }
7100 if (taskTopI == replyChainEnd) {
7101 taskTopI = -1;
7102 }
7103 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007104 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007105 } else if (forceReset || finishOnTaskLaunch
7106 || clearWhenTaskReset) {
7107 // If the activity should just be removed -- either
7108 // because it asks for it, or the task should be
7109 // cleared -- then finish it and anything that is
7110 // part of its reply chain.
7111 if (clearWhenTaskReset) {
7112 // In this case, we want to finish this activity
7113 // and everything above it, so be sneaky and pretend
7114 // like these are all in the reply chain.
7115 replyChainEnd = targetI+1;
7116 while (replyChainEnd < mHistory.size() &&
7117 ((HistoryRecord)mHistory.get(
7118 replyChainEnd)).task == task) {
7119 replyChainEnd++;
7120 }
7121 replyChainEnd--;
7122 } else if (replyChainEnd < 0) {
7123 replyChainEnd = targetI;
7124 }
7125 HistoryRecord p = null;
7126 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7127 p = (HistoryRecord)mHistory.get(srcPos);
7128 if (p.finishing) {
7129 continue;
7130 }
7131 if (finishActivityLocked(p, srcPos,
7132 Activity.RESULT_CANCELED, null, "reset")) {
7133 replyChainEnd--;
7134 srcPos--;
7135 }
7136 }
7137 if (taskTop == p) {
7138 taskTop = below;
7139 }
7140 if (taskTopI == replyChainEnd) {
7141 taskTopI = -1;
7142 }
7143 replyChainEnd = -1;
7144 } else {
7145 // If we were in the middle of a chain, well the
7146 // activity that started it all doesn't want anything
7147 // special, so leave it all as-is.
7148 replyChainEnd = -1;
7149 }
7150 } else {
7151 // Reached the bottom of the task -- any reply chain
7152 // should be left as-is.
7153 replyChainEnd = -1;
7154 }
7155
7156 } else if (target.resultTo != null) {
7157 // If this activity is sending a reply to a previous
7158 // activity, we can't do anything with it now until
7159 // we reach the start of the reply chain.
7160 // XXX note that we are assuming the result is always
7161 // to the previous activity, which is almost always
7162 // the case but we really shouldn't count on.
7163 if (replyChainEnd < 0) {
7164 replyChainEnd = targetI;
7165 }
7166
7167 } else if (taskTopI >= 0 && allowTaskReparenting
7168 && task.affinity != null
7169 && task.affinity.equals(target.taskAffinity)) {
7170 // We are inside of another task... if this activity has
7171 // an affinity for our task, then either remove it if we are
7172 // clearing or move it over to our task. Note that
7173 // we currently punt on the case where we are resetting a
7174 // task that is not at the top but who has activities above
7175 // with an affinity to it... this is really not a normal
7176 // case, and we will need to later pull that task to the front
7177 // and usually at that point we will do the reset and pick
7178 // up those remaining activities. (This only happens if
7179 // someone starts an activity in a new task from an activity
7180 // in a task that is not currently on top.)
7181 if (forceReset || finishOnTaskLaunch) {
7182 if (replyChainEnd < 0) {
7183 replyChainEnd = targetI;
7184 }
7185 HistoryRecord p = null;
7186 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7187 p = (HistoryRecord)mHistory.get(srcPos);
7188 if (p.finishing) {
7189 continue;
7190 }
7191 if (finishActivityLocked(p, srcPos,
7192 Activity.RESULT_CANCELED, null, "reset")) {
7193 taskTopI--;
7194 lastReparentPos--;
7195 replyChainEnd--;
7196 srcPos--;
7197 }
7198 }
7199 replyChainEnd = -1;
7200 } else {
7201 if (replyChainEnd < 0) {
7202 replyChainEnd = targetI;
7203 }
7204 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7205 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7206 if (p.finishing) {
7207 continue;
7208 }
7209 if (lastReparentPos < 0) {
7210 lastReparentPos = taskTopI;
7211 taskTop = p;
7212 } else {
7213 lastReparentPos--;
7214 }
7215 mHistory.remove(srcPos);
7216 p.task.numActivities--;
7217 p.task = task;
7218 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007219 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007220 + " in to resetting task " + task);
7221 task.numActivities++;
7222 mWindowManager.moveAppToken(lastReparentPos, p);
7223 mWindowManager.setAppGroupId(p, p.task.taskId);
7224 if (VALIDATE_TOKENS) {
7225 mWindowManager.validateAppTokens(mHistory);
7226 }
7227 }
7228 replyChainEnd = -1;
7229
7230 // Now we've moved it in to place... but what if this is
7231 // a singleTop activity and we have put it on top of another
7232 // instance of the same activity? Then we drop the instance
7233 // below so it remains singleTop.
7234 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7235 for (int j=lastReparentPos-1; j>=0; j--) {
7236 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7237 if (p.finishing) {
7238 continue;
7239 }
7240 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7241 if (finishActivityLocked(p, j,
7242 Activity.RESULT_CANCELED, null, "replace")) {
7243 taskTopI--;
7244 lastReparentPos--;
7245 }
7246 }
7247 }
7248 }
7249 }
7250 }
7251
7252 target = below;
7253 targetI = i;
7254 }
7255
7256 return taskTop;
7257 }
7258
7259 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007260 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007261 */
7262 public void moveTaskToFront(int task) {
7263 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7264 "moveTaskToFront()");
7265
7266 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007267 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7268 Binder.getCallingUid(), "Task to front")) {
7269 return;
7270 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271 final long origId = Binder.clearCallingIdentity();
7272 try {
7273 int N = mRecentTasks.size();
7274 for (int i=0; i<N; i++) {
7275 TaskRecord tr = mRecentTasks.get(i);
7276 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007277 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007278 return;
7279 }
7280 }
7281 for (int i=mHistory.size()-1; i>=0; i--) {
7282 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7283 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007284 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007285 return;
7286 }
7287 }
7288 } finally {
7289 Binder.restoreCallingIdentity(origId);
7290 }
7291 }
7292 }
7293
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007294 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007295 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296
7297 final int task = tr.taskId;
7298 int top = mHistory.size()-1;
7299
7300 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7301 // nothing to do!
7302 return;
7303 }
7304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007305 ArrayList moved = new ArrayList();
7306
7307 // Applying the affinities may have removed entries from the history,
7308 // so get the size again.
7309 top = mHistory.size()-1;
7310 int pos = top;
7311
7312 // Shift all activities with this task up to the top
7313 // of the stack, keeping them in the same internal order.
7314 while (pos >= 0) {
7315 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007316 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007317 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7318 boolean first = true;
7319 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007320 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007321 mHistory.remove(pos);
7322 mHistory.add(top, r);
7323 moved.add(0, r);
7324 top--;
7325 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007326 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007327 first = false;
7328 }
7329 }
7330 pos--;
7331 }
7332
Joe Onorato8a9b2202010-02-26 18:56:32 -08007333 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007334 "Prepare to front transition: task=" + tr);
7335 if (reason != null &&
7336 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7337 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7338 HistoryRecord r = topRunningActivityLocked(null);
7339 if (r != null) {
7340 mNoAnimActivities.add(r);
7341 }
7342 } else {
7343 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7344 }
7345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007346 mWindowManager.moveAppTokensToTop(moved);
7347 if (VALIDATE_TOKENS) {
7348 mWindowManager.validateAppTokens(mHistory);
7349 }
7350
Josh Bartel7f208742010-02-25 11:01:44 -06007351 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007352 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 }
7354
Josh Bartel7f208742010-02-25 11:01:44 -06007355 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356 resumeTopActivityLocked(null);
7357 }
7358
7359 public void moveTaskToBack(int task) {
7360 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7361 "moveTaskToBack()");
7362
7363 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007364 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7365 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7366 Binder.getCallingUid(), "Task to back")) {
7367 return;
7368 }
7369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007370 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007371 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 Binder.restoreCallingIdentity(origId);
7373 }
7374 }
7375
7376 /**
7377 * Moves an activity, and all of the other activities within the same task, to the bottom
7378 * of the history stack. The activity's order within the task is unchanged.
7379 *
7380 * @param token A reference to the activity we wish to move
7381 * @param nonRoot If false then this only works if the activity is the root
7382 * of a task; if true it will work for any activity in a task.
7383 * @return Returns true if the move completed, false if not.
7384 */
7385 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7386 synchronized(this) {
7387 final long origId = Binder.clearCallingIdentity();
7388 int taskId = getTaskForActivityLocked(token, !nonRoot);
7389 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007390 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 }
7392 Binder.restoreCallingIdentity(origId);
7393 }
7394 return false;
7395 }
7396
7397 /**
7398 * Worker method for rearranging history stack. Implements the function of moving all
7399 * activities for a specific task (gathering them if disjoint) into a single group at the
7400 * bottom of the stack.
7401 *
7402 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7403 * to premeptively cancel the move.
7404 *
7405 * @param task The taskId to collect and move to the bottom.
7406 * @return Returns true if the move completed, false if not.
7407 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007408 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007409 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007410
7411 // If we have a watcher, preflight the move before committing to it. First check
7412 // for *other* available tasks, but if none are available, then try again allowing the
7413 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007414 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 HistoryRecord next = topRunningActivityLocked(null, task);
7416 if (next == null) {
7417 next = topRunningActivityLocked(null, 0);
7418 }
7419 if (next != null) {
7420 // ask watcher if this is allowed
7421 boolean moveOK = true;
7422 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007423 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007425 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007426 }
7427 if (!moveOK) {
7428 return false;
7429 }
7430 }
7431 }
7432
7433 ArrayList moved = new ArrayList();
7434
Joe Onorato8a9b2202010-02-26 18:56:32 -08007435 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007437
7438 final int N = mHistory.size();
7439 int bottom = 0;
7440 int pos = 0;
7441
7442 // Shift all activities with this task down to the bottom
7443 // of the stack, keeping them in the same internal order.
7444 while (pos < N) {
7445 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007446 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007447 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7448 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007449 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007450 mHistory.remove(pos);
7451 mHistory.add(bottom, r);
7452 moved.add(r);
7453 bottom++;
7454 }
7455 pos++;
7456 }
7457
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007458 if (reason != null &&
7459 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7460 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7461 HistoryRecord r = topRunningActivityLocked(null);
7462 if (r != null) {
7463 mNoAnimActivities.add(r);
7464 }
7465 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007466 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 mWindowManager.moveAppTokensToBottom(moved);
7469 if (VALIDATE_TOKENS) {
7470 mWindowManager.validateAppTokens(mHistory);
7471 }
7472
Josh Bartel7f208742010-02-25 11:01:44 -06007473 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007474 return true;
7475 }
7476
7477 public void moveTaskBackwards(int task) {
7478 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7479 "moveTaskBackwards()");
7480
7481 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007482 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7483 Binder.getCallingUid(), "Task backwards")) {
7484 return;
7485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007486 final long origId = Binder.clearCallingIdentity();
7487 moveTaskBackwardsLocked(task);
7488 Binder.restoreCallingIdentity(origId);
7489 }
7490 }
7491
7492 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007493 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 }
7495
7496 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7497 synchronized(this) {
7498 return getTaskForActivityLocked(token, onlyRoot);
7499 }
7500 }
7501
7502 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7503 final int N = mHistory.size();
7504 TaskRecord lastTask = null;
7505 for (int i=0; i<N; i++) {
7506 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7507 if (r == token) {
7508 if (!onlyRoot || lastTask != r.task) {
7509 return r.task.taskId;
7510 }
7511 return -1;
7512 }
7513 lastTask = r.task;
7514 }
7515
7516 return -1;
7517 }
7518
7519 /**
7520 * Returns the top activity in any existing task matching the given
7521 * Intent. Returns null if no such task is found.
7522 */
7523 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7524 ComponentName cls = intent.getComponent();
7525 if (info.targetActivity != null) {
7526 cls = new ComponentName(info.packageName, info.targetActivity);
7527 }
7528
7529 TaskRecord cp = null;
7530
7531 final int N = mHistory.size();
7532 for (int i=(N-1); i>=0; i--) {
7533 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7534 if (!r.finishing && r.task != cp
7535 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7536 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007537 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007538 // + "/aff=" + r.task.affinity + " to new cls="
7539 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7540 if (r.task.affinity != null) {
7541 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007542 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007543 return r;
7544 }
7545 } else if (r.task.intent != null
7546 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007547 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007549 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007550 return r;
7551 } else if (r.task.affinityIntent != null
7552 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007553 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007554 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007555 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007556 return r;
7557 }
7558 }
7559 }
7560
7561 return null;
7562 }
7563
7564 /**
7565 * Returns the first activity (starting from the top of the stack) that
7566 * is the same as the given activity. Returns null if no such activity
7567 * is found.
7568 */
7569 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7570 ComponentName cls = intent.getComponent();
7571 if (info.targetActivity != null) {
7572 cls = new ComponentName(info.packageName, info.targetActivity);
7573 }
7574
7575 final int N = mHistory.size();
7576 for (int i=(N-1); i>=0; i--) {
7577 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7578 if (!r.finishing) {
7579 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007580 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007582 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 return r;
7584 }
7585 }
7586 }
7587
7588 return null;
7589 }
7590
7591 public void finishOtherInstances(IBinder token, ComponentName className) {
7592 synchronized(this) {
7593 final long origId = Binder.clearCallingIdentity();
7594
7595 int N = mHistory.size();
7596 TaskRecord lastTask = null;
7597 for (int i=0; i<N; i++) {
7598 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7599 if (r.realActivity.equals(className)
7600 && r != token && lastTask != r.task) {
7601 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7602 null, "others")) {
7603 i--;
7604 N--;
7605 }
7606 }
7607 lastTask = r.task;
7608 }
7609
7610 Binder.restoreCallingIdentity(origId);
7611 }
7612 }
7613
7614 // =========================================================
7615 // THUMBNAILS
7616 // =========================================================
7617
7618 public void reportThumbnail(IBinder token,
7619 Bitmap thumbnail, CharSequence description) {
7620 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7621 final long origId = Binder.clearCallingIdentity();
7622 sendPendingThumbnail(null, token, thumbnail, description, true);
7623 Binder.restoreCallingIdentity(origId);
7624 }
7625
7626 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7627 Bitmap thumbnail, CharSequence description, boolean always) {
7628 TaskRecord task = null;
7629 ArrayList receivers = null;
7630
7631 //System.out.println("Send pending thumbnail: " + r);
7632
7633 synchronized(this) {
7634 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007635 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007636 if (index < 0) {
7637 return;
7638 }
7639 r = (HistoryRecord)mHistory.get(index);
7640 }
7641 if (thumbnail == null) {
7642 thumbnail = r.thumbnail;
7643 description = r.description;
7644 }
7645 if (thumbnail == null && !always) {
7646 // If there is no thumbnail, and this entry is not actually
7647 // going away, then abort for now and pick up the next
7648 // thumbnail we get.
7649 return;
7650 }
7651 task = r.task;
7652
7653 int N = mPendingThumbnails.size();
7654 int i=0;
7655 while (i<N) {
7656 PendingThumbnailsRecord pr =
7657 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7658 //System.out.println("Looking in " + pr.pendingRecords);
7659 if (pr.pendingRecords.remove(r)) {
7660 if (receivers == null) {
7661 receivers = new ArrayList();
7662 }
7663 receivers.add(pr);
7664 if (pr.pendingRecords.size() == 0) {
7665 pr.finished = true;
7666 mPendingThumbnails.remove(i);
7667 N--;
7668 continue;
7669 }
7670 }
7671 i++;
7672 }
7673 }
7674
7675 if (receivers != null) {
7676 final int N = receivers.size();
7677 for (int i=0; i<N; i++) {
7678 try {
7679 PendingThumbnailsRecord pr =
7680 (PendingThumbnailsRecord)receivers.get(i);
7681 pr.receiver.newThumbnail(
7682 task != null ? task.taskId : -1, thumbnail, description);
7683 if (pr.finished) {
7684 pr.receiver.finished();
7685 }
7686 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007687 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007688 }
7689 }
7690 }
7691 }
7692
7693 // =========================================================
7694 // CONTENT PROVIDERS
7695 // =========================================================
7696
7697 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7698 List providers = null;
7699 try {
7700 providers = ActivityThread.getPackageManager().
7701 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007702 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007703 } catch (RemoteException ex) {
7704 }
7705 if (providers != null) {
7706 final int N = providers.size();
7707 for (int i=0; i<N; i++) {
7708 ProviderInfo cpi =
7709 (ProviderInfo)providers.get(i);
7710 ContentProviderRecord cpr =
7711 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7712 if (cpr == null) {
7713 cpr = new ContentProviderRecord(cpi, app.info);
7714 mProvidersByClass.put(cpi.name, cpr);
7715 }
7716 app.pubProviders.put(cpi.name, cpr);
7717 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007718 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007719 }
7720 }
7721 return providers;
7722 }
7723
7724 private final String checkContentProviderPermissionLocked(
7725 ProviderInfo cpi, ProcessRecord r, int mode) {
7726 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7727 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7728 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7729 cpi.exported ? -1 : cpi.applicationInfo.uid)
7730 == PackageManager.PERMISSION_GRANTED
7731 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7732 return null;
7733 }
7734 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7735 cpi.exported ? -1 : cpi.applicationInfo.uid)
7736 == PackageManager.PERMISSION_GRANTED) {
7737 return null;
7738 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007739
7740 PathPermission[] pps = cpi.pathPermissions;
7741 if (pps != null) {
7742 int i = pps.length;
7743 while (i > 0) {
7744 i--;
7745 PathPermission pp = pps[i];
7746 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7747 cpi.exported ? -1 : cpi.applicationInfo.uid)
7748 == PackageManager.PERMISSION_GRANTED
7749 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7750 return null;
7751 }
7752 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7753 cpi.exported ? -1 : cpi.applicationInfo.uid)
7754 == PackageManager.PERMISSION_GRANTED) {
7755 return null;
7756 }
7757 }
7758 }
7759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007760 String msg = "Permission Denial: opening provider " + cpi.name
7761 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7762 + ", uid=" + callingUid + ") requires "
7763 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007764 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007765 return msg;
7766 }
7767
7768 private final ContentProviderHolder getContentProviderImpl(
7769 IApplicationThread caller, String name) {
7770 ContentProviderRecord cpr;
7771 ProviderInfo cpi = null;
7772
7773 synchronized(this) {
7774 ProcessRecord r = null;
7775 if (caller != null) {
7776 r = getRecordForAppLocked(caller);
7777 if (r == null) {
7778 throw new SecurityException(
7779 "Unable to find app for caller " + caller
7780 + " (pid=" + Binder.getCallingPid()
7781 + ") when getting content provider " + name);
7782 }
7783 }
7784
7785 // First check if this content provider has been published...
7786 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7787 if (cpr != null) {
7788 cpi = cpr.info;
7789 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7790 return new ContentProviderHolder(cpi,
7791 cpi.readPermission != null
7792 ? cpi.readPermission : cpi.writePermission);
7793 }
7794
7795 if (r != null && cpr.canRunHere(r)) {
7796 // This provider has been published or is in the process
7797 // of being published... but it is also allowed to run
7798 // in the caller's process, so don't make a connection
7799 // and just let the caller instantiate its own instance.
7800 if (cpr.provider != null) {
7801 // don't give caller the provider object, it needs
7802 // to make its own.
7803 cpr = new ContentProviderRecord(cpr);
7804 }
7805 return cpr;
7806 }
7807
7808 final long origId = Binder.clearCallingIdentity();
7809
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007810 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007811 // return it right away.
7812 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007813 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007814 "Adding provider requested by "
7815 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007816 + cpr.info.processName);
7817 Integer cnt = r.conProviders.get(cpr);
7818 if (cnt == null) {
7819 r.conProviders.put(cpr, new Integer(1));
7820 } else {
7821 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 cpr.clients.add(r);
7824 } else {
7825 cpr.externals++;
7826 }
7827
7828 if (cpr.app != null) {
7829 updateOomAdjLocked(cpr.app);
7830 }
7831
7832 Binder.restoreCallingIdentity(origId);
7833
7834 } else {
7835 try {
7836 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007837 resolveContentProvider(name,
7838 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007839 } catch (RemoteException ex) {
7840 }
7841 if (cpi == null) {
7842 return null;
7843 }
7844
7845 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7846 return new ContentProviderHolder(cpi,
7847 cpi.readPermission != null
7848 ? cpi.readPermission : cpi.writePermission);
7849 }
7850
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007851 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7852 && !cpi.processName.equals("system")) {
7853 // If this content provider does not run in the system
7854 // process, and the system is not yet ready to run other
7855 // processes, then fail fast instead of hanging.
7856 throw new IllegalArgumentException(
7857 "Attempt to launch content provider before system ready");
7858 }
7859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007860 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7861 final boolean firstClass = cpr == null;
7862 if (firstClass) {
7863 try {
7864 ApplicationInfo ai =
7865 ActivityThread.getPackageManager().
7866 getApplicationInfo(
7867 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007868 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007869 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007870 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007871 + cpi.name);
7872 return null;
7873 }
7874 cpr = new ContentProviderRecord(cpi, ai);
7875 } catch (RemoteException ex) {
7876 // pm is in same process, this will never happen.
7877 }
7878 }
7879
7880 if (r != null && cpr.canRunHere(r)) {
7881 // If this is a multiprocess provider, then just return its
7882 // info and allow the caller to instantiate it. Only do
7883 // this if the provider is the same user as the caller's
7884 // process, or can run as root (so can be in any process).
7885 return cpr;
7886 }
7887
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007888 if (DEBUG_PROVIDER) {
7889 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007890 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007891 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 }
7893
7894 // This is single process, and our app is now connecting to it.
7895 // See if we are already in the process of launching this
7896 // provider.
7897 final int N = mLaunchingProviders.size();
7898 int i;
7899 for (i=0; i<N; i++) {
7900 if (mLaunchingProviders.get(i) == cpr) {
7901 break;
7902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007903 }
7904
7905 // If the provider is not already being launched, then get it
7906 // started.
7907 if (i >= N) {
7908 final long origId = Binder.clearCallingIdentity();
7909 ProcessRecord proc = startProcessLocked(cpi.processName,
7910 cpr.appInfo, false, 0, "content provider",
7911 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007912 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007913 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007914 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 + cpi.applicationInfo.packageName + "/"
7916 + cpi.applicationInfo.uid + " for provider "
7917 + name + ": process is bad");
7918 return null;
7919 }
7920 cpr.launchingApp = proc;
7921 mLaunchingProviders.add(cpr);
7922 Binder.restoreCallingIdentity(origId);
7923 }
7924
7925 // Make sure the provider is published (the same provider class
7926 // may be published under multiple names).
7927 if (firstClass) {
7928 mProvidersByClass.put(cpi.name, cpr);
7929 }
7930 mProvidersByName.put(name, cpr);
7931
7932 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007933 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007934 "Adding provider requested by "
7935 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007936 + cpr.info.processName);
7937 Integer cnt = r.conProviders.get(cpr);
7938 if (cnt == null) {
7939 r.conProviders.put(cpr, new Integer(1));
7940 } else {
7941 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007943 cpr.clients.add(r);
7944 } else {
7945 cpr.externals++;
7946 }
7947 }
7948 }
7949
7950 // Wait for the provider to be published...
7951 synchronized (cpr) {
7952 while (cpr.provider == null) {
7953 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007954 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 + cpi.applicationInfo.packageName + "/"
7956 + cpi.applicationInfo.uid + " for provider "
7957 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007958 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007959 cpi.applicationInfo.packageName,
7960 cpi.applicationInfo.uid, name);
7961 return null;
7962 }
7963 try {
7964 cpr.wait();
7965 } catch (InterruptedException ex) {
7966 }
7967 }
7968 }
7969 return cpr;
7970 }
7971
7972 public final ContentProviderHolder getContentProvider(
7973 IApplicationThread caller, String name) {
7974 if (caller == null) {
7975 String msg = "null IApplicationThread when getting content provider "
7976 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007977 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007978 throw new SecurityException(msg);
7979 }
7980
7981 return getContentProviderImpl(caller, name);
7982 }
7983
7984 private ContentProviderHolder getContentProviderExternal(String name) {
7985 return getContentProviderImpl(null, name);
7986 }
7987
7988 /**
7989 * Drop a content provider from a ProcessRecord's bookkeeping
7990 * @param cpr
7991 */
7992 public void removeContentProvider(IApplicationThread caller, String name) {
7993 synchronized (this) {
7994 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7995 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007996 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007997 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007998 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007999 return;
8000 }
8001 final ProcessRecord r = getRecordForAppLocked(caller);
8002 if (r == null) {
8003 throw new SecurityException(
8004 "Unable to find app for caller " + caller +
8005 " when removing content provider " + name);
8006 }
8007 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008008 ContentProviderRecord localCpr = (ContentProviderRecord)
8009 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008010 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008011 + r.info.processName + " from process "
8012 + localCpr.appInfo.processName);
8013 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008014 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008015 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008016 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008017 return;
8018 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008019 Integer cnt = r.conProviders.get(localCpr);
8020 if (cnt == null || cnt.intValue() <= 1) {
8021 localCpr.clients.remove(r);
8022 r.conProviders.remove(localCpr);
8023 } else {
8024 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008026 }
8027 updateOomAdjLocked();
8028 }
8029 }
8030
8031 private void removeContentProviderExternal(String name) {
8032 synchronized (this) {
8033 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
8034 if(cpr == null) {
8035 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008036 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 return;
8038 }
8039
8040 //update content provider record entry info
8041 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
8042 localCpr.externals--;
8043 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008044 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 }
8046 updateOomAdjLocked();
8047 }
8048 }
8049
8050 public final void publishContentProviders(IApplicationThread caller,
8051 List<ContentProviderHolder> providers) {
8052 if (providers == null) {
8053 return;
8054 }
8055
8056 synchronized(this) {
8057 final ProcessRecord r = getRecordForAppLocked(caller);
8058 if (r == null) {
8059 throw new SecurityException(
8060 "Unable to find app for caller " + caller
8061 + " (pid=" + Binder.getCallingPid()
8062 + ") when publishing content providers");
8063 }
8064
8065 final long origId = Binder.clearCallingIdentity();
8066
8067 final int N = providers.size();
8068 for (int i=0; i<N; i++) {
8069 ContentProviderHolder src = providers.get(i);
8070 if (src == null || src.info == null || src.provider == null) {
8071 continue;
8072 }
8073 ContentProviderRecord dst =
8074 (ContentProviderRecord)r.pubProviders.get(src.info.name);
8075 if (dst != null) {
8076 mProvidersByClass.put(dst.info.name, dst);
8077 String names[] = dst.info.authority.split(";");
8078 for (int j = 0; j < names.length; j++) {
8079 mProvidersByName.put(names[j], dst);
8080 }
8081
8082 int NL = mLaunchingProviders.size();
8083 int j;
8084 for (j=0; j<NL; j++) {
8085 if (mLaunchingProviders.get(j) == dst) {
8086 mLaunchingProviders.remove(j);
8087 j--;
8088 NL--;
8089 }
8090 }
8091 synchronized (dst) {
8092 dst.provider = src.provider;
8093 dst.app = r;
8094 dst.notifyAll();
8095 }
8096 updateOomAdjLocked(r);
8097 }
8098 }
8099
8100 Binder.restoreCallingIdentity(origId);
8101 }
8102 }
8103
8104 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008105 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008106 synchronized (mSelf) {
8107 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8108 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008109 if (providers != null) {
8110 for (int i=providers.size()-1; i>=0; i--) {
8111 ProviderInfo pi = (ProviderInfo)providers.get(i);
8112 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8113 Slog.w(TAG, "Not installing system proc provider " + pi.name
8114 + ": not system .apk");
8115 providers.remove(i);
8116 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008117 }
8118 }
8119 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008120 if (providers != null) {
8121 mSystemThread.installSystemProviders(providers);
8122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 }
8124
8125 // =========================================================
8126 // GLOBAL MANAGEMENT
8127 // =========================================================
8128
8129 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8130 ApplicationInfo info, String customProcess) {
8131 String proc = customProcess != null ? customProcess : info.processName;
8132 BatteryStatsImpl.Uid.Proc ps = null;
8133 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8134 synchronized (stats) {
8135 ps = stats.getProcessStatsLocked(info.uid, proc);
8136 }
8137 return new ProcessRecord(ps, thread, info, proc);
8138 }
8139
8140 final ProcessRecord addAppLocked(ApplicationInfo info) {
8141 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8142
8143 if (app == null) {
8144 app = newProcessRecordLocked(null, info, null);
8145 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008146 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008147 }
8148
8149 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8150 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8151 app.persistent = true;
8152 app.maxAdj = CORE_SERVER_ADJ;
8153 }
8154 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8155 mPersistentStartingProcesses.add(app);
8156 startProcessLocked(app, "added application", app.processName);
8157 }
8158
8159 return app;
8160 }
8161
8162 public void unhandledBack() {
8163 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8164 "unhandledBack()");
8165
8166 synchronized(this) {
8167 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008168 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008169 TAG, "Performing unhandledBack(): stack size = " + count);
8170 if (count > 1) {
8171 final long origId = Binder.clearCallingIdentity();
8172 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8173 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8174 Binder.restoreCallingIdentity(origId);
8175 }
8176 }
8177 }
8178
8179 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8180 String name = uri.getAuthority();
8181 ContentProviderHolder cph = getContentProviderExternal(name);
8182 ParcelFileDescriptor pfd = null;
8183 if (cph != null) {
8184 // We record the binder invoker's uid in thread-local storage before
8185 // going to the content provider to open the file. Later, in the code
8186 // that handles all permissions checks, we look for this uid and use
8187 // that rather than the Activity Manager's own uid. The effect is that
8188 // we do the check against the caller's permissions even though it looks
8189 // to the content provider like the Activity Manager itself is making
8190 // the request.
8191 sCallerIdentity.set(new Identity(
8192 Binder.getCallingPid(), Binder.getCallingUid()));
8193 try {
8194 pfd = cph.provider.openFile(uri, "r");
8195 } catch (FileNotFoundException e) {
8196 // do nothing; pfd will be returned null
8197 } finally {
8198 // Ensure that whatever happens, we clean up the identity state
8199 sCallerIdentity.remove();
8200 }
8201
8202 // We've got the fd now, so we're done with the provider.
8203 removeContentProviderExternal(name);
8204 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008205 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008206 }
8207 return pfd;
8208 }
8209
8210 public void goingToSleep() {
8211 synchronized(this) {
8212 mSleeping = true;
8213 mWindowManager.setEventDispatching(false);
8214
8215 if (mResumedActivity != null) {
8216 pauseIfSleepingLocked();
8217 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008218 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 }
8220 }
8221 }
8222
Dianne Hackborn55280a92009-05-07 15:53:46 -07008223 public boolean shutdown(int timeout) {
8224 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8225 != PackageManager.PERMISSION_GRANTED) {
8226 throw new SecurityException("Requires permission "
8227 + android.Manifest.permission.SHUTDOWN);
8228 }
8229
8230 boolean timedout = false;
8231
8232 synchronized(this) {
8233 mShuttingDown = true;
8234 mWindowManager.setEventDispatching(false);
8235
8236 if (mResumedActivity != null) {
8237 pauseIfSleepingLocked();
8238 final long endTime = System.currentTimeMillis() + timeout;
8239 while (mResumedActivity != null || mPausingActivity != null) {
8240 long delay = endTime - System.currentTimeMillis();
8241 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008242 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008243 timedout = true;
8244 break;
8245 }
8246 try {
8247 this.wait();
8248 } catch (InterruptedException e) {
8249 }
8250 }
8251 }
8252 }
8253
8254 mUsageStatsService.shutdown();
8255 mBatteryStatsService.shutdown();
8256
8257 return timedout;
8258 }
8259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008261 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008262 if (!mGoingToSleep.isHeld()) {
8263 mGoingToSleep.acquire();
8264 if (mLaunchingActivity.isHeld()) {
8265 mLaunchingActivity.release();
8266 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8267 }
8268 }
8269
8270 // If we are not currently pausing an activity, get the current
8271 // one to pause. If we are pausing one, we will just let that stuff
8272 // run and release the wake lock when all done.
8273 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008274 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8275 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008276 startPausingLocked(false, true);
8277 }
8278 }
8279 }
8280
8281 public void wakingUp() {
8282 synchronized(this) {
8283 if (mGoingToSleep.isHeld()) {
8284 mGoingToSleep.release();
8285 }
8286 mWindowManager.setEventDispatching(true);
8287 mSleeping = false;
8288 resumeTopActivityLocked(null);
8289 }
8290 }
8291
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008292 public void stopAppSwitches() {
8293 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8294 != PackageManager.PERMISSION_GRANTED) {
8295 throw new SecurityException("Requires permission "
8296 + android.Manifest.permission.STOP_APP_SWITCHES);
8297 }
8298
8299 synchronized(this) {
8300 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8301 + APP_SWITCH_DELAY_TIME;
8302 mDidAppSwitch = false;
8303 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8304 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8305 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8306 }
8307 }
8308
8309 public void resumeAppSwitches() {
8310 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8311 != PackageManager.PERMISSION_GRANTED) {
8312 throw new SecurityException("Requires permission "
8313 + android.Manifest.permission.STOP_APP_SWITCHES);
8314 }
8315
8316 synchronized(this) {
8317 // Note that we don't execute any pending app switches... we will
8318 // let those wait until either the timeout, or the next start
8319 // activity request.
8320 mAppSwitchesAllowedTime = 0;
8321 }
8322 }
8323
8324 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8325 String name) {
8326 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8327 return true;
8328 }
8329
8330 final int perm = checkComponentPermission(
8331 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8332 callingUid, -1);
8333 if (perm == PackageManager.PERMISSION_GRANTED) {
8334 return true;
8335 }
8336
Joe Onorato8a9b2202010-02-26 18:56:32 -08008337 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008338 return false;
8339 }
8340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 public void setDebugApp(String packageName, boolean waitForDebugger,
8342 boolean persistent) {
8343 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8344 "setDebugApp()");
8345
8346 // Note that this is not really thread safe if there are multiple
8347 // callers into it at the same time, but that's not a situation we
8348 // care about.
8349 if (persistent) {
8350 final ContentResolver resolver = mContext.getContentResolver();
8351 Settings.System.putString(
8352 resolver, Settings.System.DEBUG_APP,
8353 packageName);
8354 Settings.System.putInt(
8355 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8356 waitForDebugger ? 1 : 0);
8357 }
8358
8359 synchronized (this) {
8360 if (!persistent) {
8361 mOrigDebugApp = mDebugApp;
8362 mOrigWaitForDebugger = mWaitForDebugger;
8363 }
8364 mDebugApp = packageName;
8365 mWaitForDebugger = waitForDebugger;
8366 mDebugTransient = !persistent;
8367 if (packageName != null) {
8368 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008369 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008370 Binder.restoreCallingIdentity(origId);
8371 }
8372 }
8373 }
8374
8375 public void setAlwaysFinish(boolean enabled) {
8376 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8377 "setAlwaysFinish()");
8378
8379 Settings.System.putInt(
8380 mContext.getContentResolver(),
8381 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8382
8383 synchronized (this) {
8384 mAlwaysFinishActivities = enabled;
8385 }
8386 }
8387
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008388 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008389 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008390 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008391 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008392 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008393 }
8394 }
8395
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008396 public boolean isUserAMonkey() {
8397 // For now the fact that there is a controller implies
8398 // we have a monkey.
8399 synchronized (this) {
8400 return mController != null;
8401 }
8402 }
8403
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008404 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008405 synchronized (this) {
8406 mWatchers.register(watcher);
8407 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008408 }
8409
8410 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008411 synchronized (this) {
8412 mWatchers.unregister(watcher);
8413 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008414 }
8415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008416 public final void enterSafeMode() {
8417 synchronized(this) {
8418 // It only makes sense to do this before the system is ready
8419 // and started launching other packages.
8420 if (!mSystemReady) {
8421 try {
8422 ActivityThread.getPackageManager().enterSafeMode();
8423 } catch (RemoteException e) {
8424 }
8425
8426 View v = LayoutInflater.from(mContext).inflate(
8427 com.android.internal.R.layout.safe_mode, null);
8428 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8429 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8430 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8431 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8432 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8433 lp.format = v.getBackground().getOpacity();
8434 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8435 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8436 ((WindowManager)mContext.getSystemService(
8437 Context.WINDOW_SERVICE)).addView(v, lp);
8438 }
8439 }
8440 }
8441
8442 public void noteWakeupAlarm(IIntentSender sender) {
8443 if (!(sender instanceof PendingIntentRecord)) {
8444 return;
8445 }
8446 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8447 synchronized (stats) {
8448 if (mBatteryStatsService.isOnBattery()) {
8449 mBatteryStatsService.enforceCallingPermission();
8450 PendingIntentRecord rec = (PendingIntentRecord)sender;
8451 int MY_UID = Binder.getCallingUid();
8452 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8453 BatteryStatsImpl.Uid.Pkg pkg =
8454 stats.getPackageStatsLocked(uid, rec.key.packageName);
8455 pkg.incWakeupsLocked();
8456 }
8457 }
8458 }
8459
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008460 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008461 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008462 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008464 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008465 // XXX Note: don't acquire main activity lock here, because the window
8466 // manager calls in with its locks held.
8467
8468 boolean killed = false;
8469 synchronized (mPidsSelfLocked) {
8470 int[] types = new int[pids.length];
8471 int worstType = 0;
8472 for (int i=0; i<pids.length; i++) {
8473 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8474 if (proc != null) {
8475 int type = proc.setAdj;
8476 types[i] = type;
8477 if (type > worstType) {
8478 worstType = type;
8479 }
8480 }
8481 }
8482
8483 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8484 // then constrain it so we will kill all hidden procs.
8485 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8486 worstType = HIDDEN_APP_MIN_ADJ;
8487 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008488 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008489 for (int i=0; i<pids.length; i++) {
8490 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8491 if (proc == null) {
8492 continue;
8493 }
8494 int adj = proc.setAdj;
8495 if (adj >= worstType) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008496 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008497 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8498 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008499 killed = true;
8500 Process.killProcess(pids[i]);
8501 }
8502 }
8503 }
8504 return killed;
8505 }
8506
8507 public void reportPss(IApplicationThread caller, int pss) {
8508 Watchdog.PssRequestor req;
8509 String name;
8510 ProcessRecord callerApp;
8511 synchronized (this) {
8512 if (caller == null) {
8513 return;
8514 }
8515 callerApp = getRecordForAppLocked(caller);
8516 if (callerApp == null) {
8517 return;
8518 }
8519 callerApp.lastPss = pss;
8520 req = callerApp;
8521 name = callerApp.processName;
8522 }
8523 Watchdog.getInstance().reportPss(req, name, pss);
8524 if (!callerApp.persistent) {
8525 removeRequestedPss(callerApp);
8526 }
8527 }
8528
8529 public void requestPss(Runnable completeCallback) {
8530 ArrayList<ProcessRecord> procs;
8531 synchronized (this) {
8532 mRequestPssCallback = completeCallback;
8533 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008534 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8535 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008536 if (!proc.persistent) {
8537 mRequestPssList.add(proc);
8538 }
8539 }
8540 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8541 }
8542
8543 int oldPri = Process.getThreadPriority(Process.myTid());
8544 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8545 for (int i=procs.size()-1; i>=0; i--) {
8546 ProcessRecord proc = procs.get(i);
8547 proc.lastPss = 0;
8548 proc.requestPss();
8549 }
8550 Process.setThreadPriority(oldPri);
8551 }
8552
8553 void removeRequestedPss(ProcessRecord proc) {
8554 Runnable callback = null;
8555 synchronized (this) {
8556 if (mRequestPssList.remove(proc)) {
8557 if (mRequestPssList.size() == 0) {
8558 callback = mRequestPssCallback;
8559 mRequestPssCallback = null;
8560 }
8561 }
8562 }
8563
8564 if (callback != null) {
8565 callback.run();
8566 }
8567 }
8568
8569 public void collectPss(Watchdog.PssStats stats) {
8570 stats.mEmptyPss = 0;
8571 stats.mEmptyCount = 0;
8572 stats.mBackgroundPss = 0;
8573 stats.mBackgroundCount = 0;
8574 stats.mServicePss = 0;
8575 stats.mServiceCount = 0;
8576 stats.mVisiblePss = 0;
8577 stats.mVisibleCount = 0;
8578 stats.mForegroundPss = 0;
8579 stats.mForegroundCount = 0;
8580 stats.mNoPssCount = 0;
8581 synchronized (this) {
8582 int i;
8583 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8584 ? mProcDeaths.length : stats.mProcDeaths.length;
8585 int aggr = 0;
8586 for (i=0; i<NPD; i++) {
8587 aggr += mProcDeaths[i];
8588 stats.mProcDeaths[i] = aggr;
8589 }
8590 while (i<stats.mProcDeaths.length) {
8591 stats.mProcDeaths[i] = 0;
8592 i++;
8593 }
8594
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008595 for (i=mLruProcesses.size()-1; i>=0; i--) {
8596 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008597 if (proc.persistent) {
8598 continue;
8599 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008600 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008601 if (proc.lastPss == 0) {
8602 stats.mNoPssCount++;
8603 continue;
8604 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008605 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8606 if (proc.empty) {
8607 stats.mEmptyPss += proc.lastPss;
8608 stats.mEmptyCount++;
8609 } else {
8610 stats.mBackgroundPss += proc.lastPss;
8611 stats.mBackgroundCount++;
8612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8614 stats.mVisiblePss += proc.lastPss;
8615 stats.mVisibleCount++;
8616 } else {
8617 stats.mForegroundPss += proc.lastPss;
8618 stats.mForegroundCount++;
8619 }
8620 }
8621 }
8622 }
8623
8624 public final void startRunning(String pkg, String cls, String action,
8625 String data) {
8626 synchronized(this) {
8627 if (mStartRunning) {
8628 return;
8629 }
8630 mStartRunning = true;
8631 mTopComponent = pkg != null && cls != null
8632 ? new ComponentName(pkg, cls) : null;
8633 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8634 mTopData = data;
8635 if (!mSystemReady) {
8636 return;
8637 }
8638 }
8639
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008640 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008641 }
8642
8643 private void retrieveSettings() {
8644 final ContentResolver resolver = mContext.getContentResolver();
8645 String debugApp = Settings.System.getString(
8646 resolver, Settings.System.DEBUG_APP);
8647 boolean waitForDebugger = Settings.System.getInt(
8648 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8649 boolean alwaysFinishActivities = Settings.System.getInt(
8650 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8651
8652 Configuration configuration = new Configuration();
8653 Settings.System.getConfiguration(resolver, configuration);
8654
8655 synchronized (this) {
8656 mDebugApp = mOrigDebugApp = debugApp;
8657 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8658 mAlwaysFinishActivities = alwaysFinishActivities;
8659 // This happens before any activities are started, so we can
8660 // change mConfiguration in-place.
8661 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008662 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008663 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008664 }
8665 }
8666
8667 public boolean testIsSystemReady() {
8668 // no need to synchronize(this) just to read & return the value
8669 return mSystemReady;
8670 }
8671
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008672 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008673 // In the simulator, startRunning will never have been called, which
8674 // normally sets a few crucial variables. Do it here instead.
8675 if (!Process.supportsProcesses()) {
8676 mStartRunning = true;
8677 mTopAction = Intent.ACTION_MAIN;
8678 }
8679
8680 synchronized(this) {
8681 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008682 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683 return;
8684 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008685
8686 // Check to see if there are any update receivers to run.
8687 if (!mDidUpdate) {
8688 if (mWaitingUpdate) {
8689 return;
8690 }
8691 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8692 List<ResolveInfo> ris = null;
8693 try {
8694 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8695 intent, null, 0);
8696 } catch (RemoteException e) {
8697 }
8698 if (ris != null) {
8699 for (int i=ris.size()-1; i>=0; i--) {
8700 if ((ris.get(i).activityInfo.applicationInfo.flags
8701 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8702 ris.remove(i);
8703 }
8704 }
8705 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8706 for (int i=0; i<ris.size(); i++) {
8707 ActivityInfo ai = ris.get(i).activityInfo;
8708 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8709 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008710 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008711 finisher = new IIntentReceiver.Stub() {
8712 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008713 String data, Bundle extras, boolean ordered,
8714 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008715 throws RemoteException {
8716 synchronized (ActivityManagerService.this) {
8717 mDidUpdate = true;
8718 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008719 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008720 }
8721 };
8722 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008723 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008724 broadcastIntentLocked(null, null, intent, null, finisher,
8725 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008726 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008727 mWaitingUpdate = true;
8728 }
8729 }
8730 }
8731 if (mWaitingUpdate) {
8732 return;
8733 }
8734 mDidUpdate = true;
8735 }
8736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008737 mSystemReady = true;
8738 if (!mStartRunning) {
8739 return;
8740 }
8741 }
8742
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008743 ArrayList<ProcessRecord> procsToKill = null;
8744 synchronized(mPidsSelfLocked) {
8745 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8746 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8747 if (!isAllowedWhileBooting(proc.info)){
8748 if (procsToKill == null) {
8749 procsToKill = new ArrayList<ProcessRecord>();
8750 }
8751 procsToKill.add(proc);
8752 }
8753 }
8754 }
8755
8756 if (procsToKill != null) {
8757 synchronized(this) {
8758 for (int i=procsToKill.size()-1; i>=0; i--) {
8759 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008760 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008761 removeProcessLocked(proc, true);
8762 }
8763 }
8764 }
8765
Joe Onorato8a9b2202010-02-26 18:56:32 -08008766 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008767 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008768 SystemClock.uptimeMillis());
8769
8770 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008771 // Make sure we have no pre-ready processes sitting around.
8772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008773 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8774 ResolveInfo ri = mContext.getPackageManager()
8775 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008776 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008777 CharSequence errorMsg = null;
8778 if (ri != null) {
8779 ActivityInfo ai = ri.activityInfo;
8780 ApplicationInfo app = ai.applicationInfo;
8781 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8782 mTopAction = Intent.ACTION_FACTORY_TEST;
8783 mTopData = null;
8784 mTopComponent = new ComponentName(app.packageName,
8785 ai.name);
8786 } else {
8787 errorMsg = mContext.getResources().getText(
8788 com.android.internal.R.string.factorytest_not_system);
8789 }
8790 } else {
8791 errorMsg = mContext.getResources().getText(
8792 com.android.internal.R.string.factorytest_no_action);
8793 }
8794 if (errorMsg != null) {
8795 mTopAction = null;
8796 mTopData = null;
8797 mTopComponent = null;
8798 Message msg = Message.obtain();
8799 msg.what = SHOW_FACTORY_ERROR_MSG;
8800 msg.getData().putCharSequence("msg", errorMsg);
8801 mHandler.sendMessage(msg);
8802 }
8803 }
8804 }
8805
8806 retrieveSettings();
8807
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008808 if (goingCallback != null) goingCallback.run();
8809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008810 synchronized (this) {
8811 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8812 try {
8813 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008814 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008815 if (apps != null) {
8816 int N = apps.size();
8817 int i;
8818 for (i=0; i<N; i++) {
8819 ApplicationInfo info
8820 = (ApplicationInfo)apps.get(i);
8821 if (info != null &&
8822 !info.packageName.equals("android")) {
8823 addAppLocked(info);
8824 }
8825 }
8826 }
8827 } catch (RemoteException ex) {
8828 // pm is in same process, this will never happen.
8829 }
8830 }
8831
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008832 // Start up initial activity.
8833 mBooting = true;
8834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008835 try {
8836 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8837 Message msg = Message.obtain();
8838 msg.what = SHOW_UID_ERROR_MSG;
8839 mHandler.sendMessage(msg);
8840 }
8841 } catch (RemoteException e) {
8842 }
8843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008844 resumeTopActivityLocked(null);
8845 }
8846 }
8847
Dan Egnorb7f03672009-12-09 16:22:32 -08008848 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008849 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008850 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008851 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008852 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008853 startAppProblemLocked(app);
8854 app.stopFreezingAllLocked();
8855 return handleAppCrashLocked(app);
8856 }
8857
Dan Egnorb7f03672009-12-09 16:22:32 -08008858 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008859 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008860 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008861 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008862 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8863 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008864 startAppProblemLocked(app);
8865 app.stopFreezingAllLocked();
8866 }
8867
8868 /**
8869 * Generate a process error record, suitable for attachment to a ProcessRecord.
8870 *
8871 * @param app The ProcessRecord in which the error occurred.
8872 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8873 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008874 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008875 * @param shortMsg Short message describing the crash.
8876 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008877 * @param stackTrace Full crash stack trace, may be null.
8878 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008879 * @return Returns a fully-formed AppErrorStateInfo record.
8880 */
8881 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008882 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008883 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008885 report.condition = condition;
8886 report.processName = app.processName;
8887 report.pid = app.pid;
8888 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008889 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008890 report.shortMsg = shortMsg;
8891 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008892 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008893
8894 return report;
8895 }
8896
Dan Egnor42471dd2010-01-07 17:25:22 -08008897 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008898 synchronized (this) {
8899 app.crashing = false;
8900 app.crashingReport = null;
8901 app.notResponding = false;
8902 app.notRespondingReport = null;
8903 if (app.anrDialog == fromDialog) {
8904 app.anrDialog = null;
8905 }
8906 if (app.waitDialog == fromDialog) {
8907 app.waitDialog = null;
8908 }
8909 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008910 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07008911 Slog.i(ActivityManagerService.TAG, "Killing "
8912 + app.processName + " (pid=" + app.pid + "): user's request");
8913 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
8914 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008915 Process.killProcess(app.pid);
8916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008917 }
8918 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008919
Dan Egnorb7f03672009-12-09 16:22:32 -08008920 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008921 long now = SystemClock.uptimeMillis();
8922
8923 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8924 app.info.uid);
8925 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8926 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008927 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008929 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008930 app.info.processName, app.info.uid);
8931 killServicesLocked(app, false);
8932 for (int i=mHistory.size()-1; i>=0; i--) {
8933 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8934 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008935 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008936 + r.intent.getComponent().flattenToShortString());
8937 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8938 }
8939 }
8940 if (!app.persistent) {
8941 // We don't want to start this process again until the user
8942 // explicitly does so... but for persistent process, we really
8943 // need to keep it running. If a persistent process is actually
8944 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008945 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008946 app.info.processName);
8947 mBadProcesses.put(app.info.processName, app.info.uid, now);
8948 app.bad = true;
8949 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8950 app.removed = true;
8951 removeProcessLocked(app, false);
8952 return false;
8953 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008954 } else {
8955 HistoryRecord r = topRunningActivityLocked(null);
8956 if (r.app == app) {
8957 // If the top running activity is from this crashing
8958 // process, then terminate it to avoid getting in a loop.
8959 Slog.w(TAG, " Force finishing activity "
8960 + r.intent.getComponent().flattenToShortString());
8961 int index = indexOfTokenLocked(r);
8962 finishActivityLocked(r, index,
8963 Activity.RESULT_CANCELED, null, "crashed");
8964 // Also terminate an activities below it that aren't yet
8965 // stopped, to avoid a situation where one will get
8966 // re-start our crashing activity once it gets resumed again.
8967 index--;
8968 if (index >= 0) {
8969 r = (HistoryRecord)mHistory.get(index);
8970 if (r.state == ActivityState.RESUMED
8971 || r.state == ActivityState.PAUSING
8972 || r.state == ActivityState.PAUSED) {
8973 if (!r.isHomeActivity) {
8974 Slog.w(TAG, " Force finishing activity "
8975 + r.intent.getComponent().flattenToShortString());
8976 finishActivityLocked(r, index,
8977 Activity.RESULT_CANCELED, null, "crashed");
8978 }
8979 }
8980 }
8981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008982 }
8983
8984 // Bump up the crash count of any services currently running in the proc.
8985 if (app.services.size() != 0) {
8986 // Any services running in the application need to be placed
8987 // back in the pending list.
8988 Iterator it = app.services.iterator();
8989 while (it.hasNext()) {
8990 ServiceRecord sr = (ServiceRecord)it.next();
8991 sr.crashCount++;
8992 }
8993 }
8994
8995 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8996 return true;
8997 }
8998
8999 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009000 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9001 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009002 skipCurrentReceiverLocked(app);
9003 }
9004
9005 void skipCurrentReceiverLocked(ProcessRecord app) {
9006 boolean reschedule = false;
9007 BroadcastRecord r = app.curReceiver;
9008 if (r != null) {
9009 // The current broadcast is waiting for this app's receiver
9010 // to be finished. Looks like that's not going to happen, so
9011 // let the broadcast continue.
9012 logBroadcastReceiverDiscard(r);
9013 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9014 r.resultExtras, r.resultAbort, true);
9015 reschedule = true;
9016 }
9017 r = mPendingBroadcast;
9018 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009019 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009020 "skip & discard pending app " + r);
9021 logBroadcastReceiverDiscard(r);
9022 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9023 r.resultExtras, r.resultAbort, true);
9024 reschedule = true;
9025 }
9026 if (reschedule) {
9027 scheduleBroadcastsLocked();
9028 }
9029 }
9030
Dan Egnor60d87622009-12-16 16:32:58 -08009031 /**
9032 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9033 * The application process will exit immediately after this call returns.
9034 * @param app object of the crashing app, null for the system server
9035 * @param crashInfo describing the exception
9036 */
9037 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9038 ProcessRecord r = findAppProcess(app);
9039
9040 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9041 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009042 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009043 crashInfo.exceptionClassName,
9044 crashInfo.exceptionMessage,
9045 crashInfo.throwFileName,
9046 crashInfo.throwLineNumber);
9047
Dan Egnor42471dd2010-01-07 17:25:22 -08009048 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009049
9050 crashApplication(r, crashInfo);
9051 }
9052
9053 /**
9054 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9055 * @param app object of the crashing app, null for the system server
9056 * @param tag reported by the caller
9057 * @param crashInfo describing the context of the error
9058 * @return true if the process should exit immediately (WTF is fatal)
9059 */
9060 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009061 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009062 ProcessRecord r = findAppProcess(app);
9063
9064 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9065 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009066 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009067 tag, crashInfo.exceptionMessage);
9068
Dan Egnor42471dd2010-01-07 17:25:22 -08009069 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009070
Doug Zongker43866e02010-01-07 12:09:54 -08009071 if (Settings.Secure.getInt(mContext.getContentResolver(),
9072 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009073 crashApplication(r, crashInfo);
9074 return true;
9075 } else {
9076 return false;
9077 }
9078 }
9079
9080 /**
9081 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9082 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9083 */
9084 private ProcessRecord findAppProcess(IBinder app) {
9085 if (app == null) {
9086 return null;
9087 }
9088
9089 synchronized (this) {
9090 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9091 final int NA = apps.size();
9092 for (int ia=0; ia<NA; ia++) {
9093 ProcessRecord p = apps.valueAt(ia);
9094 if (p.thread != null && p.thread.asBinder() == app) {
9095 return p;
9096 }
9097 }
9098 }
9099
Joe Onorato8a9b2202010-02-26 18:56:32 -08009100 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009101 return null;
9102 }
9103 }
9104
9105 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009106 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009107 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009108 * @param process which caused the error, null means the system server
9109 * @param activity which triggered the error, null if unknown
9110 * @param parent activity related to the error, null if unknown
9111 * @param subject line related to the error, null if absent
9112 * @param report in long form describing the error, null if absent
9113 * @param logFile to include in the report, null if none
9114 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009115 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009116 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009117 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9118 final String report, final File logFile,
9119 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009120 // NOTE -- this must never acquire the ActivityManagerService lock,
9121 // otherwise the watchdog may be prevented from resetting the system.
9122
Dan Egnora455d192010-03-12 08:52:28 -08009123 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009124 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009125 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009126 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009127 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009128 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009129 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009130 }
9131
Dan Egnora455d192010-03-12 08:52:28 -08009132 final String dropboxTag = prefix + eventType;
9133 final DropBoxManager dbox = (DropBoxManager)
9134 mContext.getSystemService(Context.DROPBOX_SERVICE);
9135
9136 // Exit early if the dropbox isn't configured to accept this report type.
9137 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9138
9139 final StringBuilder sb = new StringBuilder(1024);
9140 if (process == null || process.pid == MY_PID) {
9141 sb.append("Process: system_server\n");
9142 } else {
9143 sb.append("Process: ").append(process.processName).append("\n");
9144 }
9145 if (process != null) {
9146 int flags = process.info.flags;
9147 IPackageManager pm = ActivityThread.getPackageManager();
9148 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9149 for (String pkg : process.pkgList) {
9150 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009151 try {
Dan Egnora455d192010-03-12 08:52:28 -08009152 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9153 if (pi != null) {
9154 sb.append(" v").append(pi.versionCode);
9155 if (pi.versionName != null) {
9156 sb.append(" (").append(pi.versionName).append(")");
9157 }
9158 }
9159 } catch (RemoteException e) {
9160 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009161 }
Dan Egnora455d192010-03-12 08:52:28 -08009162 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009163 }
Dan Egnora455d192010-03-12 08:52:28 -08009164 }
9165 if (activity != null) {
9166 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9167 }
9168 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9169 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9170 }
9171 if (parent != null && parent != activity) {
9172 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9173 }
9174 if (subject != null) {
9175 sb.append("Subject: ").append(subject).append("\n");
9176 }
9177 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9178 sb.append("\n");
9179
9180 // Do the rest in a worker thread to avoid blocking the caller on I/O
9181 // (After this point, we shouldn't access AMS internal data structures.)
9182 Thread worker = new Thread("Error dump: " + dropboxTag) {
9183 @Override
9184 public void run() {
9185 if (report != null) {
9186 sb.append(report);
9187 }
9188 if (logFile != null) {
9189 try {
9190 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9191 } catch (IOException e) {
9192 Slog.e(TAG, "Error reading " + logFile, e);
9193 }
9194 }
9195 if (crashInfo != null && crashInfo.stackTrace != null) {
9196 sb.append(crashInfo.stackTrace);
9197 }
9198
9199 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9200 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9201 if (lines > 0) {
9202 sb.append("\n");
9203
9204 // Merge several logcat streams, and take the last N lines
9205 InputStreamReader input = null;
9206 try {
9207 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9208 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9209 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9210
9211 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9212 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9213 input = new InputStreamReader(logcat.getInputStream());
9214
9215 int num;
9216 char[] buf = new char[8192];
9217 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9218 } catch (IOException e) {
9219 Slog.e(TAG, "Error running logcat", e);
9220 } finally {
9221 if (input != null) try { input.close(); } catch (IOException e) {}
9222 }
9223 }
9224
9225 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009226 }
Dan Egnora455d192010-03-12 08:52:28 -08009227 };
9228
9229 if (process == null || process.pid == MY_PID) {
9230 worker.run(); // We may be about to die -- need to run this synchronously
9231 } else {
9232 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009233 }
9234 }
9235
9236 /**
9237 * Bring up the "unexpected error" dialog box for a crashing app.
9238 * Deal with edge cases (intercepts from instrumented applications,
9239 * ActivityController, error intent receivers, that sort of thing).
9240 * @param r the application crashing
9241 * @param crashInfo describing the failure
9242 */
9243 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009244 long timeMillis = System.currentTimeMillis();
9245 String shortMsg = crashInfo.exceptionClassName;
9246 String longMsg = crashInfo.exceptionMessage;
9247 String stackTrace = crashInfo.stackTrace;
9248 if (shortMsg != null && longMsg != null) {
9249 longMsg = shortMsg + ": " + longMsg;
9250 } else if (shortMsg != null) {
9251 longMsg = shortMsg;
9252 }
9253
Dan Egnor60d87622009-12-16 16:32:58 -08009254 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009255 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009256 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009257 try {
9258 String name = r != null ? r.processName : null;
9259 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009260 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009261 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009262 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009263 + " at watcher's request");
9264 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009265 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009266 }
9267 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009268 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009269 }
9270 }
9271
9272 final long origId = Binder.clearCallingIdentity();
9273
9274 // If this process is running instrumentation, finish it.
9275 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009276 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009277 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009278 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9279 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009280 Bundle info = new Bundle();
9281 info.putString("shortMsg", shortMsg);
9282 info.putString("longMsg", longMsg);
9283 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9284 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009285 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286 }
9287
Dan Egnor60d87622009-12-16 16:32:58 -08009288 // If we can't identify the process or it's already exceeded its crash quota,
9289 // quit right away without showing a crash dialog.
9290 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009292 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009293 }
9294
9295 Message msg = Message.obtain();
9296 msg.what = SHOW_ERROR_MSG;
9297 HashMap data = new HashMap();
9298 data.put("result", result);
9299 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009300 msg.obj = data;
9301 mHandler.sendMessage(msg);
9302
9303 Binder.restoreCallingIdentity(origId);
9304 }
9305
9306 int res = result.get();
9307
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009308 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009309 synchronized (this) {
9310 if (r != null) {
9311 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9312 SystemClock.uptimeMillis());
9313 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009314 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009315 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009316 }
9317 }
9318
9319 if (appErrorIntent != null) {
9320 try {
9321 mContext.startActivity(appErrorIntent);
9322 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009323 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009324 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009327
9328 Intent createAppErrorIntentLocked(ProcessRecord r,
9329 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9330 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009331 if (report == null) {
9332 return null;
9333 }
9334 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9335 result.setComponent(r.errorReportReceiver);
9336 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9337 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9338 return result;
9339 }
9340
Dan Egnorb7f03672009-12-09 16:22:32 -08009341 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9342 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009343 if (r.errorReportReceiver == null) {
9344 return null;
9345 }
9346
9347 if (!r.crashing && !r.notResponding) {
9348 return null;
9349 }
9350
Dan Egnorb7f03672009-12-09 16:22:32 -08009351 ApplicationErrorReport report = new ApplicationErrorReport();
9352 report.packageName = r.info.packageName;
9353 report.installerPackageName = r.errorReportReceiver.getPackageName();
9354 report.processName = r.processName;
9355 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009356 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009357
Dan Egnorb7f03672009-12-09 16:22:32 -08009358 if (r.crashing) {
9359 report.type = ApplicationErrorReport.TYPE_CRASH;
9360 report.crashInfo = crashInfo;
9361 } else if (r.notResponding) {
9362 report.type = ApplicationErrorReport.TYPE_ANR;
9363 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009364
Dan Egnorb7f03672009-12-09 16:22:32 -08009365 report.anrInfo.activity = r.notRespondingReport.tag;
9366 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9367 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009368 }
9369
Dan Egnorb7f03672009-12-09 16:22:32 -08009370 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009371 }
9372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009373 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9374 // assume our apps are happy - lazy create the list
9375 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9376
9377 synchronized (this) {
9378
9379 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009380 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9381 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009382 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9383 // This one's in trouble, so we'll generate a report for it
9384 // crashes are higher priority (in case there's a crash *and* an anr)
9385 ActivityManager.ProcessErrorStateInfo report = null;
9386 if (app.crashing) {
9387 report = app.crashingReport;
9388 } else if (app.notResponding) {
9389 report = app.notRespondingReport;
9390 }
9391
9392 if (report != null) {
9393 if (errList == null) {
9394 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9395 }
9396 errList.add(report);
9397 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009398 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009399 " crashing = " + app.crashing +
9400 " notResponding = " + app.notResponding);
9401 }
9402 }
9403 }
9404 }
9405
9406 return errList;
9407 }
9408
9409 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9410 // Lazy instantiation of list
9411 List<ActivityManager.RunningAppProcessInfo> runList = null;
9412 synchronized (this) {
9413 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009414 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9415 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009416 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9417 // Generate process state info for running application
9418 ActivityManager.RunningAppProcessInfo currApp =
9419 new ActivityManager.RunningAppProcessInfo(app.processName,
9420 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009421 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009422 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009423 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009424 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9425 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9426 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009427 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9428 } else if (adj >= HOME_APP_ADJ) {
9429 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9430 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009431 } else if (adj >= SECONDARY_SERVER_ADJ) {
9432 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9433 } else if (adj >= VISIBLE_APP_ADJ) {
9434 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9435 } else {
9436 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9437 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009438 currApp.importanceReasonCode = app.adjTypeCode;
9439 if (app.adjSource instanceof ProcessRecord) {
9440 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9441 } else if (app.adjSource instanceof HistoryRecord) {
9442 HistoryRecord r = (HistoryRecord)app.adjSource;
9443 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9444 }
9445 if (app.adjTarget instanceof ComponentName) {
9446 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9447 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009448 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009449 // + " lru=" + currApp.lru);
9450 if (runList == null) {
9451 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9452 }
9453 runList.add(currApp);
9454 }
9455 }
9456 }
9457 return runList;
9458 }
9459
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009460 public List<ApplicationInfo> getRunningExternalApplications() {
9461 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9462 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9463 if (runningApps != null && runningApps.size() > 0) {
9464 Set<String> extList = new HashSet<String>();
9465 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9466 if (app.pkgList != null) {
9467 for (String pkg : app.pkgList) {
9468 extList.add(pkg);
9469 }
9470 }
9471 }
9472 IPackageManager pm = ActivityThread.getPackageManager();
9473 for (String pkg : extList) {
9474 try {
9475 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9476 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9477 retList.add(info);
9478 }
9479 } catch (RemoteException e) {
9480 }
9481 }
9482 }
9483 return retList;
9484 }
9485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009486 @Override
9487 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009488 if (checkCallingPermission(android.Manifest.permission.DUMP)
9489 != PackageManager.PERMISSION_GRANTED) {
9490 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9491 + Binder.getCallingPid()
9492 + ", uid=" + Binder.getCallingUid()
9493 + " without permission "
9494 + android.Manifest.permission.DUMP);
9495 return;
9496 }
9497
9498 boolean dumpAll = false;
9499
9500 int opti = 0;
9501 while (opti < args.length) {
9502 String opt = args[opti];
9503 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9504 break;
9505 }
9506 opti++;
9507 if ("-a".equals(opt)) {
9508 dumpAll = true;
9509 } else if ("-h".equals(opt)) {
9510 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009511 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009512 pw.println(" cmd may be one of:");
9513 pw.println(" activities: activity stack state");
9514 pw.println(" broadcasts: broadcast state");
9515 pw.println(" intents: pending intent state");
9516 pw.println(" processes: process state");
9517 pw.println(" providers: content provider state");
9518 pw.println(" services: service state");
9519 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009520 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009521 } else {
9522 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009523 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009524 }
9525
9526 // Is the caller requesting to dump a particular piece of data?
9527 if (opti < args.length) {
9528 String cmd = args[opti];
9529 opti++;
9530 if ("activities".equals(cmd) || "a".equals(cmd)) {
9531 synchronized (this) {
9532 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009533 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009534 return;
9535 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9536 synchronized (this) {
9537 dumpBroadcastsLocked(fd, pw, args, opti, true);
9538 }
9539 return;
9540 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9541 synchronized (this) {
9542 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9543 }
9544 return;
9545 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9546 synchronized (this) {
9547 dumpProcessesLocked(fd, pw, args, opti, true);
9548 }
9549 return;
9550 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9551 synchronized (this) {
9552 dumpProvidersLocked(fd, pw, args, opti, true);
9553 }
9554 return;
9555 } else if ("service".equals(cmd)) {
9556 dumpService(fd, pw, args, opti, true);
9557 return;
9558 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9559 synchronized (this) {
9560 dumpServicesLocked(fd, pw, args, opti, true);
9561 }
9562 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009563 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009564 }
9565
9566 // No piece of data specified, dump everything.
9567 synchronized (this) {
9568 boolean needSep;
9569 if (dumpAll) {
9570 pw.println("Providers in Current Activity Manager State:");
9571 }
9572 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9573 if (needSep) {
9574 pw.println(" ");
9575 }
9576 if (dumpAll) {
9577 pw.println("-------------------------------------------------------------------------------");
9578 pw.println("Broadcasts in Current Activity Manager State:");
9579 }
9580 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9581 if (needSep) {
9582 pw.println(" ");
9583 }
9584 if (dumpAll) {
9585 pw.println("-------------------------------------------------------------------------------");
9586 pw.println("Services in Current Activity Manager State:");
9587 }
9588 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9589 if (needSep) {
9590 pw.println(" ");
9591 }
9592 if (dumpAll) {
9593 pw.println("-------------------------------------------------------------------------------");
9594 pw.println("PendingIntents in Current Activity Manager State:");
9595 }
9596 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9597 if (needSep) {
9598 pw.println(" ");
9599 }
9600 if (dumpAll) {
9601 pw.println("-------------------------------------------------------------------------------");
9602 pw.println("Activities in Current Activity Manager State:");
9603 }
9604 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9605 if (needSep) {
9606 pw.println(" ");
9607 }
9608 if (dumpAll) {
9609 pw.println("-------------------------------------------------------------------------------");
9610 pw.println("Processes in Current Activity Manager State:");
9611 }
9612 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9613 }
9614 }
9615
9616 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9617 int opti, boolean dumpAll, boolean needHeader) {
9618 if (needHeader) {
9619 pw.println(" Activity stack:");
9620 }
9621 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9622 pw.println(" ");
9623 pw.println(" Running activities (most recent first):");
9624 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9625 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009627 pw.println(" Activities waiting for another to become visible:");
9628 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9629 }
9630 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009631 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009632 pw.println(" Activities waiting to stop:");
9633 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9634 }
9635 if (mFinishingActivities.size() > 0) {
9636 pw.println(" ");
9637 pw.println(" Activities waiting to finish:");
9638 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009640
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009641 pw.println(" ");
9642 pw.println(" mPausingActivity: " + mPausingActivity);
9643 pw.println(" mResumedActivity: " + mResumedActivity);
9644 pw.println(" mFocusedActivity: " + mFocusedActivity);
9645 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009646
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009647 if (dumpAll && mRecentTasks.size() > 0) {
9648 pw.println(" ");
9649 pw.println("Recent tasks in Current Activity Manager State:");
9650
9651 final int N = mRecentTasks.size();
9652 for (int i=0; i<N; i++) {
9653 TaskRecord tr = mRecentTasks.get(i);
9654 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9655 pw.println(tr);
9656 mRecentTasks.get(i).dump(pw, " ");
9657 }
9658 }
9659
9660 pw.println(" ");
9661 pw.println(" mCurTask: " + mCurTask);
9662
9663 return true;
9664 }
9665
9666 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9667 int opti, boolean dumpAll) {
9668 boolean needSep = false;
9669 int numPers = 0;
9670
9671 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009672 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9673 final int NA = procs.size();
9674 for (int ia=0; ia<NA; ia++) {
9675 if (!needSep) {
9676 pw.println(" All known processes:");
9677 needSep = true;
9678 }
9679 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009680 pw.print(r.persistent ? " *PERS*" : " *APP*");
9681 pw.print(" UID "); pw.print(procs.keyAt(ia));
9682 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 r.dump(pw, " ");
9684 if (r.persistent) {
9685 numPers++;
9686 }
9687 }
9688 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009689 }
9690
9691 if (mLruProcesses.size() > 0) {
9692 if (needSep) pw.println(" ");
9693 needSep = true;
9694 pw.println(" Running processes (most recent first):");
9695 dumpProcessList(pw, this, mLruProcesses, " ",
9696 "App ", "PERS", true);
9697 needSep = true;
9698 }
9699
9700 synchronized (mPidsSelfLocked) {
9701 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 if (needSep) pw.println(" ");
9703 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009704 pw.println(" PID mappings:");
9705 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9706 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9707 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009708 }
9709 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009710 }
9711
9712 if (mForegroundProcesses.size() > 0) {
9713 if (needSep) pw.println(" ");
9714 needSep = true;
9715 pw.println(" Foreground Processes:");
9716 for (int i=0; i<mForegroundProcesses.size(); i++) {
9717 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9718 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009719 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009720 }
9721
9722 if (mPersistentStartingProcesses.size() > 0) {
9723 if (needSep) pw.println(" ");
9724 needSep = true;
9725 pw.println(" Persisent processes that are starting:");
9726 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9727 "Starting Norm", "Restarting PERS", false);
9728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009729
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009730 if (mStartingProcesses.size() > 0) {
9731 if (needSep) pw.println(" ");
9732 needSep = true;
9733 pw.println(" Processes that are starting:");
9734 dumpProcessList(pw, this, mStartingProcesses, " ",
9735 "Starting Norm", "Starting PERS", false);
9736 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009737
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009738 if (mRemovedProcesses.size() > 0) {
9739 if (needSep) pw.println(" ");
9740 needSep = true;
9741 pw.println(" Processes that are being removed:");
9742 dumpProcessList(pw, this, mRemovedProcesses, " ",
9743 "Removed Norm", "Removed PERS", false);
9744 }
9745
9746 if (mProcessesOnHold.size() > 0) {
9747 if (needSep) pw.println(" ");
9748 needSep = true;
9749 pw.println(" Processes that are on old until the system is ready:");
9750 dumpProcessList(pw, this, mProcessesOnHold, " ",
9751 "OnHold Norm", "OnHold PERS", false);
9752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009753
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009754 if (mProcessesToGc.size() > 0) {
9755 if (needSep) pw.println(" ");
9756 needSep = true;
9757 pw.println(" Processes that are waiting to GC:");
9758 long now = SystemClock.uptimeMillis();
9759 for (int i=0; i<mProcessesToGc.size(); i++) {
9760 ProcessRecord proc = mProcessesToGc.get(i);
9761 pw.print(" Process "); pw.println(proc);
9762 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9763 pw.print(", last gced=");
9764 pw.print(now-proc.lastRequestedGc);
9765 pw.print(" ms ago, last lowMem=");
9766 pw.print(now-proc.lastLowMemory);
9767 pw.println(" ms ago");
9768
9769 }
9770 }
9771
9772 if (mProcessCrashTimes.getMap().size() > 0) {
9773 if (needSep) pw.println(" ");
9774 needSep = true;
9775 pw.println(" Time since processes crashed:");
9776 long now = SystemClock.uptimeMillis();
9777 for (Map.Entry<String, SparseArray<Long>> procs
9778 : mProcessCrashTimes.getMap().entrySet()) {
9779 SparseArray<Long> uids = procs.getValue();
9780 final int N = uids.size();
9781 for (int i=0; i<N; i++) {
9782 pw.print(" Process "); pw.print(procs.getKey());
9783 pw.print(" uid "); pw.print(uids.keyAt(i));
9784 pw.print(": last crashed ");
9785 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009786 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009787 }
9788 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009790
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009791 if (mBadProcesses.getMap().size() > 0) {
9792 if (needSep) pw.println(" ");
9793 needSep = true;
9794 pw.println(" Bad processes:");
9795 for (Map.Entry<String, SparseArray<Long>> procs
9796 : mBadProcesses.getMap().entrySet()) {
9797 SparseArray<Long> uids = procs.getValue();
9798 final int N = uids.size();
9799 for (int i=0; i<N; i++) {
9800 pw.print(" Bad process "); pw.print(procs.getKey());
9801 pw.print(" uid "); pw.print(uids.keyAt(i));
9802 pw.print(": crashed at time ");
9803 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009804 }
9805 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009807
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009808 pw.println(" ");
9809 pw.println(" mHomeProcess: " + mHomeProcess);
9810 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07009811 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009812 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9813 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9814 || mOrigWaitForDebugger) {
9815 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9816 + " mDebugTransient=" + mDebugTransient
9817 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9818 }
9819 if (mAlwaysFinishActivities || mController != null) {
9820 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9821 + " mController=" + mController);
9822 }
9823 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 pw.println(" mStartRunning=" + mStartRunning
9826 + " mSystemReady=" + mSystemReady
9827 + " mBooting=" + mBooting
9828 + " mBooted=" + mBooted
9829 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 pw.println(" mGoingToSleep=" + mGoingToSleep);
9831 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009833
9834 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835 }
9836
9837 /**
9838 * There are three ways to call this:
9839 * - no service specified: dump all the services
9840 * - a flattened component name that matched an existing service was specified as the
9841 * first arg: dump that one service
9842 * - the first arg isn't the flattened component name of an existing service:
9843 * dump all services whose component contains the first arg as a substring
9844 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009845 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9846 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009847 String[] newArgs;
9848 String componentNameString;
9849 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009850 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009851 componentNameString = null;
9852 newArgs = EMPTY_STRING_ARRAY;
9853 r = null;
9854 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009855 componentNameString = args[opti];
9856 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009857 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9858 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009859 newArgs = new String[args.length - opti];
9860 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009861 }
9862
9863 if (r != null) {
9864 dumpService(fd, pw, r, newArgs);
9865 } else {
9866 for (ServiceRecord r1 : mServices.values()) {
9867 if (componentNameString == null
9868 || r1.name.flattenToString().contains(componentNameString)) {
9869 dumpService(fd, pw, r1, newArgs);
9870 }
9871 }
9872 }
9873 }
9874
9875 /**
9876 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9877 * there is a thread associated with the service.
9878 */
9879 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9880 pw.println(" Service " + r.name.flattenToString());
9881 if (r.app != null && r.app.thread != null) {
9882 try {
9883 // flush anything that is already in the PrintWriter since the thread is going
9884 // to write to the file descriptor directly
9885 pw.flush();
9886 r.app.thread.dumpService(fd, r, args);
9887 pw.print("\n");
9888 } catch (RemoteException e) {
9889 pw.println("got a RemoteException while dumping the service");
9890 }
9891 }
9892 }
9893
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009894 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9895 int opti, boolean dumpAll) {
9896 boolean needSep = false;
9897
9898 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009899 if (mRegisteredReceivers.size() > 0) {
9900 pw.println(" ");
9901 pw.println(" Registered Receivers:");
9902 Iterator it = mRegisteredReceivers.values().iterator();
9903 while (it.hasNext()) {
9904 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009905 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009906 r.dump(pw, " ");
9907 }
9908 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009910 pw.println(" ");
9911 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009912 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009913 needSep = true;
9914 }
9915
9916 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9917 || mPendingBroadcast != null) {
9918 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009919 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009920 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009921 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009922 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9923 pw.println(" Broadcast #" + i + ":");
9924 mParallelBroadcasts.get(i).dump(pw, " ");
9925 }
9926 if (mOrderedBroadcasts.size() > 0) {
9927 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07009928 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009929 }
9930 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9931 pw.println(" Serialized Broadcast #" + i + ":");
9932 mOrderedBroadcasts.get(i).dump(pw, " ");
9933 }
9934 pw.println(" ");
9935 pw.println(" Pending broadcast:");
9936 if (mPendingBroadcast != null) {
9937 mPendingBroadcast.dump(pw, " ");
9938 } else {
9939 pw.println(" (null)");
9940 }
9941 needSep = true;
9942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009944 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009945 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009946 pw.println(" Historical broadcasts:");
9947 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9948 BroadcastRecord r = mBroadcastHistory[i];
9949 if (r == null) {
9950 break;
9951 }
9952 pw.println(" Historical Broadcast #" + i + ":");
9953 r.dump(pw, " ");
9954 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009955 needSep = true;
9956 }
9957
9958 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009959 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009960 pw.println(" Sticky broadcasts:");
9961 StringBuilder sb = new StringBuilder(128);
9962 for (Map.Entry<String, ArrayList<Intent>> ent
9963 : mStickyBroadcasts.entrySet()) {
9964 pw.print(" * Sticky action "); pw.print(ent.getKey());
9965 pw.println(":");
9966 ArrayList<Intent> intents = ent.getValue();
9967 final int N = intents.size();
9968 for (int i=0; i<N; i++) {
9969 sb.setLength(0);
9970 sb.append(" Intent: ");
9971 intents.get(i).toShortString(sb, true, false);
9972 pw.println(sb.toString());
9973 Bundle bundle = intents.get(i).getExtras();
9974 if (bundle != null) {
9975 pw.print(" ");
9976 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009977 }
9978 }
9979 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009980 needSep = true;
9981 }
9982
9983 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009984 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009985 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009986 pw.println(" mHandler:");
9987 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009988 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009989 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009990
9991 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992 }
9993
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009994 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9995 int opti, boolean dumpAll) {
9996 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009997
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009998 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009999 if (mServices.size() > 0) {
10000 pw.println(" Active services:");
10001 Iterator<ServiceRecord> it = mServices.values().iterator();
10002 while (it.hasNext()) {
10003 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010004 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010005 r.dump(pw, " ");
10006 }
10007 needSep = true;
10008 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010010
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010011 if (mPendingServices.size() > 0) {
10012 if (needSep) pw.println(" ");
10013 pw.println(" Pending services:");
10014 for (int i=0; i<mPendingServices.size(); i++) {
10015 ServiceRecord r = mPendingServices.get(i);
10016 pw.print(" * Pending "); pw.println(r);
10017 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010018 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010019 needSep = true;
10020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010021
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010022 if (mRestartingServices.size() > 0) {
10023 if (needSep) pw.println(" ");
10024 pw.println(" Restarting services:");
10025 for (int i=0; i<mRestartingServices.size(); i++) {
10026 ServiceRecord r = mRestartingServices.get(i);
10027 pw.print(" * Restarting "); pw.println(r);
10028 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010029 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010030 needSep = true;
10031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010033 if (mStoppingServices.size() > 0) {
10034 if (needSep) pw.println(" ");
10035 pw.println(" Stopping services:");
10036 for (int i=0; i<mStoppingServices.size(); i++) {
10037 ServiceRecord r = mStoppingServices.get(i);
10038 pw.print(" * Stopping "); pw.println(r);
10039 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010040 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010041 needSep = true;
10042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010043
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010044 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010045 if (mServiceConnections.size() > 0) {
10046 if (needSep) pw.println(" ");
10047 pw.println(" Connection bindings to services:");
10048 Iterator<ConnectionRecord> it
10049 = mServiceConnections.values().iterator();
10050 while (it.hasNext()) {
10051 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010052 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053 r.dump(pw, " ");
10054 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010055 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010056 }
10057 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010058
10059 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010060 }
10061
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010062 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10063 int opti, boolean dumpAll) {
10064 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010065
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010066 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010067 if (mProvidersByClass.size() > 0) {
10068 if (needSep) pw.println(" ");
10069 pw.println(" Published content providers (by class):");
10070 Iterator it = mProvidersByClass.entrySet().iterator();
10071 while (it.hasNext()) {
10072 Map.Entry e = (Map.Entry)it.next();
10073 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010074 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075 r.dump(pw, " ");
10076 }
10077 needSep = true;
10078 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010079
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010080 if (mProvidersByName.size() > 0) {
10081 pw.println(" ");
10082 pw.println(" Authority to provider mappings:");
10083 Iterator it = mProvidersByName.entrySet().iterator();
10084 while (it.hasNext()) {
10085 Map.Entry e = (Map.Entry)it.next();
10086 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
10087 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10088 pw.println(r);
10089 }
10090 needSep = true;
10091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010092 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010093
10094 if (mLaunchingProviders.size() > 0) {
10095 if (needSep) pw.println(" ");
10096 pw.println(" Launching content providers:");
10097 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10098 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10099 pw.println(mLaunchingProviders.get(i));
10100 }
10101 needSep = true;
10102 }
10103
10104 if (mGrantedUriPermissions.size() > 0) {
10105 pw.println();
10106 pw.println("Granted Uri Permissions:");
10107 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10108 int uid = mGrantedUriPermissions.keyAt(i);
10109 HashMap<Uri, UriPermission> perms
10110 = mGrantedUriPermissions.valueAt(i);
10111 pw.print(" * UID "); pw.print(uid);
10112 pw.println(" holds:");
10113 for (UriPermission perm : perms.values()) {
10114 pw.print(" "); pw.println(perm);
10115 perm.dump(pw, " ");
10116 }
10117 }
10118 needSep = true;
10119 }
10120
10121 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010122 }
10123
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010124 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10125 int opti, boolean dumpAll) {
10126 boolean needSep = false;
10127
10128 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010129 if (this.mIntentSenderRecords.size() > 0) {
10130 Iterator<WeakReference<PendingIntentRecord>> it
10131 = mIntentSenderRecords.values().iterator();
10132 while (it.hasNext()) {
10133 WeakReference<PendingIntentRecord> ref = it.next();
10134 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010135 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010136 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010137 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010138 rec.dump(pw, " ");
10139 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010140 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010141 }
10142 }
10143 }
10144 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010145
10146 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010147 }
10148
10149 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010150 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010151 TaskRecord lastTask = null;
10152 for (int i=list.size()-1; i>=0; i--) {
10153 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010154 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155 if (lastTask != r.task) {
10156 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010157 pw.print(prefix);
10158 pw.print(full ? "* " : " ");
10159 pw.println(lastTask);
10160 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010161 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010163 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010164 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10165 pw.print(" #"); pw.print(i); pw.print(": ");
10166 pw.println(r);
10167 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010168 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010170 }
10171 }
10172
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010173 private static String buildOomTag(String prefix, String space, int val, int base) {
10174 if (val == base) {
10175 if (space == null) return prefix;
10176 return prefix + " ";
10177 }
10178 return prefix + "+" + Integer.toString(val-base);
10179 }
10180
10181 private static final int dumpProcessList(PrintWriter pw,
10182 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010183 String prefix, String normalLabel, String persistentLabel,
10184 boolean inclOomAdj) {
10185 int numPers = 0;
10186 for (int i=list.size()-1; i>=0; i--) {
10187 ProcessRecord r = (ProcessRecord)list.get(i);
10188 if (false) {
10189 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10190 + " #" + i + ":");
10191 r.dump(pw, prefix + " ");
10192 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010193 String oomAdj;
10194 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010195 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010196 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010197 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10198 } else if (r.setAdj >= HOME_APP_ADJ) {
10199 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10200 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10201 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10202 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10203 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10204 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10205 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10206 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10207 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010208 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010209 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010210 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010211 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010212 } else {
10213 oomAdj = Integer.toString(r.setAdj);
10214 }
10215 String schedGroup;
10216 switch (r.setSchedGroup) {
10217 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10218 schedGroup = "B";
10219 break;
10220 case Process.THREAD_GROUP_DEFAULT:
10221 schedGroup = "F";
10222 break;
10223 default:
10224 schedGroup = Integer.toString(r.setSchedGroup);
10225 break;
10226 }
10227 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010228 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010229 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010230 if (r.adjSource != null || r.adjTarget != null) {
10231 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010232 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 } else {
10235 pw.println(String.format("%s%s #%2d: %s",
10236 prefix, (r.persistent ? persistentLabel : normalLabel),
10237 i, r.toString()));
10238 }
10239 if (r.persistent) {
10240 numPers++;
10241 }
10242 }
10243 return numPers;
10244 }
10245
Dianne Hackborn472ad872010-04-07 17:31:48 -070010246 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010247 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010248 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 long uptime = SystemClock.uptimeMillis();
10250 long realtime = SystemClock.elapsedRealtime();
10251
10252 if (isCheckinRequest) {
10253 // short checkin version
10254 pw.println(uptime + "," + realtime);
10255 pw.flush();
10256 } else {
10257 pw.println("Applications Memory Usage (kB):");
10258 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10259 }
10260 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10261 ProcessRecord r = (ProcessRecord)list.get(i);
10262 if (r.thread != null) {
10263 if (!isCheckinRequest) {
10264 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10265 pw.flush();
10266 }
10267 try {
10268 r.thread.asBinder().dump(fd, args);
10269 } catch (RemoteException e) {
10270 if (!isCheckinRequest) {
10271 pw.println("Got RemoteException!");
10272 pw.flush();
10273 }
10274 }
10275 }
10276 }
10277 }
10278
10279 /**
10280 * Searches array of arguments for the specified string
10281 * @param args array of argument strings
10282 * @param value value to search for
10283 * @return true if the value is contained in the array
10284 */
10285 private static boolean scanArgs(String[] args, String value) {
10286 if (args != null) {
10287 for (String arg : args) {
10288 if (value.equals(arg)) {
10289 return true;
10290 }
10291 }
10292 }
10293 return false;
10294 }
10295
Dianne Hackborn75b03852009-06-12 15:43:26 -070010296 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010297 int count = mHistory.size();
10298
10299 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010300 int index = -1;
10301 for (int i=count-1; i>=0; i--) {
10302 Object o = mHistory.get(i);
10303 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010304 index = i;
10305 break;
10306 }
10307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010308
10309 return index;
10310 }
10311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010312 private final void killServicesLocked(ProcessRecord app,
10313 boolean allowRestart) {
10314 // Report disconnected services.
10315 if (false) {
10316 // XXX we are letting the client link to the service for
10317 // death notifications.
10318 if (app.services.size() > 0) {
10319 Iterator it = app.services.iterator();
10320 while (it.hasNext()) {
10321 ServiceRecord r = (ServiceRecord)it.next();
10322 if (r.connections.size() > 0) {
10323 Iterator<ConnectionRecord> jt
10324 = r.connections.values().iterator();
10325 while (jt.hasNext()) {
10326 ConnectionRecord c = jt.next();
10327 if (c.binding.client != app) {
10328 try {
10329 //c.conn.connected(r.className, null);
10330 } catch (Exception e) {
10331 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010332 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010333 + r.shortName
10334 + " from app " + app.processName, e);
10335 }
10336 }
10337 }
10338 }
10339 }
10340 }
10341 }
10342
10343 // Clean up any connections this application has to other services.
10344 if (app.connections.size() > 0) {
10345 Iterator<ConnectionRecord> it = app.connections.iterator();
10346 while (it.hasNext()) {
10347 ConnectionRecord r = it.next();
10348 removeConnectionLocked(r, app, null);
10349 }
10350 }
10351 app.connections.clear();
10352
10353 if (app.services.size() != 0) {
10354 // Any services running in the application need to be placed
10355 // back in the pending list.
10356 Iterator it = app.services.iterator();
10357 while (it.hasNext()) {
10358 ServiceRecord sr = (ServiceRecord)it.next();
10359 synchronized (sr.stats.getBatteryStats()) {
10360 sr.stats.stopLaunchedLocked();
10361 }
10362 sr.app = null;
10363 sr.executeNesting = 0;
10364 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010365
10366 boolean hasClients = sr.bindings.size() > 0;
10367 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010368 Iterator<IntentBindRecord> bindings
10369 = sr.bindings.values().iterator();
10370 while (bindings.hasNext()) {
10371 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010372 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 + ": shouldUnbind=" + b.hasBound);
10374 b.binder = null;
10375 b.requested = b.received = b.hasBound = false;
10376 }
10377 }
10378
10379 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010380 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010381 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010382 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 sr.crashCount, sr.shortName, app.pid);
10384 bringDownServiceLocked(sr, true);
10385 } else if (!allowRestart) {
10386 bringDownServiceLocked(sr, true);
10387 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010388 boolean canceled = scheduleServiceRestartLocked(sr, true);
10389
10390 // Should the service remain running? Note that in the
10391 // extreme case of so many attempts to deliver a command
10392 // that it failed, that we also will stop it here.
10393 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10394 if (sr.pendingStarts.size() == 0) {
10395 sr.startRequested = false;
10396 if (!hasClients) {
10397 // Whoops, no reason to restart!
10398 bringDownServiceLocked(sr, true);
10399 }
10400 }
10401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 }
10403 }
10404
10405 if (!allowRestart) {
10406 app.services.clear();
10407 }
10408 }
10409
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010410 // Make sure we have no more records on the stopping list.
10411 int i = mStoppingServices.size();
10412 while (i > 0) {
10413 i--;
10414 ServiceRecord sr = mStoppingServices.get(i);
10415 if (sr.app == app) {
10416 mStoppingServices.remove(i);
10417 }
10418 }
10419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010420 app.executingServices.clear();
10421 }
10422
10423 private final void removeDyingProviderLocked(ProcessRecord proc,
10424 ContentProviderRecord cpr) {
10425 synchronized (cpr) {
10426 cpr.launchingApp = null;
10427 cpr.notifyAll();
10428 }
10429
10430 mProvidersByClass.remove(cpr.info.name);
10431 String names[] = cpr.info.authority.split(";");
10432 for (int j = 0; j < names.length; j++) {
10433 mProvidersByName.remove(names[j]);
10434 }
10435
10436 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10437 while (cit.hasNext()) {
10438 ProcessRecord capp = cit.next();
10439 if (!capp.persistent && capp.thread != null
10440 && capp.pid != 0
10441 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010442 Slog.i(TAG, "Kill " + capp.processName
10443 + " (pid " + capp.pid + "): provider " + cpr.info.name
10444 + " in dying process " + proc.processName);
10445 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10446 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010447 Process.killProcess(capp.pid);
10448 }
10449 }
10450
10451 mLaunchingProviders.remove(cpr);
10452 }
10453
10454 /**
10455 * Main code for cleaning up a process when it has gone away. This is
10456 * called both as a result of the process dying, or directly when stopping
10457 * a process when running in single process mode.
10458 */
10459 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10460 boolean restarting, int index) {
10461 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010462 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010463 }
10464
Dianne Hackborn36124872009-10-08 16:22:03 -070010465 mProcessesToGc.remove(app);
10466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010467 // Dismiss any open dialogs.
10468 if (app.crashDialog != null) {
10469 app.crashDialog.dismiss();
10470 app.crashDialog = null;
10471 }
10472 if (app.anrDialog != null) {
10473 app.anrDialog.dismiss();
10474 app.anrDialog = null;
10475 }
10476 if (app.waitDialog != null) {
10477 app.waitDialog.dismiss();
10478 app.waitDialog = null;
10479 }
10480
10481 app.crashing = false;
10482 app.notResponding = false;
10483
10484 app.resetPackageList();
10485 app.thread = null;
10486 app.forcingToForeground = null;
10487 app.foregroundServices = false;
10488
10489 killServicesLocked(app, true);
10490
10491 boolean restart = false;
10492
10493 int NL = mLaunchingProviders.size();
10494
10495 // Remove published content providers.
10496 if (!app.pubProviders.isEmpty()) {
10497 Iterator it = app.pubProviders.values().iterator();
10498 while (it.hasNext()) {
10499 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10500 cpr.provider = null;
10501 cpr.app = null;
10502
10503 // See if someone is waiting for this provider... in which
10504 // case we don't remove it, but just let it restart.
10505 int i = 0;
10506 if (!app.bad) {
10507 for (; i<NL; i++) {
10508 if (mLaunchingProviders.get(i) == cpr) {
10509 restart = true;
10510 break;
10511 }
10512 }
10513 } else {
10514 i = NL;
10515 }
10516
10517 if (i >= NL) {
10518 removeDyingProviderLocked(app, cpr);
10519 NL = mLaunchingProviders.size();
10520 }
10521 }
10522 app.pubProviders.clear();
10523 }
10524
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010525 // Take care of any launching providers waiting for this process.
10526 if (checkAppInLaunchingProvidersLocked(app, false)) {
10527 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010530 // Unregister from connected content providers.
10531 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010532 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010533 while (it.hasNext()) {
10534 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10535 cpr.clients.remove(app);
10536 }
10537 app.conProviders.clear();
10538 }
10539
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010540 // At this point there may be remaining entries in mLaunchingProviders
10541 // where we were the only one waiting, so they are no longer of use.
10542 // Look for these and clean up if found.
10543 // XXX Commented out for now. Trying to figure out a way to reproduce
10544 // the actual situation to identify what is actually going on.
10545 if (false) {
10546 for (int i=0; i<NL; i++) {
10547 ContentProviderRecord cpr = (ContentProviderRecord)
10548 mLaunchingProviders.get(i);
10549 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10550 synchronized (cpr) {
10551 cpr.launchingApp = null;
10552 cpr.notifyAll();
10553 }
10554 }
10555 }
10556 }
10557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010558 skipCurrentReceiverLocked(app);
10559
10560 // Unregister any receivers.
10561 if (app.receivers.size() > 0) {
10562 Iterator<ReceiverList> it = app.receivers.iterator();
10563 while (it.hasNext()) {
10564 removeReceiverLocked(it.next());
10565 }
10566 app.receivers.clear();
10567 }
10568
Christopher Tate181fafa2009-05-14 11:12:14 -070010569 // If the app is undergoing backup, tell the backup manager about it
10570 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010571 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010572 try {
10573 IBackupManager bm = IBackupManager.Stub.asInterface(
10574 ServiceManager.getService(Context.BACKUP_SERVICE));
10575 bm.agentDisconnected(app.info.packageName);
10576 } catch (RemoteException e) {
10577 // can't happen; backup manager is local
10578 }
10579 }
10580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 // If the caller is restarting this app, then leave it in its
10582 // current lists and let the caller take care of it.
10583 if (restarting) {
10584 return;
10585 }
10586
10587 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010588 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010589 "Removing non-persistent process during cleanup: " + app);
10590 mProcessNames.remove(app.processName, app.info.uid);
10591 } else if (!app.removed) {
10592 // This app is persistent, so we need to keep its record around.
10593 // If it is not already on the pending app list, add it there
10594 // and start a new process for it.
10595 app.thread = null;
10596 app.forcingToForeground = null;
10597 app.foregroundServices = false;
10598 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10599 mPersistentStartingProcesses.add(app);
10600 restart = true;
10601 }
10602 }
10603 mProcessesOnHold.remove(app);
10604
The Android Open Source Project4df24232009-03-05 14:34:35 -080010605 if (app == mHomeProcess) {
10606 mHomeProcess = null;
10607 }
10608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010609 if (restart) {
10610 // We have components that still need to be running in the
10611 // process, so re-launch it.
10612 mProcessNames.put(app.processName, app.info.uid, app);
10613 startProcessLocked(app, "restart", app.processName);
10614 } else if (app.pid > 0 && app.pid != MY_PID) {
10615 // Goodbye!
10616 synchronized (mPidsSelfLocked) {
10617 mPidsSelfLocked.remove(app.pid);
10618 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10619 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010620 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010621 }
10622 }
10623
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010624 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10625 // Look through the content providers we are waiting to have launched,
10626 // and if any run in this process then either schedule a restart of
10627 // the process or kill the client waiting for it if this process has
10628 // gone bad.
10629 int NL = mLaunchingProviders.size();
10630 boolean restart = false;
10631 for (int i=0; i<NL; i++) {
10632 ContentProviderRecord cpr = (ContentProviderRecord)
10633 mLaunchingProviders.get(i);
10634 if (cpr.launchingApp == app) {
10635 if (!alwaysBad && !app.bad) {
10636 restart = true;
10637 } else {
10638 removeDyingProviderLocked(app, cpr);
10639 NL = mLaunchingProviders.size();
10640 }
10641 }
10642 }
10643 return restart;
10644 }
10645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010646 // =========================================================
10647 // SERVICES
10648 // =========================================================
10649
10650 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10651 ActivityManager.RunningServiceInfo info =
10652 new ActivityManager.RunningServiceInfo();
10653 info.service = r.name;
10654 if (r.app != null) {
10655 info.pid = r.app.pid;
10656 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010657 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010658 info.process = r.processName;
10659 info.foreground = r.isForeground;
10660 info.activeSince = r.createTime;
10661 info.started = r.startRequested;
10662 info.clientCount = r.connections.size();
10663 info.crashCount = r.crashCount;
10664 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010665 if (r.isForeground) {
10666 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10667 }
10668 if (r.startRequested) {
10669 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10670 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010671 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010672 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10673 }
10674 if (r.app != null && r.app.persistent) {
10675 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10676 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010677 for (ConnectionRecord conn : r.connections.values()) {
10678 if (conn.clientLabel != 0) {
10679 info.clientPackage = conn.binding.client.info.packageName;
10680 info.clientLabel = conn.clientLabel;
10681 break;
10682 }
10683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010684 return info;
10685 }
10686
10687 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10688 int flags) {
10689 synchronized (this) {
10690 ArrayList<ActivityManager.RunningServiceInfo> res
10691 = new ArrayList<ActivityManager.RunningServiceInfo>();
10692
10693 if (mServices.size() > 0) {
10694 Iterator<ServiceRecord> it = mServices.values().iterator();
10695 while (it.hasNext() && res.size() < maxNum) {
10696 res.add(makeRunningServiceInfoLocked(it.next()));
10697 }
10698 }
10699
10700 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10701 ServiceRecord r = mRestartingServices.get(i);
10702 ActivityManager.RunningServiceInfo info =
10703 makeRunningServiceInfoLocked(r);
10704 info.restarting = r.nextRestartTime;
10705 res.add(info);
10706 }
10707
10708 return res;
10709 }
10710 }
10711
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010712 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10713 synchronized (this) {
10714 ServiceRecord r = mServices.get(name);
10715 if (r != null) {
10716 for (ConnectionRecord conn : r.connections.values()) {
10717 if (conn.clientIntent != null) {
10718 return conn.clientIntent;
10719 }
10720 }
10721 }
10722 }
10723 return null;
10724 }
10725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010726 private final ServiceRecord findServiceLocked(ComponentName name,
10727 IBinder token) {
10728 ServiceRecord r = mServices.get(name);
10729 return r == token ? r : null;
10730 }
10731
10732 private final class ServiceLookupResult {
10733 final ServiceRecord record;
10734 final String permission;
10735
10736 ServiceLookupResult(ServiceRecord _record, String _permission) {
10737 record = _record;
10738 permission = _permission;
10739 }
10740 };
10741
10742 private ServiceLookupResult findServiceLocked(Intent service,
10743 String resolvedType) {
10744 ServiceRecord r = null;
10745 if (service.getComponent() != null) {
10746 r = mServices.get(service.getComponent());
10747 }
10748 if (r == null) {
10749 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10750 r = mServicesByIntent.get(filter);
10751 }
10752
10753 if (r == null) {
10754 try {
10755 ResolveInfo rInfo =
10756 ActivityThread.getPackageManager().resolveService(
10757 service, resolvedType, 0);
10758 ServiceInfo sInfo =
10759 rInfo != null ? rInfo.serviceInfo : null;
10760 if (sInfo == null) {
10761 return null;
10762 }
10763
10764 ComponentName name = new ComponentName(
10765 sInfo.applicationInfo.packageName, sInfo.name);
10766 r = mServices.get(name);
10767 } catch (RemoteException ex) {
10768 // pm is in same process, this will never happen.
10769 }
10770 }
10771 if (r != null) {
10772 int callingPid = Binder.getCallingPid();
10773 int callingUid = Binder.getCallingUid();
10774 if (checkComponentPermission(r.permission,
10775 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10776 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010777 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778 + " from pid=" + callingPid
10779 + ", uid=" + callingUid
10780 + " requires " + r.permission);
10781 return new ServiceLookupResult(null, r.permission);
10782 }
10783 return new ServiceLookupResult(r, null);
10784 }
10785 return null;
10786 }
10787
10788 private class ServiceRestarter implements Runnable {
10789 private ServiceRecord mService;
10790
10791 void setService(ServiceRecord service) {
10792 mService = service;
10793 }
10794
10795 public void run() {
10796 synchronized(ActivityManagerService.this) {
10797 performServiceRestartLocked(mService);
10798 }
10799 }
10800 }
10801
10802 private ServiceLookupResult retrieveServiceLocked(Intent service,
10803 String resolvedType, int callingPid, int callingUid) {
10804 ServiceRecord r = null;
10805 if (service.getComponent() != null) {
10806 r = mServices.get(service.getComponent());
10807 }
10808 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10809 r = mServicesByIntent.get(filter);
10810 if (r == null) {
10811 try {
10812 ResolveInfo rInfo =
10813 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010814 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010815 ServiceInfo sInfo =
10816 rInfo != null ? rInfo.serviceInfo : null;
10817 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010818 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010819 ": not found");
10820 return null;
10821 }
10822
10823 ComponentName name = new ComponentName(
10824 sInfo.applicationInfo.packageName, sInfo.name);
10825 r = mServices.get(name);
10826 if (r == null) {
10827 filter = new Intent.FilterComparison(service.cloneFilter());
10828 ServiceRestarter res = new ServiceRestarter();
10829 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10830 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10831 synchronized (stats) {
10832 ss = stats.getServiceStatsLocked(
10833 sInfo.applicationInfo.uid, sInfo.packageName,
10834 sInfo.name);
10835 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010836 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010837 res.setService(r);
10838 mServices.put(name, r);
10839 mServicesByIntent.put(filter, r);
10840
10841 // Make sure this component isn't in the pending list.
10842 int N = mPendingServices.size();
10843 for (int i=0; i<N; i++) {
10844 ServiceRecord pr = mPendingServices.get(i);
10845 if (pr.name.equals(name)) {
10846 mPendingServices.remove(i);
10847 i--;
10848 N--;
10849 }
10850 }
10851 }
10852 } catch (RemoteException ex) {
10853 // pm is in same process, this will never happen.
10854 }
10855 }
10856 if (r != null) {
10857 if (checkComponentPermission(r.permission,
10858 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10859 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010860 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010861 + " from pid=" + Binder.getCallingPid()
10862 + ", uid=" + Binder.getCallingUid()
10863 + " requires " + r.permission);
10864 return new ServiceLookupResult(null, r.permission);
10865 }
10866 return new ServiceLookupResult(r, null);
10867 }
10868 return null;
10869 }
10870
10871 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10872 long now = SystemClock.uptimeMillis();
10873 if (r.executeNesting == 0 && r.app != null) {
10874 if (r.app.executingServices.size() == 0) {
10875 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10876 msg.obj = r.app;
10877 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10878 }
10879 r.app.executingServices.add(r);
10880 }
10881 r.executeNesting++;
10882 r.executingStart = now;
10883 }
10884
10885 private final void sendServiceArgsLocked(ServiceRecord r,
10886 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010887 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010888 if (N == 0) {
10889 return;
10890 }
10891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010892 int i = 0;
10893 while (i < N) {
10894 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010895 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010896 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010897 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010898 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010899 // If somehow we got a dummy start at the front, then
10900 // just drop it here.
10901 i++;
10902 continue;
10903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010904 bumpServiceExecutingLocked(r);
10905 if (!oomAdjusted) {
10906 oomAdjusted = true;
10907 updateOomAdjLocked(r.app);
10908 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010909 int flags = 0;
10910 if (si.deliveryCount > 0) {
10911 flags |= Service.START_FLAG_RETRY;
10912 }
10913 if (si.doneExecutingCount > 0) {
10914 flags |= Service.START_FLAG_REDELIVERY;
10915 }
10916 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10917 si.deliveredTime = SystemClock.uptimeMillis();
10918 r.deliveredStarts.add(si);
10919 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010920 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010921 } catch (RemoteException e) {
10922 // Remote process gone... we'll let the normal cleanup take
10923 // care of this.
10924 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010925 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010926 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927 break;
10928 }
10929 }
10930 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010931 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010932 } else {
10933 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010934 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010935 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936 }
10937 }
10938 }
10939
10940 private final boolean requestServiceBindingLocked(ServiceRecord r,
10941 IntentBindRecord i, boolean rebind) {
10942 if (r.app == null || r.app.thread == null) {
10943 // If service is not currently running, can't yet bind.
10944 return false;
10945 }
10946 if ((!i.requested || rebind) && i.apps.size() > 0) {
10947 try {
10948 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010949 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010950 + ": shouldUnbind=" + i.hasBound);
10951 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10952 if (!rebind) {
10953 i.requested = true;
10954 }
10955 i.hasBound = true;
10956 i.doRebind = false;
10957 } catch (RemoteException e) {
10958 return false;
10959 }
10960 }
10961 return true;
10962 }
10963
10964 private final void requestServiceBindingsLocked(ServiceRecord r) {
10965 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10966 while (bindings.hasNext()) {
10967 IntentBindRecord i = bindings.next();
10968 if (!requestServiceBindingLocked(r, i, false)) {
10969 break;
10970 }
10971 }
10972 }
10973
10974 private final void realStartServiceLocked(ServiceRecord r,
10975 ProcessRecord app) throws RemoteException {
10976 if (app.thread == null) {
10977 throw new RemoteException();
10978 }
10979
10980 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010981 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010982
10983 app.services.add(r);
10984 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010985 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010986
10987 boolean created = false;
10988 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010989 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010990 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010991 mStringBuilder.setLength(0);
10992 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010993 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010994 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010995 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 synchronized (r.stats.getBatteryStats()) {
10997 r.stats.startLaunchedLocked();
10998 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010999 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011000 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011001 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011002 created = true;
11003 } finally {
11004 if (!created) {
11005 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011006 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007 }
11008 }
11009
11010 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011011
11012 // If the service is in the started state, and there are no
11013 // pending arguments, then fake up one so its onStartCommand() will
11014 // be called.
11015 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11016 r.lastStartId++;
11017 if (r.lastStartId < 1) {
11018 r.lastStartId = 1;
11019 }
11020 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11021 }
11022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 sendServiceArgsLocked(r, true);
11024 }
11025
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011026 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11027 boolean allowCancel) {
11028 boolean canceled = false;
11029
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011030 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011031 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011032 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011033
11034 // Any delivered but not yet finished starts should be put back
11035 // on the pending list.
11036 final int N = r.deliveredStarts.size();
11037 if (N > 0) {
11038 for (int i=N-1; i>=0; i--) {
11039 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11040 if (si.intent == null) {
11041 // We'll generate this again if needed.
11042 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11043 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11044 r.pendingStarts.add(0, si);
11045 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11046 dur *= 2;
11047 if (minDuration < dur) minDuration = dur;
11048 if (resetTime < dur) resetTime = dur;
11049 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011050 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011051 + r.name);
11052 canceled = true;
11053 }
11054 }
11055 r.deliveredStarts.clear();
11056 }
11057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011058 r.totalRestartCount++;
11059 if (r.restartDelay == 0) {
11060 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011061 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 } else {
11063 // If it has been a "reasonably long time" since the service
11064 // was started, then reset our restart duration back to
11065 // the beginning, so we don't infinitely increase the duration
11066 // on a service that just occasionally gets killed (which is
11067 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011068 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011069 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011070 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011071 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011072 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011073 if (r.restartDelay < minDuration) {
11074 r.restartDelay = minDuration;
11075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011076 }
11077 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011078
11079 r.nextRestartTime = now + r.restartDelay;
11080
11081 // Make sure that we don't end up restarting a bunch of services
11082 // all at the same time.
11083 boolean repeat;
11084 do {
11085 repeat = false;
11086 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11087 ServiceRecord r2 = mRestartingServices.get(i);
11088 if (r2 != r && r.nextRestartTime
11089 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11090 && r.nextRestartTime
11091 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11092 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11093 r.restartDelay = r.nextRestartTime - now;
11094 repeat = true;
11095 break;
11096 }
11097 }
11098 } while (repeat);
11099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011100 if (!mRestartingServices.contains(r)) {
11101 mRestartingServices.add(r);
11102 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011103
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011104 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011107 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011108 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011109 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011111 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011112 r.shortName, r.restartDelay);
11113
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011114 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011115 }
11116
11117 final void performServiceRestartLocked(ServiceRecord r) {
11118 if (!mRestartingServices.contains(r)) {
11119 return;
11120 }
11121 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11122 }
11123
11124 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11125 if (r.restartDelay == 0) {
11126 return false;
11127 }
11128 r.resetRestartCounter();
11129 mRestartingServices.remove(r);
11130 mHandler.removeCallbacks(r.restarter);
11131 return true;
11132 }
11133
11134 private final boolean bringUpServiceLocked(ServiceRecord r,
11135 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011136 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011137 //r.dump(" ");
11138
Dianne Hackborn36124872009-10-08 16:22:03 -070011139 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 sendServiceArgsLocked(r, false);
11141 return true;
11142 }
11143
11144 if (!whileRestarting && r.restartDelay > 0) {
11145 // If waiting for a restart, then do nothing.
11146 return true;
11147 }
11148
Joe Onorato8a9b2202010-02-26 18:56:32 -080011149 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011150 + " " + r.intent);
11151
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011152 // We are now bringing the service up, so no longer in the
11153 // restarting state.
11154 mRestartingServices.remove(r);
11155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 final String appName = r.processName;
11157 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11158 if (app != null && app.thread != null) {
11159 try {
11160 realStartServiceLocked(r, app);
11161 return true;
11162 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011163 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 }
11165
11166 // If a dead object exception was thrown -- fall through to
11167 // restart the application.
11168 }
11169
Dianne Hackborn36124872009-10-08 16:22:03 -070011170 // Not running -- get it started, and enqueue this service record
11171 // to be executed when the app comes up.
11172 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11173 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011174 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011175 + r.appInfo.packageName + "/"
11176 + r.appInfo.uid + " for service "
11177 + r.intent.getIntent() + ": process is bad");
11178 bringDownServiceLocked(r, true);
11179 return false;
11180 }
11181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011182 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011183 mPendingServices.add(r);
11184 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186 return true;
11187 }
11188
11189 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011190 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011191 //r.dump(" ");
11192
11193 // Does it still need to run?
11194 if (!force && r.startRequested) {
11195 return;
11196 }
11197 if (r.connections.size() > 0) {
11198 if (!force) {
11199 // XXX should probably keep a count of the number of auto-create
11200 // connections directly in the service.
11201 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11202 while (it.hasNext()) {
11203 ConnectionRecord cr = it.next();
11204 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11205 return;
11206 }
11207 }
11208 }
11209
11210 // Report to all of the connections that the service is no longer
11211 // available.
11212 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11213 while (it.hasNext()) {
11214 ConnectionRecord c = it.next();
11215 try {
11216 // todo: shouldn't be a synchronous call!
11217 c.conn.connected(r.name, null);
11218 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011219 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 " to connection " + c.conn.asBinder() +
11221 " (in " + c.binding.client.processName + ")", e);
11222 }
11223 }
11224 }
11225
11226 // Tell the service that it has been unbound.
11227 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11228 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11229 while (it.hasNext()) {
11230 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011231 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011232 + ": hasBound=" + ibr.hasBound);
11233 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11234 try {
11235 bumpServiceExecutingLocked(r);
11236 updateOomAdjLocked(r.app);
11237 ibr.hasBound = false;
11238 r.app.thread.scheduleUnbindService(r,
11239 ibr.intent.getIntent());
11240 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011241 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011242 + r.shortName, e);
11243 serviceDoneExecutingLocked(r, true);
11244 }
11245 }
11246 }
11247 }
11248
Joe Onorato8a9b2202010-02-26 18:56:32 -080011249 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011250 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011251 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011252 System.identityHashCode(r), r.shortName,
11253 (r.app != null) ? r.app.pid : -1);
11254
11255 mServices.remove(r.name);
11256 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011257 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 r.totalRestartCount = 0;
11259 unscheduleServiceRestartLocked(r);
11260
11261 // Also make sure it is not on the pending list.
11262 int N = mPendingServices.size();
11263 for (int i=0; i<N; i++) {
11264 if (mPendingServices.get(i) == r) {
11265 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011266 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 TAG, "Removed pending service: " + r.shortName);
11268 i--;
11269 N--;
11270 }
11271 }
11272
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011273 r.cancelNotification();
11274 r.isForeground = false;
11275 r.foregroundId = 0;
11276 r.foregroundNoti = null;
11277
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011278 // Clear start entries.
11279 r.deliveredStarts.clear();
11280 r.pendingStarts.clear();
11281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 if (r.app != null) {
11283 synchronized (r.stats.getBatteryStats()) {
11284 r.stats.stopLaunchedLocked();
11285 }
11286 r.app.services.remove(r);
11287 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011288 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011289 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011290 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 bumpServiceExecutingLocked(r);
11292 mStoppingServices.add(r);
11293 updateOomAdjLocked(r.app);
11294 r.app.thread.scheduleStopService(r);
11295 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011296 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011297 + r.shortName, e);
11298 serviceDoneExecutingLocked(r, true);
11299 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011300 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011301 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011302 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011303 TAG, "Removed service that has no process: " + r.shortName);
11304 }
11305 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011306 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011307 TAG, "Removed service that is not running: " + r.shortName);
11308 }
11309 }
11310
11311 ComponentName startServiceLocked(IApplicationThread caller,
11312 Intent service, String resolvedType,
11313 int callingPid, int callingUid) {
11314 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011315 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011316 + " type=" + resolvedType + " args=" + service.getExtras());
11317
11318 if (caller != null) {
11319 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11320 if (callerApp == null) {
11321 throw new SecurityException(
11322 "Unable to find app for caller " + caller
11323 + " (pid=" + Binder.getCallingPid()
11324 + ") when starting service " + service);
11325 }
11326 }
11327
11328 ServiceLookupResult res =
11329 retrieveServiceLocked(service, resolvedType,
11330 callingPid, callingUid);
11331 if (res == null) {
11332 return null;
11333 }
11334 if (res.record == null) {
11335 return new ComponentName("!", res.permission != null
11336 ? res.permission : "private to package");
11337 }
11338 ServiceRecord r = res.record;
11339 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011340 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 + r.shortName);
11342 }
11343 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011344 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011345 r.lastStartId++;
11346 if (r.lastStartId < 1) {
11347 r.lastStartId = 1;
11348 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011349 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011350 r.lastActivity = SystemClock.uptimeMillis();
11351 synchronized (r.stats.getBatteryStats()) {
11352 r.stats.startRunningLocked();
11353 }
11354 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11355 return new ComponentName("!", "Service process is bad");
11356 }
11357 return r.name;
11358 }
11359 }
11360
11361 public ComponentName startService(IApplicationThread caller, Intent service,
11362 String resolvedType) {
11363 // Refuse possible leaked file descriptors
11364 if (service != null && service.hasFileDescriptors() == true) {
11365 throw new IllegalArgumentException("File descriptors passed in Intent");
11366 }
11367
11368 synchronized(this) {
11369 final int callingPid = Binder.getCallingPid();
11370 final int callingUid = Binder.getCallingUid();
11371 final long origId = Binder.clearCallingIdentity();
11372 ComponentName res = startServiceLocked(caller, service,
11373 resolvedType, callingPid, callingUid);
11374 Binder.restoreCallingIdentity(origId);
11375 return res;
11376 }
11377 }
11378
11379 ComponentName startServiceInPackage(int uid,
11380 Intent service, String resolvedType) {
11381 synchronized(this) {
11382 final long origId = Binder.clearCallingIdentity();
11383 ComponentName res = startServiceLocked(null, service,
11384 resolvedType, -1, uid);
11385 Binder.restoreCallingIdentity(origId);
11386 return res;
11387 }
11388 }
11389
11390 public int stopService(IApplicationThread caller, Intent service,
11391 String resolvedType) {
11392 // Refuse possible leaked file descriptors
11393 if (service != null && service.hasFileDescriptors() == true) {
11394 throw new IllegalArgumentException("File descriptors passed in Intent");
11395 }
11396
11397 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011398 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 + " type=" + resolvedType);
11400
11401 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11402 if (caller != null && callerApp == null) {
11403 throw new SecurityException(
11404 "Unable to find app for caller " + caller
11405 + " (pid=" + Binder.getCallingPid()
11406 + ") when stopping service " + service);
11407 }
11408
11409 // If this service is active, make sure it is stopped.
11410 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11411 if (r != null) {
11412 if (r.record != null) {
11413 synchronized (r.record.stats.getBatteryStats()) {
11414 r.record.stats.stopRunningLocked();
11415 }
11416 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011417 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 final long origId = Binder.clearCallingIdentity();
11419 bringDownServiceLocked(r.record, false);
11420 Binder.restoreCallingIdentity(origId);
11421 return 1;
11422 }
11423 return -1;
11424 }
11425 }
11426
11427 return 0;
11428 }
11429
11430 public IBinder peekService(Intent service, String resolvedType) {
11431 // Refuse possible leaked file descriptors
11432 if (service != null && service.hasFileDescriptors() == true) {
11433 throw new IllegalArgumentException("File descriptors passed in Intent");
11434 }
11435
11436 IBinder ret = null;
11437
11438 synchronized(this) {
11439 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11440
11441 if (r != null) {
11442 // r.record is null if findServiceLocked() failed the caller permission check
11443 if (r.record == null) {
11444 throw new SecurityException(
11445 "Permission Denial: Accessing service " + r.record.name
11446 + " from pid=" + Binder.getCallingPid()
11447 + ", uid=" + Binder.getCallingUid()
11448 + " requires " + r.permission);
11449 }
11450 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11451 if (ib != null) {
11452 ret = ib.binder;
11453 }
11454 }
11455 }
11456
11457 return ret;
11458 }
11459
11460 public boolean stopServiceToken(ComponentName className, IBinder token,
11461 int startId) {
11462 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011463 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011464 + " " + token + " startId=" + startId);
11465 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011466 if (r != null) {
11467 if (startId >= 0) {
11468 // Asked to only stop if done with all work. Note that
11469 // to avoid leaks, we will take this as dropping all
11470 // start items up to and including this one.
11471 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11472 if (si != null) {
11473 while (r.deliveredStarts.size() > 0) {
11474 if (r.deliveredStarts.remove(0) == si) {
11475 break;
11476 }
11477 }
11478 }
11479
11480 if (r.lastStartId != startId) {
11481 return false;
11482 }
11483
11484 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011485 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011486 + " is last, but have " + r.deliveredStarts.size()
11487 + " remaining args");
11488 }
11489 }
11490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011491 synchronized (r.stats.getBatteryStats()) {
11492 r.stats.stopRunningLocked();
11493 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011494 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011495 }
11496 final long origId = Binder.clearCallingIdentity();
11497 bringDownServiceLocked(r, false);
11498 Binder.restoreCallingIdentity(origId);
11499 return true;
11500 }
11501 }
11502 return false;
11503 }
11504
11505 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011506 int id, Notification notification, boolean removeNotification) {
11507 final long origId = Binder.clearCallingIdentity();
11508 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011509 synchronized(this) {
11510 ServiceRecord r = findServiceLocked(className, token);
11511 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011512 if (id != 0) {
11513 if (notification == null) {
11514 throw new IllegalArgumentException("null notification");
11515 }
11516 if (r.foregroundId != id) {
11517 r.cancelNotification();
11518 r.foregroundId = id;
11519 }
11520 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11521 r.foregroundNoti = notification;
11522 r.isForeground = true;
11523 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011524 if (r.app != null) {
11525 updateServiceForegroundLocked(r.app, true);
11526 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011527 } else {
11528 if (r.isForeground) {
11529 r.isForeground = false;
11530 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011531 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011532 updateServiceForegroundLocked(r.app, true);
11533 }
11534 }
11535 if (removeNotification) {
11536 r.cancelNotification();
11537 r.foregroundId = 0;
11538 r.foregroundNoti = null;
11539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011540 }
11541 }
11542 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011543 } finally {
11544 Binder.restoreCallingIdentity(origId);
11545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 }
11547
11548 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11549 boolean anyForeground = false;
11550 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11551 if (sr.isForeground) {
11552 anyForeground = true;
11553 break;
11554 }
11555 }
11556 if (anyForeground != proc.foregroundServices) {
11557 proc.foregroundServices = anyForeground;
11558 if (oomAdj) {
11559 updateOomAdjLocked();
11560 }
11561 }
11562 }
11563
11564 public int bindService(IApplicationThread caller, IBinder token,
11565 Intent service, String resolvedType,
11566 IServiceConnection connection, int flags) {
11567 // Refuse possible leaked file descriptors
11568 if (service != null && service.hasFileDescriptors() == true) {
11569 throw new IllegalArgumentException("File descriptors passed in Intent");
11570 }
11571
11572 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011573 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011574 + " type=" + resolvedType + " conn=" + connection.asBinder()
11575 + " flags=0x" + Integer.toHexString(flags));
11576 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11577 if (callerApp == null) {
11578 throw new SecurityException(
11579 "Unable to find app for caller " + caller
11580 + " (pid=" + Binder.getCallingPid()
11581 + ") when binding service " + service);
11582 }
11583
11584 HistoryRecord activity = null;
11585 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011586 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011587 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011588 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011589 return 0;
11590 }
11591 activity = (HistoryRecord)mHistory.get(aindex);
11592 }
11593
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011594 int clientLabel = 0;
11595 PendingIntent clientIntent = null;
11596
11597 if (callerApp.info.uid == Process.SYSTEM_UID) {
11598 // Hacky kind of thing -- allow system stuff to tell us
11599 // what they are, so we can report this elsewhere for
11600 // others to know why certain services are running.
11601 try {
11602 clientIntent = (PendingIntent)service.getParcelableExtra(
11603 Intent.EXTRA_CLIENT_INTENT);
11604 } catch (RuntimeException e) {
11605 }
11606 if (clientIntent != null) {
11607 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11608 if (clientLabel != 0) {
11609 // There are no useful extras in the intent, trash them.
11610 // System code calling with this stuff just needs to know
11611 // this will happen.
11612 service = service.cloneFilter();
11613 }
11614 }
11615 }
11616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011617 ServiceLookupResult res =
11618 retrieveServiceLocked(service, resolvedType,
11619 Binder.getCallingPid(), Binder.getCallingUid());
11620 if (res == null) {
11621 return 0;
11622 }
11623 if (res.record == null) {
11624 return -1;
11625 }
11626 ServiceRecord s = res.record;
11627
11628 final long origId = Binder.clearCallingIdentity();
11629
11630 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011631 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011632 + s.shortName);
11633 }
11634
11635 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11636 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011637 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011638
11639 IBinder binder = connection.asBinder();
11640 s.connections.put(binder, c);
11641 b.connections.add(c);
11642 if (activity != null) {
11643 if (activity.connections == null) {
11644 activity.connections = new HashSet<ConnectionRecord>();
11645 }
11646 activity.connections.add(c);
11647 }
11648 b.client.connections.add(c);
11649 mServiceConnections.put(binder, c);
11650
11651 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11652 s.lastActivity = SystemClock.uptimeMillis();
11653 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11654 return 0;
11655 }
11656 }
11657
11658 if (s.app != null) {
11659 // This could have made the service more important.
11660 updateOomAdjLocked(s.app);
11661 }
11662
Joe Onorato8a9b2202010-02-26 18:56:32 -080011663 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011664 + ": received=" + b.intent.received
11665 + " apps=" + b.intent.apps.size()
11666 + " doRebind=" + b.intent.doRebind);
11667
11668 if (s.app != null && b.intent.received) {
11669 // Service is already running, so we can immediately
11670 // publish the connection.
11671 try {
11672 c.conn.connected(s.name, b.intent.binder);
11673 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011674 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011675 + " to connection " + c.conn.asBinder()
11676 + " (in " + c.binding.client.processName + ")", e);
11677 }
11678
11679 // If this is the first app connected back to this binding,
11680 // and the service had previously asked to be told when
11681 // rebound, then do so.
11682 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11683 requestServiceBindingLocked(s, b.intent, true);
11684 }
11685 } else if (!b.intent.requested) {
11686 requestServiceBindingLocked(s, b.intent, false);
11687 }
11688
11689 Binder.restoreCallingIdentity(origId);
11690 }
11691
11692 return 1;
11693 }
11694
11695 private void removeConnectionLocked(
11696 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11697 IBinder binder = c.conn.asBinder();
11698 AppBindRecord b = c.binding;
11699 ServiceRecord s = b.service;
11700 s.connections.remove(binder);
11701 b.connections.remove(c);
11702 if (c.activity != null && c.activity != skipAct) {
11703 if (c.activity.connections != null) {
11704 c.activity.connections.remove(c);
11705 }
11706 }
11707 if (b.client != skipApp) {
11708 b.client.connections.remove(c);
11709 }
11710 mServiceConnections.remove(binder);
11711
11712 if (b.connections.size() == 0) {
11713 b.intent.apps.remove(b.client);
11714 }
11715
Joe Onorato8a9b2202010-02-26 18:56:32 -080011716 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011717 + ": shouldUnbind=" + b.intent.hasBound);
11718 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11719 && b.intent.hasBound) {
11720 try {
11721 bumpServiceExecutingLocked(s);
11722 updateOomAdjLocked(s.app);
11723 b.intent.hasBound = false;
11724 // Assume the client doesn't want to know about a rebind;
11725 // we will deal with that later if it asks for one.
11726 b.intent.doRebind = false;
11727 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11728 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011729 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 serviceDoneExecutingLocked(s, true);
11731 }
11732 }
11733
11734 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11735 bringDownServiceLocked(s, false);
11736 }
11737 }
11738
11739 public boolean unbindService(IServiceConnection connection) {
11740 synchronized (this) {
11741 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011742 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011743 ConnectionRecord r = mServiceConnections.get(binder);
11744 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011745 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011746 + connection.asBinder());
11747 return false;
11748 }
11749
11750 final long origId = Binder.clearCallingIdentity();
11751
11752 removeConnectionLocked(r, null, null);
11753
11754 if (r.binding.service.app != null) {
11755 // This could have made the service less important.
11756 updateOomAdjLocked(r.binding.service.app);
11757 }
11758
11759 Binder.restoreCallingIdentity(origId);
11760 }
11761
11762 return true;
11763 }
11764
11765 public void publishService(IBinder token, Intent intent, IBinder service) {
11766 // Refuse possible leaked file descriptors
11767 if (intent != null && intent.hasFileDescriptors() == true) {
11768 throw new IllegalArgumentException("File descriptors passed in Intent");
11769 }
11770
11771 synchronized(this) {
11772 if (!(token instanceof ServiceRecord)) {
11773 throw new IllegalArgumentException("Invalid service token");
11774 }
11775 ServiceRecord r = (ServiceRecord)token;
11776
11777 final long origId = Binder.clearCallingIdentity();
11778
Joe Onorato8a9b2202010-02-26 18:56:32 -080011779 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011780 + " " + intent + ": " + service);
11781 if (r != null) {
11782 Intent.FilterComparison filter
11783 = new Intent.FilterComparison(intent);
11784 IntentBindRecord b = r.bindings.get(filter);
11785 if (b != null && !b.received) {
11786 b.binder = service;
11787 b.requested = true;
11788 b.received = true;
11789 if (r.connections.size() > 0) {
11790 Iterator<ConnectionRecord> it
11791 = r.connections.values().iterator();
11792 while (it.hasNext()) {
11793 ConnectionRecord c = it.next();
11794 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011795 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011796 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011797 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011798 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011799 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011800 TAG, "Published intent: " + intent);
11801 continue;
11802 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011803 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 try {
11805 c.conn.connected(r.name, service);
11806 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011807 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808 " to connection " + c.conn.asBinder() +
11809 " (in " + c.binding.client.processName + ")", e);
11810 }
11811 }
11812 }
11813 }
11814
11815 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11816
11817 Binder.restoreCallingIdentity(origId);
11818 }
11819 }
11820 }
11821
11822 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11823 // Refuse possible leaked file descriptors
11824 if (intent != null && intent.hasFileDescriptors() == true) {
11825 throw new IllegalArgumentException("File descriptors passed in Intent");
11826 }
11827
11828 synchronized(this) {
11829 if (!(token instanceof ServiceRecord)) {
11830 throw new IllegalArgumentException("Invalid service token");
11831 }
11832 ServiceRecord r = (ServiceRecord)token;
11833
11834 final long origId = Binder.clearCallingIdentity();
11835
11836 if (r != null) {
11837 Intent.FilterComparison filter
11838 = new Intent.FilterComparison(intent);
11839 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011840 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011841 + " at " + b + ": apps="
11842 + (b != null ? b.apps.size() : 0));
11843 if (b != null) {
11844 if (b.apps.size() > 0) {
11845 // Applications have already bound since the last
11846 // unbind, so just rebind right here.
11847 requestServiceBindingLocked(r, b, true);
11848 } else {
11849 // Note to tell the service the next time there is
11850 // a new client.
11851 b.doRebind = true;
11852 }
11853 }
11854
11855 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11856
11857 Binder.restoreCallingIdentity(origId);
11858 }
11859 }
11860 }
11861
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011862 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011863 synchronized(this) {
11864 if (!(token instanceof ServiceRecord)) {
11865 throw new IllegalArgumentException("Invalid service token");
11866 }
11867 ServiceRecord r = (ServiceRecord)token;
11868 boolean inStopping = mStoppingServices.contains(token);
11869 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011870 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011871 + ": nesting=" + r.executeNesting
11872 + ", inStopping=" + inStopping);
11873 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011874 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011875 + " with incorrect token: given " + token
11876 + ", expected " + r);
11877 return;
11878 }
11879
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011880 if (type == 1) {
11881 // This is a call from a service start... take care of
11882 // book-keeping.
11883 r.callStart = true;
11884 switch (res) {
11885 case Service.START_STICKY_COMPATIBILITY:
11886 case Service.START_STICKY: {
11887 // We are done with the associated start arguments.
11888 r.findDeliveredStart(startId, true);
11889 // Don't stop if killed.
11890 r.stopIfKilled = false;
11891 break;
11892 }
11893 case Service.START_NOT_STICKY: {
11894 // We are done with the associated start arguments.
11895 r.findDeliveredStart(startId, true);
11896 if (r.lastStartId == startId) {
11897 // There is no more work, and this service
11898 // doesn't want to hang around if killed.
11899 r.stopIfKilled = true;
11900 }
11901 break;
11902 }
11903 case Service.START_REDELIVER_INTENT: {
11904 // We'll keep this item until they explicitly
11905 // call stop for it, but keep track of the fact
11906 // that it was delivered.
11907 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11908 if (si != null) {
11909 si.deliveryCount = 0;
11910 si.doneExecutingCount++;
11911 // Don't stop if killed.
11912 r.stopIfKilled = true;
11913 }
11914 break;
11915 }
11916 default:
11917 throw new IllegalArgumentException(
11918 "Unknown service start result: " + res);
11919 }
11920 if (res == Service.START_STICKY_COMPATIBILITY) {
11921 r.callStart = false;
11922 }
11923 }
11924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011925 final long origId = Binder.clearCallingIdentity();
11926 serviceDoneExecutingLocked(r, inStopping);
11927 Binder.restoreCallingIdentity(origId);
11928 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011929 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011930 + " with token " + token);
11931 }
11932 }
11933 }
11934
11935 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11936 r.executeNesting--;
11937 if (r.executeNesting <= 0 && r.app != null) {
11938 r.app.executingServices.remove(r);
11939 if (r.app.executingServices.size() == 0) {
11940 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11941 }
11942 if (inStopping) {
11943 mStoppingServices.remove(r);
11944 }
11945 updateOomAdjLocked(r.app);
11946 }
11947 }
11948
11949 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011950 String anrMessage = null;
11951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 synchronized(this) {
11953 if (proc.executingServices.size() == 0 || proc.thread == null) {
11954 return;
11955 }
11956 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11957 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11958 ServiceRecord timeout = null;
11959 long nextTime = 0;
11960 while (it.hasNext()) {
11961 ServiceRecord sr = it.next();
11962 if (sr.executingStart < maxTime) {
11963 timeout = sr;
11964 break;
11965 }
11966 if (sr.executingStart > nextTime) {
11967 nextTime = sr.executingStart;
11968 }
11969 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011970 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011971 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011972 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011973 } else {
11974 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11975 msg.obj = proc;
11976 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11977 }
11978 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011979
11980 if (anrMessage != null) {
11981 appNotResponding(proc, null, null, anrMessage);
11982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011983 }
11984
11985 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011986 // BACKUP AND RESTORE
11987 // =========================================================
11988
11989 // Cause the target app to be launched if necessary and its backup agent
11990 // instantiated. The backup agent will invoke backupAgentCreated() on the
11991 // activity manager to announce its creation.
11992 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011993 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011994 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11995
11996 synchronized(this) {
11997 // !!! TODO: currently no check here that we're already bound
11998 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11999 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12000 synchronized (stats) {
12001 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12002 }
12003
12004 BackupRecord r = new BackupRecord(ss, app, backupMode);
12005 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12006 // startProcessLocked() returns existing proc's record if it's already running
12007 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012008 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012009 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012010 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012011 return false;
12012 }
12013
12014 r.app = proc;
12015 mBackupTarget = r;
12016 mBackupAppName = app.packageName;
12017
Christopher Tate6fa95972009-06-05 18:43:55 -070012018 // Try not to kill the process during backup
12019 updateOomAdjLocked(proc);
12020
Christopher Tate181fafa2009-05-14 11:12:14 -070012021 // If the process is already attached, schedule the creation of the backup agent now.
12022 // If it is not yet live, this will be done when it attaches to the framework.
12023 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012024 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012025 try {
12026 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12027 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012028 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012029 }
12030 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012031 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012032 }
12033 // Invariants: at this point, the target app process exists and the application
12034 // is either already running or in the process of coming up. mBackupTarget and
12035 // mBackupAppName describe the app, so that when it binds back to the AM we
12036 // know that it's scheduled for a backup-agent operation.
12037 }
12038
12039 return true;
12040 }
12041
12042 // A backup agent has just come up
12043 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012044 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012045 + " = " + agent);
12046
12047 synchronized(this) {
12048 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012049 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012050 return;
12051 }
12052
Christopher Tate043dadc2009-06-02 16:11:00 -070012053 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012054 try {
12055 IBackupManager bm = IBackupManager.Stub.asInterface(
12056 ServiceManager.getService(Context.BACKUP_SERVICE));
12057 bm.agentConnected(agentPackageName, agent);
12058 } catch (RemoteException e) {
12059 // can't happen; the backup manager service is local
12060 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012061 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012062 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012063 } finally {
12064 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012065 }
12066 }
12067 }
12068
12069 // done with this agent
12070 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012071 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012072 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012073 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012074 return;
12075 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012076
12077 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012078 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012079 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012080 return;
12081 }
12082
Christopher Tate181fafa2009-05-14 11:12:14 -070012083 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012084 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012085 return;
12086 }
12087
Christopher Tate6fa95972009-06-05 18:43:55 -070012088 ProcessRecord proc = mBackupTarget.app;
12089 mBackupTarget = null;
12090 mBackupAppName = null;
12091
12092 // Not backing this app up any more; reset its OOM adjustment
12093 updateOomAdjLocked(proc);
12094
Christopher Tatec7b31e32009-06-10 15:49:30 -070012095 // If the app crashed during backup, 'thread' will be null here
12096 if (proc.thread != null) {
12097 try {
12098 proc.thread.scheduleDestroyBackupAgent(appInfo);
12099 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012100 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012101 e.printStackTrace();
12102 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012103 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012104 }
12105 }
12106 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012107 // BROADCASTS
12108 // =========================================================
12109
Josh Bartel7f208742010-02-25 11:01:44 -060012110 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012111 List cur) {
12112 final ContentResolver resolver = mContext.getContentResolver();
12113 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12114 if (list == null) {
12115 return cur;
12116 }
12117 int N = list.size();
12118 for (int i=0; i<N; i++) {
12119 Intent intent = list.get(i);
12120 if (filter.match(resolver, intent, true, TAG) >= 0) {
12121 if (cur == null) {
12122 cur = new ArrayList<Intent>();
12123 }
12124 cur.add(intent);
12125 }
12126 }
12127 return cur;
12128 }
12129
12130 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012131 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012132 + mBroadcastsScheduled);
12133
12134 if (mBroadcastsScheduled) {
12135 return;
12136 }
12137 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12138 mBroadcastsScheduled = true;
12139 }
12140
12141 public Intent registerReceiver(IApplicationThread caller,
12142 IIntentReceiver receiver, IntentFilter filter, String permission) {
12143 synchronized(this) {
12144 ProcessRecord callerApp = null;
12145 if (caller != null) {
12146 callerApp = getRecordForAppLocked(caller);
12147 if (callerApp == null) {
12148 throw new SecurityException(
12149 "Unable to find app for caller " + caller
12150 + " (pid=" + Binder.getCallingPid()
12151 + ") when registering receiver " + receiver);
12152 }
12153 }
12154
12155 List allSticky = null;
12156
12157 // Look for any matching sticky broadcasts...
12158 Iterator actions = filter.actionsIterator();
12159 if (actions != null) {
12160 while (actions.hasNext()) {
12161 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012162 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012163 }
12164 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012165 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012166 }
12167
12168 // The first sticky in the list is returned directly back to
12169 // the client.
12170 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12171
Joe Onorato8a9b2202010-02-26 18:56:32 -080012172 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012173 + ": " + sticky);
12174
12175 if (receiver == null) {
12176 return sticky;
12177 }
12178
12179 ReceiverList rl
12180 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12181 if (rl == null) {
12182 rl = new ReceiverList(this, callerApp,
12183 Binder.getCallingPid(),
12184 Binder.getCallingUid(), receiver);
12185 if (rl.app != null) {
12186 rl.app.receivers.add(rl);
12187 } else {
12188 try {
12189 receiver.asBinder().linkToDeath(rl, 0);
12190 } catch (RemoteException e) {
12191 return sticky;
12192 }
12193 rl.linkedToDeath = true;
12194 }
12195 mRegisteredReceivers.put(receiver.asBinder(), rl);
12196 }
12197 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12198 rl.add(bf);
12199 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012200 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012201 }
12202 mReceiverResolver.addFilter(bf);
12203
12204 // Enqueue broadcasts for all existing stickies that match
12205 // this filter.
12206 if (allSticky != null) {
12207 ArrayList receivers = new ArrayList();
12208 receivers.add(bf);
12209
12210 int N = allSticky.size();
12211 for (int i=0; i<N; i++) {
12212 Intent intent = (Intent)allSticky.get(i);
12213 BroadcastRecord r = new BroadcastRecord(intent, null,
12214 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012215 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012216 if (mParallelBroadcasts.size() == 0) {
12217 scheduleBroadcastsLocked();
12218 }
12219 mParallelBroadcasts.add(r);
12220 }
12221 }
12222
12223 return sticky;
12224 }
12225 }
12226
12227 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012228 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012229
12230 boolean doNext = false;
12231
12232 synchronized(this) {
12233 ReceiverList rl
12234 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12235 if (rl != null) {
12236 if (rl.curBroadcast != null) {
12237 BroadcastRecord r = rl.curBroadcast;
12238 doNext = finishReceiverLocked(
12239 receiver.asBinder(), r.resultCode, r.resultData,
12240 r.resultExtras, r.resultAbort, true);
12241 }
12242
12243 if (rl.app != null) {
12244 rl.app.receivers.remove(rl);
12245 }
12246 removeReceiverLocked(rl);
12247 if (rl.linkedToDeath) {
12248 rl.linkedToDeath = false;
12249 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12250 }
12251 }
12252 }
12253
12254 if (!doNext) {
12255 return;
12256 }
12257
12258 final long origId = Binder.clearCallingIdentity();
12259 processNextBroadcast(false);
12260 trimApplications();
12261 Binder.restoreCallingIdentity(origId);
12262 }
12263
12264 void removeReceiverLocked(ReceiverList rl) {
12265 mRegisteredReceivers.remove(rl.receiver.asBinder());
12266 int N = rl.size();
12267 for (int i=0; i<N; i++) {
12268 mReceiverResolver.removeFilter(rl.get(i));
12269 }
12270 }
12271
12272 private final int broadcastIntentLocked(ProcessRecord callerApp,
12273 String callerPackage, Intent intent, String resolvedType,
12274 IIntentReceiver resultTo, int resultCode, String resultData,
12275 Bundle map, String requiredPermission,
12276 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12277 intent = new Intent(intent);
12278
Joe Onorato8a9b2202010-02-26 18:56:32 -080012279 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12281 + " ordered=" + ordered);
12282 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012283 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012284 }
12285
12286 // Handle special intents: if this broadcast is from the package
12287 // manager about a package being removed, we need to remove all of
12288 // its activities from the history stack.
12289 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12290 intent.getAction());
12291 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12292 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012293 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012294 || uidRemoved) {
12295 if (checkComponentPermission(
12296 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12297 callingPid, callingUid, -1)
12298 == PackageManager.PERMISSION_GRANTED) {
12299 if (uidRemoved) {
12300 final Bundle intentExtras = intent.getExtras();
12301 final int uid = intentExtras != null
12302 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12303 if (uid >= 0) {
12304 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12305 synchronized (bs) {
12306 bs.removeUidStatsLocked(uid);
12307 }
12308 }
12309 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012310 // If resources are unvailble just force stop all
12311 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012312 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012313 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12314 if (list != null && (list.length > 0)) {
12315 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012316 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012317 }
12318 }
12319 } else {
12320 Uri data = intent.getData();
12321 String ssp;
12322 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12323 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12324 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012325 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012327 }
12328 }
12329 }
12330 } else {
12331 String msg = "Permission Denial: " + intent.getAction()
12332 + " broadcast from " + callerPackage + " (pid=" + callingPid
12333 + ", uid=" + callingUid + ")"
12334 + " requires "
12335 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012336 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012337 throw new SecurityException(msg);
12338 }
12339 }
12340
12341 /*
12342 * If this is the time zone changed action, queue up a message that will reset the timezone
12343 * of all currently running processes. This message will get queued up before the broadcast
12344 * happens.
12345 */
12346 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12347 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12348 }
12349
Dianne Hackborn854060af2009-07-09 18:14:31 -070012350 /*
12351 * Prevent non-system code (defined here to be non-persistent
12352 * processes) from sending protected broadcasts.
12353 */
12354 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12355 || callingUid == Process.SHELL_UID || callingUid == 0) {
12356 // Always okay.
12357 } else if (callerApp == null || !callerApp.persistent) {
12358 try {
12359 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12360 intent.getAction())) {
12361 String msg = "Permission Denial: not allowed to send broadcast "
12362 + intent.getAction() + " from pid="
12363 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012364 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012365 throw new SecurityException(msg);
12366 }
12367 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012368 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012369 return BROADCAST_SUCCESS;
12370 }
12371 }
12372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012373 // Add to the sticky list if requested.
12374 if (sticky) {
12375 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12376 callingPid, callingUid)
12377 != PackageManager.PERMISSION_GRANTED) {
12378 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12379 + callingPid + ", uid=" + callingUid
12380 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012381 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012382 throw new SecurityException(msg);
12383 }
12384 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012385 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012386 + " and enforce permission " + requiredPermission);
12387 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12388 }
12389 if (intent.getComponent() != null) {
12390 throw new SecurityException(
12391 "Sticky broadcasts can't target a specific component");
12392 }
12393 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12394 if (list == null) {
12395 list = new ArrayList<Intent>();
12396 mStickyBroadcasts.put(intent.getAction(), list);
12397 }
12398 int N = list.size();
12399 int i;
12400 for (i=0; i<N; i++) {
12401 if (intent.filterEquals(list.get(i))) {
12402 // This sticky already exists, replace it.
12403 list.set(i, new Intent(intent));
12404 break;
12405 }
12406 }
12407 if (i >= N) {
12408 list.add(new Intent(intent));
12409 }
12410 }
12411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012412 // Figure out who all will receive this broadcast.
12413 List receivers = null;
12414 List<BroadcastFilter> registeredReceivers = null;
12415 try {
12416 if (intent.getComponent() != null) {
12417 // Broadcast is going to one specific receiver class...
12418 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012419 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012420 if (ai != null) {
12421 receivers = new ArrayList();
12422 ResolveInfo ri = new ResolveInfo();
12423 ri.activityInfo = ai;
12424 receivers.add(ri);
12425 }
12426 } else {
12427 // Need to resolve the intent to interested receivers...
12428 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12429 == 0) {
12430 receivers =
12431 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012432 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012433 }
Mihai Preda074edef2009-05-18 17:13:31 +020012434 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012435 }
12436 } catch (RemoteException ex) {
12437 // pm is in same process, this will never happen.
12438 }
12439
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012440 final boolean replacePending =
12441 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12442
Joe Onorato8a9b2202010-02-26 18:56:32 -080012443 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012444 + " replacePending=" + replacePending);
12445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012446 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12447 if (!ordered && NR > 0) {
12448 // If we are not serializing this broadcast, then send the
12449 // registered receivers separately so they don't wait for the
12450 // components to be launched.
12451 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12452 callerPackage, callingPid, callingUid, requiredPermission,
12453 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012454 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012455 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012456 TAG, "Enqueueing parallel broadcast " + r
12457 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012458 boolean replaced = false;
12459 if (replacePending) {
12460 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12461 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012462 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012463 "***** DROPPING PARALLEL: " + intent);
12464 mParallelBroadcasts.set(i, r);
12465 replaced = true;
12466 break;
12467 }
12468 }
12469 }
12470 if (!replaced) {
12471 mParallelBroadcasts.add(r);
12472 scheduleBroadcastsLocked();
12473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012474 registeredReceivers = null;
12475 NR = 0;
12476 }
12477
12478 // Merge into one list.
12479 int ir = 0;
12480 if (receivers != null) {
12481 // A special case for PACKAGE_ADDED: do not allow the package
12482 // being added to see this broadcast. This prevents them from
12483 // using this as a back door to get run as soon as they are
12484 // installed. Maybe in the future we want to have a special install
12485 // broadcast or such for apps, but we'd like to deliberately make
12486 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012487 String skipPackages[] = null;
12488 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12489 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12490 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12491 Uri data = intent.getData();
12492 if (data != null) {
12493 String pkgName = data.getSchemeSpecificPart();
12494 if (pkgName != null) {
12495 skipPackages = new String[] { pkgName };
12496 }
12497 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012498 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012499 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012500 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012501 if (skipPackages != null && (skipPackages.length > 0)) {
12502 for (String skipPackage : skipPackages) {
12503 if (skipPackage != null) {
12504 int NT = receivers.size();
12505 for (int it=0; it<NT; it++) {
12506 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12507 if (curt.activityInfo.packageName.equals(skipPackage)) {
12508 receivers.remove(it);
12509 it--;
12510 NT--;
12511 }
12512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012513 }
12514 }
12515 }
12516
12517 int NT = receivers != null ? receivers.size() : 0;
12518 int it = 0;
12519 ResolveInfo curt = null;
12520 BroadcastFilter curr = null;
12521 while (it < NT && ir < NR) {
12522 if (curt == null) {
12523 curt = (ResolveInfo)receivers.get(it);
12524 }
12525 if (curr == null) {
12526 curr = registeredReceivers.get(ir);
12527 }
12528 if (curr.getPriority() >= curt.priority) {
12529 // Insert this broadcast record into the final list.
12530 receivers.add(it, curr);
12531 ir++;
12532 curr = null;
12533 it++;
12534 NT++;
12535 } else {
12536 // Skip to the next ResolveInfo in the final list.
12537 it++;
12538 curt = null;
12539 }
12540 }
12541 }
12542 while (ir < NR) {
12543 if (receivers == null) {
12544 receivers = new ArrayList();
12545 }
12546 receivers.add(registeredReceivers.get(ir));
12547 ir++;
12548 }
12549
12550 if ((receivers != null && receivers.size() > 0)
12551 || resultTo != null) {
12552 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12553 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012554 receivers, resultTo, resultCode, resultData, map, ordered,
12555 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012556 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012557 TAG, "Enqueueing ordered broadcast " + r
12558 + ": prev had " + mOrderedBroadcasts.size());
12559 if (DEBUG_BROADCAST) {
12560 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012561 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012562 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012563 boolean replaced = false;
12564 if (replacePending) {
12565 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12566 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012567 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012568 "***** DROPPING ORDERED: " + intent);
12569 mOrderedBroadcasts.set(i, r);
12570 replaced = true;
12571 break;
12572 }
12573 }
12574 }
12575 if (!replaced) {
12576 mOrderedBroadcasts.add(r);
12577 scheduleBroadcastsLocked();
12578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012579 }
12580
12581 return BROADCAST_SUCCESS;
12582 }
12583
12584 public final int broadcastIntent(IApplicationThread caller,
12585 Intent intent, String resolvedType, IIntentReceiver resultTo,
12586 int resultCode, String resultData, Bundle map,
12587 String requiredPermission, boolean serialized, boolean sticky) {
12588 // Refuse possible leaked file descriptors
12589 if (intent != null && intent.hasFileDescriptors() == true) {
12590 throw new IllegalArgumentException("File descriptors passed in Intent");
12591 }
12592
12593 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012594 int flags = intent.getFlags();
12595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012596 if (!mSystemReady) {
12597 // if the caller really truly claims to know what they're doing, go
12598 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012599 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12600 intent = new Intent(intent);
12601 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12602 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012603 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012604 + " before boot completion");
12605 throw new IllegalStateException("Cannot broadcast before boot completed");
12606 }
12607 }
12608
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012609 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12610 throw new IllegalArgumentException(
12611 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12612 }
12613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012614 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12615 final int callingPid = Binder.getCallingPid();
12616 final int callingUid = Binder.getCallingUid();
12617 final long origId = Binder.clearCallingIdentity();
12618 int res = broadcastIntentLocked(callerApp,
12619 callerApp != null ? callerApp.info.packageName : null,
12620 intent, resolvedType, resultTo,
12621 resultCode, resultData, map, requiredPermission, serialized,
12622 sticky, callingPid, callingUid);
12623 Binder.restoreCallingIdentity(origId);
12624 return res;
12625 }
12626 }
12627
12628 int broadcastIntentInPackage(String packageName, int uid,
12629 Intent intent, String resolvedType, IIntentReceiver resultTo,
12630 int resultCode, String resultData, Bundle map,
12631 String requiredPermission, boolean serialized, boolean sticky) {
12632 synchronized(this) {
12633 final long origId = Binder.clearCallingIdentity();
12634 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12635 resultTo, resultCode, resultData, map, requiredPermission,
12636 serialized, sticky, -1, uid);
12637 Binder.restoreCallingIdentity(origId);
12638 return res;
12639 }
12640 }
12641
12642 public final void unbroadcastIntent(IApplicationThread caller,
12643 Intent intent) {
12644 // Refuse possible leaked file descriptors
12645 if (intent != null && intent.hasFileDescriptors() == true) {
12646 throw new IllegalArgumentException("File descriptors passed in Intent");
12647 }
12648
12649 synchronized(this) {
12650 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12651 != PackageManager.PERMISSION_GRANTED) {
12652 String msg = "Permission Denial: unbroadcastIntent() from pid="
12653 + Binder.getCallingPid()
12654 + ", uid=" + Binder.getCallingUid()
12655 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012656 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012657 throw new SecurityException(msg);
12658 }
12659 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12660 if (list != null) {
12661 int N = list.size();
12662 int i;
12663 for (i=0; i<N; i++) {
12664 if (intent.filterEquals(list.get(i))) {
12665 list.remove(i);
12666 break;
12667 }
12668 }
12669 }
12670 }
12671 }
12672
12673 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12674 String resultData, Bundle resultExtras, boolean resultAbort,
12675 boolean explicit) {
12676 if (mOrderedBroadcasts.size() == 0) {
12677 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012678 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012679 }
12680 return false;
12681 }
12682 BroadcastRecord r = mOrderedBroadcasts.get(0);
12683 if (r.receiver == null) {
12684 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012685 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012686 }
12687 return false;
12688 }
12689 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012690 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012691 return false;
12692 }
12693 int state = r.state;
12694 r.state = r.IDLE;
12695 if (state == r.IDLE) {
12696 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012697 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012698 }
12699 }
12700 r.receiver = null;
12701 r.intent.setComponent(null);
12702 if (r.curApp != null) {
12703 r.curApp.curReceiver = null;
12704 }
12705 if (r.curFilter != null) {
12706 r.curFilter.receiverList.curBroadcast = null;
12707 }
12708 r.curFilter = null;
12709 r.curApp = null;
12710 r.curComponent = null;
12711 r.curReceiver = null;
12712 mPendingBroadcast = null;
12713
12714 r.resultCode = resultCode;
12715 r.resultData = resultData;
12716 r.resultExtras = resultExtras;
12717 r.resultAbort = resultAbort;
12718
12719 // We will process the next receiver right now if this is finishing
12720 // an app receiver (which is always asynchronous) or after we have
12721 // come back from calling a receiver.
12722 return state == BroadcastRecord.APP_RECEIVE
12723 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12724 }
12725
12726 public void finishReceiver(IBinder who, int resultCode, String resultData,
12727 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012728 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012729
12730 // Refuse possible leaked file descriptors
12731 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12732 throw new IllegalArgumentException("File descriptors passed in Bundle");
12733 }
12734
12735 boolean doNext;
12736
12737 final long origId = Binder.clearCallingIdentity();
12738
12739 synchronized(this) {
12740 doNext = finishReceiverLocked(
12741 who, resultCode, resultData, resultExtras, resultAbort, true);
12742 }
12743
12744 if (doNext) {
12745 processNextBroadcast(false);
12746 }
12747 trimApplications();
12748
12749 Binder.restoreCallingIdentity(origId);
12750 }
12751
12752 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12753 if (r.nextReceiver > 0) {
12754 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12755 if (curReceiver instanceof BroadcastFilter) {
12756 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012757 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012758 System.identityHashCode(r),
12759 r.intent.getAction(),
12760 r.nextReceiver - 1,
12761 System.identityHashCode(bf));
12762 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012763 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012764 System.identityHashCode(r),
12765 r.intent.getAction(),
12766 r.nextReceiver - 1,
12767 ((ResolveInfo)curReceiver).toString());
12768 }
12769 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012770 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012771 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012772 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012773 System.identityHashCode(r),
12774 r.intent.getAction(),
12775 r.nextReceiver,
12776 "NONE");
12777 }
12778 }
12779
12780 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012781 ProcessRecord app = null;
12782 String anrMessage = null;
12783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012784 synchronized (this) {
12785 if (mOrderedBroadcasts.size() == 0) {
12786 return;
12787 }
12788 long now = SystemClock.uptimeMillis();
12789 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012790 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012791 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012792 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012793 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012794 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012795 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012796 return;
12797 }
12798
Joe Onorato8a9b2202010-02-26 18:56:32 -080012799 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012800 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012801 r.anrCount++;
12802
12803 // Current receiver has passed its expiration date.
12804 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012805 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012806 return;
12807 }
12808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012809 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012810 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012811 logBroadcastReceiverDiscard(r);
12812 if (curReceiver instanceof BroadcastFilter) {
12813 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12814 if (bf.receiverList.pid != 0
12815 && bf.receiverList.pid != MY_PID) {
12816 synchronized (this.mPidsSelfLocked) {
12817 app = this.mPidsSelfLocked.get(
12818 bf.receiverList.pid);
12819 }
12820 }
12821 } else {
12822 app = r.curApp;
12823 }
12824
12825 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012826 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012827 }
12828
12829 if (mPendingBroadcast == r) {
12830 mPendingBroadcast = null;
12831 }
12832
12833 // Move on to the next receiver.
12834 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12835 r.resultExtras, r.resultAbort, true);
12836 scheduleBroadcastsLocked();
12837 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012838
12839 if (anrMessage != null) {
12840 appNotResponding(app, null, null, anrMessage);
12841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012842 }
12843
12844 private final void processCurBroadcastLocked(BroadcastRecord r,
12845 ProcessRecord app) throws RemoteException {
12846 if (app.thread == null) {
12847 throw new RemoteException();
12848 }
12849 r.receiver = app.thread.asBinder();
12850 r.curApp = app;
12851 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012852 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012853
12854 // Tell the application to launch this receiver.
12855 r.intent.setComponent(r.curComponent);
12856
12857 boolean started = false;
12858 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012859 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012860 "Delivering to component " + r.curComponent
12861 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012862 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012863 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12864 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12865 started = true;
12866 } finally {
12867 if (!started) {
12868 r.receiver = null;
12869 r.curApp = null;
12870 app.curReceiver = null;
12871 }
12872 }
12873
12874 }
12875
12876 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012877 Intent intent, int resultCode, String data, Bundle extras,
12878 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012879 if (app != null && app.thread != null) {
12880 // If we have an app thread, do the call through that so it is
12881 // correctly ordered with other one-way calls.
12882 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012883 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012884 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012885 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012886 }
12887 }
12888
12889 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12890 BroadcastFilter filter, boolean ordered) {
12891 boolean skip = false;
12892 if (filter.requiredPermission != null) {
12893 int perm = checkComponentPermission(filter.requiredPermission,
12894 r.callingPid, r.callingUid, -1);
12895 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012896 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012897 + r.intent.toString()
12898 + " from " + r.callerPackage + " (pid="
12899 + r.callingPid + ", uid=" + r.callingUid + ")"
12900 + " requires " + filter.requiredPermission
12901 + " due to registered receiver " + filter);
12902 skip = true;
12903 }
12904 }
12905 if (r.requiredPermission != null) {
12906 int perm = checkComponentPermission(r.requiredPermission,
12907 filter.receiverList.pid, filter.receiverList.uid, -1);
12908 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012909 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012910 + r.intent.toString()
12911 + " to " + filter.receiverList.app
12912 + " (pid=" + filter.receiverList.pid
12913 + ", uid=" + filter.receiverList.uid + ")"
12914 + " requires " + r.requiredPermission
12915 + " due to sender " + r.callerPackage
12916 + " (uid " + r.callingUid + ")");
12917 skip = true;
12918 }
12919 }
12920
12921 if (!skip) {
12922 // If this is not being sent as an ordered broadcast, then we
12923 // don't want to touch the fields that keep track of the current
12924 // state of ordered broadcasts.
12925 if (ordered) {
12926 r.receiver = filter.receiverList.receiver.asBinder();
12927 r.curFilter = filter;
12928 filter.receiverList.curBroadcast = r;
12929 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012930 if (filter.receiverList.app != null) {
12931 // Bump hosting application to no longer be in background
12932 // scheduling class. Note that we can't do that if there
12933 // isn't an app... but we can only be in that case for
12934 // things that directly call the IActivityManager API, which
12935 // are already core system stuff so don't matter for this.
12936 r.curApp = filter.receiverList.app;
12937 filter.receiverList.app.curReceiver = r;
12938 updateOomAdjLocked();
12939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012940 }
12941 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012942 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012943 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012944 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012945 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012946 }
12947 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12948 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012949 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012950 if (ordered) {
12951 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12952 }
12953 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012954 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012955 if (ordered) {
12956 r.receiver = null;
12957 r.curFilter = null;
12958 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012959 if (filter.receiverList.app != null) {
12960 filter.receiverList.app.curReceiver = null;
12961 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012962 }
12963 }
12964 }
12965 }
12966
Dianne Hackborn12527f92009-11-11 17:39:50 -080012967 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12968 if (r.callingUid < 0) {
12969 // This was from a registerReceiver() call; ignore it.
12970 return;
12971 }
12972 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12973 MAX_BROADCAST_HISTORY-1);
12974 r.finishTime = SystemClock.uptimeMillis();
12975 mBroadcastHistory[0] = r;
12976 }
12977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012978 private final void processNextBroadcast(boolean fromMsg) {
12979 synchronized(this) {
12980 BroadcastRecord r;
12981
Joe Onorato8a9b2202010-02-26 18:56:32 -080012982 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012983 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012984 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012985
12986 updateCpuStats();
12987
12988 if (fromMsg) {
12989 mBroadcastsScheduled = false;
12990 }
12991
12992 // First, deliver any non-serialized broadcasts right away.
12993 while (mParallelBroadcasts.size() > 0) {
12994 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012995 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012996 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012997 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012998 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012999 for (int i=0; i<N; i++) {
13000 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013001 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013002 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013003 + target + ": " + r);
13004 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13005 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013006 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013007 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013008 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013009 }
13010
13011 // Now take care of the next serialized one...
13012
13013 // If we are waiting for a process to come up to handle the next
13014 // broadcast, then do nothing at this point. Just in case, we
13015 // check that the process we're waiting for still exists.
13016 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013017 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013018 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013019 + mPendingBroadcast.curApp);
13020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013021
13022 boolean isDead;
13023 synchronized (mPidsSelfLocked) {
13024 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13025 }
13026 if (!isDead) {
13027 // It's still alive, so keep waiting
13028 return;
13029 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013030 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013031 + " died before responding to broadcast");
13032 mPendingBroadcast = null;
13033 }
13034 }
13035
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013036 boolean looped = false;
13037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013038 do {
13039 if (mOrderedBroadcasts.size() == 0) {
13040 // No more broadcasts pending, so all done!
13041 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013042 if (looped) {
13043 // If we had finished the last ordered broadcast, then
13044 // make sure all processes have correct oom and sched
13045 // adjustments.
13046 updateOomAdjLocked();
13047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013048 return;
13049 }
13050 r = mOrderedBroadcasts.get(0);
13051 boolean forceReceive = false;
13052
13053 // Ensure that even if something goes awry with the timeout
13054 // detection, we catch "hung" broadcasts here, discard them,
13055 // and continue to make progress.
13056 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
13057 long now = SystemClock.uptimeMillis();
13058 if (r.dispatchTime > 0) {
13059 if ((numReceivers > 0) &&
13060 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013061 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013062 + " now=" + now
13063 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013064 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013065 + " intent=" + r.intent
13066 + " numReceivers=" + numReceivers
13067 + " nextReceiver=" + r.nextReceiver
13068 + " state=" + r.state);
13069 broadcastTimeout(); // forcibly finish this broadcast
13070 forceReceive = true;
13071 r.state = BroadcastRecord.IDLE;
13072 }
13073 }
13074
13075 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013076 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013077 "processNextBroadcast() called when not idle (state="
13078 + r.state + ")");
13079 return;
13080 }
13081
13082 if (r.receivers == null || r.nextReceiver >= numReceivers
13083 || r.resultAbort || forceReceive) {
13084 // No more receivers for this broadcast! Send the final
13085 // result if requested...
13086 if (r.resultTo != null) {
13087 try {
13088 if (DEBUG_BROADCAST) {
13089 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013090 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013091 + " seq=" + seq + " app=" + r.callerApp);
13092 }
13093 performReceive(r.callerApp, r.resultTo,
13094 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013095 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013096 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013097 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013098 }
13099 }
13100
Joe Onorato8a9b2202010-02-26 18:56:32 -080013101 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013102 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13103
Joe Onorato8a9b2202010-02-26 18:56:32 -080013104 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013105 + r);
13106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013107 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013108 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013109 mOrderedBroadcasts.remove(0);
13110 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013111 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013112 continue;
13113 }
13114 } while (r == null);
13115
13116 // Get the next receiver...
13117 int recIdx = r.nextReceiver++;
13118
13119 // Keep track of when this receiver started, and make sure there
13120 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013121 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013122 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013123 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013124
Joe Onorato8a9b2202010-02-26 18:56:32 -080013125 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013126 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013127 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013128 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013129 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013130 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013131 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013132 }
13133
13134 Object nextReceiver = r.receivers.get(recIdx);
13135 if (nextReceiver instanceof BroadcastFilter) {
13136 // Simple case: this is a registered receiver who gets
13137 // a direct call.
13138 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013139 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013140 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013141 + filter + ": " + r);
13142 deliverToRegisteredReceiver(r, filter, r.ordered);
13143 if (r.receiver == null || !r.ordered) {
13144 // The receiver has already finished, so schedule to
13145 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013146 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13147 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013148 r.state = BroadcastRecord.IDLE;
13149 scheduleBroadcastsLocked();
13150 }
13151 return;
13152 }
13153
13154 // Hard case: need to instantiate the receiver, possibly
13155 // starting its application process to host it.
13156
13157 ResolveInfo info =
13158 (ResolveInfo)nextReceiver;
13159
13160 boolean skip = false;
13161 int perm = checkComponentPermission(info.activityInfo.permission,
13162 r.callingPid, r.callingUid,
13163 info.activityInfo.exported
13164 ? -1 : info.activityInfo.applicationInfo.uid);
13165 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013166 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013167 + r.intent.toString()
13168 + " from " + r.callerPackage + " (pid=" + r.callingPid
13169 + ", uid=" + r.callingUid + ")"
13170 + " requires " + info.activityInfo.permission
13171 + " due to receiver " + info.activityInfo.packageName
13172 + "/" + info.activityInfo.name);
13173 skip = true;
13174 }
13175 if (r.callingUid != Process.SYSTEM_UID &&
13176 r.requiredPermission != null) {
13177 try {
13178 perm = ActivityThread.getPackageManager().
13179 checkPermission(r.requiredPermission,
13180 info.activityInfo.applicationInfo.packageName);
13181 } catch (RemoteException e) {
13182 perm = PackageManager.PERMISSION_DENIED;
13183 }
13184 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013185 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013186 + r.intent + " to "
13187 + info.activityInfo.applicationInfo.packageName
13188 + " requires " + r.requiredPermission
13189 + " due to sender " + r.callerPackage
13190 + " (uid " + r.callingUid + ")");
13191 skip = true;
13192 }
13193 }
13194 if (r.curApp != null && r.curApp.crashing) {
13195 // If the target process is crashing, just skip it.
13196 skip = true;
13197 }
13198
13199 if (skip) {
13200 r.receiver = null;
13201 r.curFilter = null;
13202 r.state = BroadcastRecord.IDLE;
13203 scheduleBroadcastsLocked();
13204 return;
13205 }
13206
13207 r.state = BroadcastRecord.APP_RECEIVE;
13208 String targetProcess = info.activityInfo.processName;
13209 r.curComponent = new ComponentName(
13210 info.activityInfo.applicationInfo.packageName,
13211 info.activityInfo.name);
13212 r.curReceiver = info.activityInfo;
13213
13214 // Is this receiver's application already running?
13215 ProcessRecord app = getProcessRecordLocked(targetProcess,
13216 info.activityInfo.applicationInfo.uid);
13217 if (app != null && app.thread != null) {
13218 try {
13219 processCurBroadcastLocked(r, app);
13220 return;
13221 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013222 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013223 + r.curComponent, e);
13224 }
13225
13226 // If a dead object exception was thrown -- fall through to
13227 // restart the application.
13228 }
13229
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013230 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013231 if ((r.curApp=startProcessLocked(targetProcess,
13232 info.activityInfo.applicationInfo, true,
13233 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013234 "broadcast", r.curComponent,
13235 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13236 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013237 // Ah, this recipient is unavailable. Finish it if necessary,
13238 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013239 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013240 + info.activityInfo.applicationInfo.packageName + "/"
13241 + info.activityInfo.applicationInfo.uid + " for broadcast "
13242 + r.intent + ": process is bad");
13243 logBroadcastReceiverDiscard(r);
13244 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13245 r.resultExtras, r.resultAbort, true);
13246 scheduleBroadcastsLocked();
13247 r.state = BroadcastRecord.IDLE;
13248 return;
13249 }
13250
13251 mPendingBroadcast = r;
13252 }
13253 }
13254
13255 // =========================================================
13256 // INSTRUMENTATION
13257 // =========================================================
13258
13259 public boolean startInstrumentation(ComponentName className,
13260 String profileFile, int flags, Bundle arguments,
13261 IInstrumentationWatcher watcher) {
13262 // Refuse possible leaked file descriptors
13263 if (arguments != null && arguments.hasFileDescriptors()) {
13264 throw new IllegalArgumentException("File descriptors passed in Bundle");
13265 }
13266
13267 synchronized(this) {
13268 InstrumentationInfo ii = null;
13269 ApplicationInfo ai = null;
13270 try {
13271 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013272 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013273 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013274 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013275 } catch (PackageManager.NameNotFoundException e) {
13276 }
13277 if (ii == null) {
13278 reportStartInstrumentationFailure(watcher, className,
13279 "Unable to find instrumentation info for: " + className);
13280 return false;
13281 }
13282 if (ai == null) {
13283 reportStartInstrumentationFailure(watcher, className,
13284 "Unable to find instrumentation target package: " + ii.targetPackage);
13285 return false;
13286 }
13287
13288 int match = mContext.getPackageManager().checkSignatures(
13289 ii.targetPackage, ii.packageName);
13290 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13291 String msg = "Permission Denial: starting instrumentation "
13292 + className + " from pid="
13293 + Binder.getCallingPid()
13294 + ", uid=" + Binder.getCallingPid()
13295 + " not allowed because package " + ii.packageName
13296 + " does not have a signature matching the target "
13297 + ii.targetPackage;
13298 reportStartInstrumentationFailure(watcher, className, msg);
13299 throw new SecurityException(msg);
13300 }
13301
13302 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013303 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013304 ProcessRecord app = addAppLocked(ai);
13305 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013306 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013307 app.instrumentationProfileFile = profileFile;
13308 app.instrumentationArguments = arguments;
13309 app.instrumentationWatcher = watcher;
13310 app.instrumentationResultClass = className;
13311 Binder.restoreCallingIdentity(origId);
13312 }
13313
13314 return true;
13315 }
13316
13317 /**
13318 * Report errors that occur while attempting to start Instrumentation. Always writes the
13319 * error to the logs, but if somebody is watching, send the report there too. This enables
13320 * the "am" command to report errors with more information.
13321 *
13322 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13323 * @param cn The component name of the instrumentation.
13324 * @param report The error report.
13325 */
13326 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13327 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013328 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013329 try {
13330 if (watcher != null) {
13331 Bundle results = new Bundle();
13332 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13333 results.putString("Error", report);
13334 watcher.instrumentationStatus(cn, -1, results);
13335 }
13336 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013337 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013338 }
13339 }
13340
13341 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13342 if (app.instrumentationWatcher != null) {
13343 try {
13344 // NOTE: IInstrumentationWatcher *must* be oneway here
13345 app.instrumentationWatcher.instrumentationFinished(
13346 app.instrumentationClass,
13347 resultCode,
13348 results);
13349 } catch (RemoteException e) {
13350 }
13351 }
13352 app.instrumentationWatcher = null;
13353 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013354 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013355 app.instrumentationProfileFile = null;
13356 app.instrumentationArguments = null;
13357
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013358 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013359 }
13360
13361 public void finishInstrumentation(IApplicationThread target,
13362 int resultCode, Bundle results) {
13363 // Refuse possible leaked file descriptors
13364 if (results != null && results.hasFileDescriptors()) {
13365 throw new IllegalArgumentException("File descriptors passed in Intent");
13366 }
13367
13368 synchronized(this) {
13369 ProcessRecord app = getRecordForAppLocked(target);
13370 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013371 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013372 return;
13373 }
13374 final long origId = Binder.clearCallingIdentity();
13375 finishInstrumentationLocked(app, resultCode, results);
13376 Binder.restoreCallingIdentity(origId);
13377 }
13378 }
13379
13380 // =========================================================
13381 // CONFIGURATION
13382 // =========================================================
13383
13384 public ConfigurationInfo getDeviceConfigurationInfo() {
13385 ConfigurationInfo config = new ConfigurationInfo();
13386 synchronized (this) {
13387 config.reqTouchScreen = mConfiguration.touchscreen;
13388 config.reqKeyboardType = mConfiguration.keyboard;
13389 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013390 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13391 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13393 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013394 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13395 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013396 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13397 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013398 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013399 }
13400 return config;
13401 }
13402
13403 public Configuration getConfiguration() {
13404 Configuration ci;
13405 synchronized(this) {
13406 ci = new Configuration(mConfiguration);
13407 }
13408 return ci;
13409 }
13410
13411 public void updateConfiguration(Configuration values) {
13412 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13413 "updateConfiguration()");
13414
13415 synchronized(this) {
13416 if (values == null && mWindowManager != null) {
13417 // sentinel: fetch the current configuration from the window manager
13418 values = mWindowManager.computeNewConfiguration();
13419 }
13420
13421 final long origId = Binder.clearCallingIdentity();
13422 updateConfigurationLocked(values, null);
13423 Binder.restoreCallingIdentity(origId);
13424 }
13425 }
13426
13427 /**
13428 * Do either or both things: (1) change the current configuration, and (2)
13429 * make sure the given activity is running with the (now) current
13430 * configuration. Returns true if the activity has been left running, or
13431 * false if <var>starting</var> is being destroyed to match the new
13432 * configuration.
13433 */
13434 public boolean updateConfigurationLocked(Configuration values,
13435 HistoryRecord starting) {
13436 int changes = 0;
13437
13438 boolean kept = true;
13439
13440 if (values != null) {
13441 Configuration newConfig = new Configuration(mConfiguration);
13442 changes = newConfig.updateFrom(values);
13443 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013444 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013445 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013446 }
13447
Doug Zongker2bec3d42009-12-04 12:52:44 -080013448 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013449
13450 if (values.locale != null) {
13451 saveLocaleLocked(values.locale,
13452 !values.locale.equals(mConfiguration.locale),
13453 values.userSetLocale);
13454 }
13455
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013456 mConfigurationSeq++;
13457 if (mConfigurationSeq <= 0) {
13458 mConfigurationSeq = 1;
13459 }
13460 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013461 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013462 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013463
13464 AttributeCache ac = AttributeCache.instance();
13465 if (ac != null) {
13466 ac.updateConfiguration(mConfiguration);
13467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013468
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013469 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13470 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13471 msg.obj = new Configuration(mConfiguration);
13472 mHandler.sendMessage(msg);
13473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013474
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013475 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13476 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013477 try {
13478 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013479 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013480 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013481 app.thread.scheduleConfigurationChanged(mConfiguration);
13482 }
13483 } catch (Exception e) {
13484 }
13485 }
13486 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013487 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13488 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013489 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13490 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013491 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13492 broadcastIntentLocked(null, null,
13493 new Intent(Intent.ACTION_LOCALE_CHANGED),
13494 null, null, 0, null, null,
13495 null, false, false, MY_PID, Process.SYSTEM_UID);
13496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013497 }
13498 }
13499
13500 if (changes != 0 && starting == null) {
13501 // If the configuration changed, and the caller is not already
13502 // in the process of starting an activity, then find the top
13503 // activity to check if its configuration needs to change.
13504 starting = topRunningActivityLocked(null);
13505 }
13506
13507 if (starting != null) {
13508 kept = ensureActivityConfigurationLocked(starting, changes);
13509 if (kept) {
13510 // If this didn't result in the starting activity being
13511 // destroyed, then we need to make sure at this point that all
13512 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013513 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013514 + ", ensuring others are correct.");
13515 ensureActivitiesVisibleLocked(starting, changes);
13516 }
13517 }
13518
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013519 if (values != null && mWindowManager != null) {
13520 mWindowManager.setNewConfiguration(mConfiguration);
13521 }
13522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013523 return kept;
13524 }
13525
13526 private final boolean relaunchActivityLocked(HistoryRecord r,
13527 int changes, boolean andResume) {
13528 List<ResultInfo> results = null;
13529 List<Intent> newIntents = null;
13530 if (andResume) {
13531 results = r.results;
13532 newIntents = r.newIntents;
13533 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013534 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013535 + " with results=" + results + " newIntents=" + newIntents
13536 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013537 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13538 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013539 r.task.taskId, r.shortComponentName);
13540
13541 r.startFreezingScreenLocked(r.app, 0);
13542
13543 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013544 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013545 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013546 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013547 // Note: don't need to call pauseIfSleepingLocked() here, because
13548 // the caller will only pass in 'andResume' if this activity is
13549 // currently resumed, which implies we aren't sleeping.
13550 } catch (RemoteException e) {
13551 return false;
13552 }
13553
13554 if (andResume) {
13555 r.results = null;
13556 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013557 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013558 }
13559
13560 return true;
13561 }
13562
13563 /**
13564 * Make sure the given activity matches the current configuration. Returns
13565 * false if the activity had to be destroyed. Returns true if the
13566 * configuration is the same, or the activity will remain running as-is
13567 * for whatever reason. Ensures the HistoryRecord is updated with the
13568 * correct configuration and all other bookkeeping is handled.
13569 */
13570 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13571 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013572 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013573 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13574 "Skipping config check (will change): " + r);
13575 return true;
13576 }
13577
Joe Onorato8a9b2202010-02-26 18:56:32 -080013578 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013579 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013580
13581 // Short circuit: if the two configurations are the exact same
13582 // object (the common case), then there is nothing to do.
13583 Configuration newConfig = mConfiguration;
13584 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013585 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013586 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013587 return true;
13588 }
13589
13590 // We don't worry about activities that are finishing.
13591 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013592 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013593 "Configuration doesn't matter in finishing " + r);
13594 r.stopFreezingScreenLocked(false);
13595 return true;
13596 }
13597
13598 // Okay we now are going to make this activity have the new config.
13599 // But then we need to figure out how it needs to deal with that.
13600 Configuration oldConfig = r.configuration;
13601 r.configuration = newConfig;
13602
13603 // If the activity isn't currently running, just leave the new
13604 // configuration and it will pick that up next time it starts.
13605 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013606 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013607 "Configuration doesn't matter not running " + r);
13608 r.stopFreezingScreenLocked(false);
13609 return true;
13610 }
13611
13612 // If the activity isn't persistent, there is a chance we will
13613 // need to restart it.
13614 if (!r.persistent) {
13615
13616 // Figure out what has changed between the two configurations.
13617 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013618 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013619 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013620 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013621 + Integer.toHexString(r.info.configChanges)
13622 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013623 }
13624 if ((changes&(~r.info.configChanges)) != 0) {
13625 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13626 r.configChangeFlags |= changes;
13627 r.startFreezingScreenLocked(r.app, globalChanges);
13628 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013629 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013630 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013631 destroyActivityLocked(r, true);
13632 } else if (r.state == ActivityState.PAUSING) {
13633 // A little annoying: we are waiting for this activity to
13634 // finish pausing. Let's not do anything now, but just
13635 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013636 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013637 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013638 r.configDestroy = true;
13639 return true;
13640 } else if (r.state == ActivityState.RESUMED) {
13641 // Try to optimize this case: the configuration is changing
13642 // and we need to restart the top, resumed activity.
13643 // Instead of doing the normal handshaking, just say
13644 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013645 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013646 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013647 relaunchActivityLocked(r, r.configChangeFlags, true);
13648 r.configChangeFlags = 0;
13649 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013650 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013651 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013652 relaunchActivityLocked(r, r.configChangeFlags, false);
13653 r.configChangeFlags = 0;
13654 }
13655
13656 // All done... tell the caller we weren't able to keep this
13657 // activity around.
13658 return false;
13659 }
13660 }
13661
13662 // Default case: the activity can handle this new configuration, so
13663 // hand it over. Note that we don't need to give it the new
13664 // configuration, since we always send configuration changes to all
13665 // process when they happen so it can just use whatever configuration
13666 // it last got.
13667 if (r.app != null && r.app.thread != null) {
13668 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013669 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013670 r.app.thread.scheduleActivityConfigurationChanged(r);
13671 } catch (RemoteException e) {
13672 // If process died, whatever.
13673 }
13674 }
13675 r.stopFreezingScreenLocked(false);
13676
13677 return true;
13678 }
13679
13680 /**
13681 * Save the locale. You must be inside a synchronized (this) block.
13682 */
13683 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13684 if(isDiff) {
13685 SystemProperties.set("user.language", l.getLanguage());
13686 SystemProperties.set("user.region", l.getCountry());
13687 }
13688
13689 if(isPersist) {
13690 SystemProperties.set("persist.sys.language", l.getLanguage());
13691 SystemProperties.set("persist.sys.country", l.getCountry());
13692 SystemProperties.set("persist.sys.localevar", l.getVariant());
13693 }
13694 }
13695
13696 // =========================================================
13697 // LIFETIME MANAGEMENT
13698 // =========================================================
13699
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013700 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13701 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013702 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013703 // This adjustment has already been computed. If we are calling
13704 // from the top, we may have already computed our adjustment with
13705 // an earlier hidden adjustment that isn't really for us... if
13706 // so, use the new hidden adjustment.
13707 if (!recursed && app.hidden) {
13708 app.curAdj = hiddenAdj;
13709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013710 return app.curAdj;
13711 }
13712
13713 if (app.thread == null) {
13714 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013715 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013716 return (app.curAdj=EMPTY_APP_ADJ);
13717 }
13718
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013719 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13720 // The max adjustment doesn't allow this app to be anything
13721 // below foreground, so it is not worth doing work for it.
13722 app.adjType = "fixed";
13723 app.adjSeq = mAdjSeq;
13724 app.curRawAdj = app.maxAdj;
13725 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13726 return (app.curAdj=app.maxAdj);
13727 }
13728
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013729 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013730 app.adjSource = null;
13731 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013732 app.empty = false;
13733 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013734
The Android Open Source Project4df24232009-03-05 14:34:35 -080013735 // Determine the importance of the process, starting with most
13736 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013737 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013738 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013739 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013740 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013741 // The last app on the list is the foreground app.
13742 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013743 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013744 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013745 } else if (app.instrumentationClass != null) {
13746 // Don't want to kill running instrumentation.
13747 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013748 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013749 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013750 } else if (app.persistentActivities > 0) {
13751 // Special persistent activities... shouldn't be used these days.
13752 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013753 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013754 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013755 } else if (app.curReceiver != null ||
13756 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13757 // An app that is currently receiving a broadcast also
13758 // counts as being in the foreground.
13759 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013760 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013761 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013762 } else if (app.executingServices.size() > 0) {
13763 // An app that is currently executing a service callback also
13764 // counts as being in the foreground.
13765 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013766 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013767 app.adjType = "exec-service";
13768 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013769 // The user is aware of this app, so make it visible.
13770 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013771 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013772 app.adjType = "foreground-service";
13773 } else if (app.forcingToForeground != null) {
13774 // The user is aware of this app, so make it visible.
13775 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013776 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013777 app.adjType = "force-foreground";
13778 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013779 } else if (app == mHomeProcess) {
13780 // This process is hosting what we currently consider to be the
13781 // home app, so we don't want to let it go into the background.
13782 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013783 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013784 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013785 } else if ((N=app.activities.size()) != 0) {
13786 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013787 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013788 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013789 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013790 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013791 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013792 for (int j=0; j<N; j++) {
13793 if (((HistoryRecord)app.activities.get(j)).visible) {
13794 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013795 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013796 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013797 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013798 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013799 break;
13800 }
13801 }
13802 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013803 // A very not-needed process. If this is lower in the lru list,
13804 // we will push it in to the empty bucket.
13805 app.hidden = true;
13806 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013807 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013808 adj = hiddenAdj;
13809 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013810 }
13811
Joe Onorato8a9b2202010-02-26 18:56:32 -080013812 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013813
The Android Open Source Project4df24232009-03-05 14:34:35 -080013814 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013815 // there are applications dependent on our services or providers, but
13816 // this gives us a baseline and makes sure we don't get into an
13817 // infinite recursion.
13818 app.adjSeq = mAdjSeq;
13819 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013820
Christopher Tate6fa95972009-06-05 18:43:55 -070013821 if (mBackupTarget != null && app == mBackupTarget.app) {
13822 // If possible we want to avoid killing apps while they're being backed up
13823 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013824 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013825 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013826 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013827 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013828 }
13829 }
13830
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013831 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13832 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013833 final long now = SystemClock.uptimeMillis();
13834 // This process is more important if the top activity is
13835 // bound to the service.
13836 Iterator jt = app.services.iterator();
13837 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13838 ServiceRecord s = (ServiceRecord)jt.next();
13839 if (s.startRequested) {
13840 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13841 // This service has seen some activity within
13842 // recent memory, so we will keep its process ahead
13843 // of the background processes.
13844 if (adj > SECONDARY_SERVER_ADJ) {
13845 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013846 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013847 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013848 }
13849 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013850 // If we have let the service slide into the background
13851 // state, still have some text describing what it is doing
13852 // even though the service no longer has an impact.
13853 if (adj > SECONDARY_SERVER_ADJ) {
13854 app.adjType = "started-bg-services";
13855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013856 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013857 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13858 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013859 Iterator<ConnectionRecord> kt
13860 = s.connections.values().iterator();
13861 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13862 // XXX should compute this based on the max of
13863 // all connected clients.
13864 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013865 if (cr.binding.client == app) {
13866 // Binding to ourself is not interesting.
13867 continue;
13868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013869 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13870 ProcessRecord client = cr.binding.client;
13871 int myHiddenAdj = hiddenAdj;
13872 if (myHiddenAdj > client.hiddenAdj) {
13873 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13874 myHiddenAdj = client.hiddenAdj;
13875 } else {
13876 myHiddenAdj = VISIBLE_APP_ADJ;
13877 }
13878 }
13879 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013880 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013881 if (adj > clientAdj) {
13882 adj = clientAdj > VISIBLE_APP_ADJ
13883 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013884 if (!client.hidden) {
13885 app.hidden = false;
13886 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013887 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013888 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13889 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013890 app.adjSource = cr.binding.client;
13891 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013892 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013893 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13894 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13895 schedGroup = Process.THREAD_GROUP_DEFAULT;
13896 }
13897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013898 }
13899 HistoryRecord a = cr.activity;
13900 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013901 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013902 //}
13903 if (a != null && adj > FOREGROUND_APP_ADJ &&
13904 (a.state == ActivityState.RESUMED
13905 || a.state == ActivityState.PAUSING)) {
13906 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013907 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013908 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013909 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013910 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13911 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013912 app.adjSource = a;
13913 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013914 }
13915 }
13916 }
13917 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013918
13919 // Finally, f this process has active services running in it, we
13920 // would like to avoid killing it unless it would prevent the current
13921 // application from running. By default we put the process in
13922 // with the rest of the background processes; as we scan through
13923 // its services we may bump it up from there.
13924 if (adj > hiddenAdj) {
13925 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013926 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013927 app.adjType = "bg-services";
13928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013929 }
13930
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013931 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13932 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013933 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013934 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13935 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013936 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13937 if (cpr.clients.size() != 0) {
13938 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13939 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13940 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013941 if (client == app) {
13942 // Being our own client is not interesting.
13943 continue;
13944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013945 int myHiddenAdj = hiddenAdj;
13946 if (myHiddenAdj > client.hiddenAdj) {
13947 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13948 myHiddenAdj = client.hiddenAdj;
13949 } else {
13950 myHiddenAdj = FOREGROUND_APP_ADJ;
13951 }
13952 }
13953 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013954 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013955 if (adj > clientAdj) {
13956 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013957 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013958 if (!client.hidden) {
13959 app.hidden = false;
13960 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013961 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013962 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13963 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013964 app.adjSource = client;
13965 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013966 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013967 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13968 schedGroup = Process.THREAD_GROUP_DEFAULT;
13969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013970 }
13971 }
13972 // If the provider has external (non-framework) process
13973 // dependencies, ensure that its adjustment is at least
13974 // FOREGROUND_APP_ADJ.
13975 if (cpr.externals != 0) {
13976 if (adj > FOREGROUND_APP_ADJ) {
13977 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013978 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013979 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013980 app.adjType = "provider";
13981 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013982 }
13983 }
13984 }
13985 }
13986
13987 app.curRawAdj = adj;
13988
Joe Onorato8a9b2202010-02-26 18:56:32 -080013989 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013990 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13991 if (adj > app.maxAdj) {
13992 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013993 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13994 schedGroup = Process.THREAD_GROUP_DEFAULT;
13995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013996 }
13997
13998 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013999 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014001 return adj;
14002 }
14003
14004 /**
14005 * Ask a given process to GC right now.
14006 */
14007 final void performAppGcLocked(ProcessRecord app) {
14008 try {
14009 app.lastRequestedGc = SystemClock.uptimeMillis();
14010 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014011 if (app.reportLowMemory) {
14012 app.reportLowMemory = false;
14013 app.thread.scheduleLowMemory();
14014 } else {
14015 app.thread.processInBackground();
14016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014017 }
14018 } catch (Exception e) {
14019 // whatever.
14020 }
14021 }
14022
14023 /**
14024 * Returns true if things are idle enough to perform GCs.
14025 */
Josh Bartel7f208742010-02-25 11:01:44 -060014026 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014027 return mParallelBroadcasts.size() == 0
14028 && mOrderedBroadcasts.size() == 0
14029 && (mSleeping || (mResumedActivity != null &&
14030 mResumedActivity.idle));
14031 }
14032
14033 /**
14034 * Perform GCs on all processes that are waiting for it, but only
14035 * if things are idle.
14036 */
14037 final void performAppGcsLocked() {
14038 final int N = mProcessesToGc.size();
14039 if (N <= 0) {
14040 return;
14041 }
Josh Bartel7f208742010-02-25 11:01:44 -060014042 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014043 while (mProcessesToGc.size() > 0) {
14044 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014045 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
14046 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14047 <= SystemClock.uptimeMillis()) {
14048 // To avoid spamming the system, we will GC processes one
14049 // at a time, waiting a few seconds between each.
14050 performAppGcLocked(proc);
14051 scheduleAppGcsLocked();
14052 return;
14053 } else {
14054 // It hasn't been long enough since we last GCed this
14055 // process... put it in the list to wait for its time.
14056 addProcessToGcListLocked(proc);
14057 break;
14058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014059 }
14060 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014061
14062 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014063 }
14064 }
14065
14066 /**
14067 * If all looks good, perform GCs on all processes waiting for them.
14068 */
14069 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014070 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014071 performAppGcsLocked();
14072 return;
14073 }
14074 // Still not idle, wait some more.
14075 scheduleAppGcsLocked();
14076 }
14077
14078 /**
14079 * Schedule the execution of all pending app GCs.
14080 */
14081 final void scheduleAppGcsLocked() {
14082 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014083
14084 if (mProcessesToGc.size() > 0) {
14085 // Schedule a GC for the time to the next process.
14086 ProcessRecord proc = mProcessesToGc.get(0);
14087 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14088
14089 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14090 long now = SystemClock.uptimeMillis();
14091 if (when < (now+GC_TIMEOUT)) {
14092 when = now + GC_TIMEOUT;
14093 }
14094 mHandler.sendMessageAtTime(msg, when);
14095 }
14096 }
14097
14098 /**
14099 * Add a process to the array of processes waiting to be GCed. Keeps the
14100 * list in sorted order by the last GC time. The process can't already be
14101 * on the list.
14102 */
14103 final void addProcessToGcListLocked(ProcessRecord proc) {
14104 boolean added = false;
14105 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14106 if (mProcessesToGc.get(i).lastRequestedGc <
14107 proc.lastRequestedGc) {
14108 added = true;
14109 mProcessesToGc.add(i+1, proc);
14110 break;
14111 }
14112 }
14113 if (!added) {
14114 mProcessesToGc.add(0, proc);
14115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014116 }
14117
14118 /**
14119 * Set up to ask a process to GC itself. This will either do it
14120 * immediately, or put it on the list of processes to gc the next
14121 * time things are idle.
14122 */
14123 final void scheduleAppGcLocked(ProcessRecord app) {
14124 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014125 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014126 return;
14127 }
14128 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014129 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014130 scheduleAppGcsLocked();
14131 }
14132 }
14133
14134 private final boolean updateOomAdjLocked(
14135 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14136 app.hiddenAdj = hiddenAdj;
14137
14138 if (app.thread == null) {
14139 return true;
14140 }
14141
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014142 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014143
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014144 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014145 if (app.curRawAdj != app.setRawAdj) {
14146 if (app.curRawAdj > FOREGROUND_APP_ADJ
14147 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14148 // If this app is transitioning from foreground to
14149 // non-foreground, have it do a gc.
14150 scheduleAppGcLocked(app);
14151 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14152 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14153 // Likewise do a gc when an app is moving in to the
14154 // background (such as a service stopping).
14155 scheduleAppGcLocked(app);
14156 }
14157 app.setRawAdj = app.curRawAdj;
14158 }
14159 if (adj != app.setAdj) {
14160 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014161 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014162 TAG, "Set app " + app.processName +
14163 " oom adj to " + adj);
14164 app.setAdj = adj;
14165 } else {
14166 return false;
14167 }
14168 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014169 if (app.setSchedGroup != app.curSchedGroup) {
14170 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014171 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014172 "Setting process group of " + app.processName
14173 + " to " + app.curSchedGroup);
14174 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014175 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014176 try {
14177 Process.setProcessGroup(app.pid, app.curSchedGroup);
14178 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014179 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014180 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014181 e.printStackTrace();
14182 } finally {
14183 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014184 }
14185 }
14186 if (false) {
14187 if (app.thread != null) {
14188 try {
14189 app.thread.setSchedulingGroup(app.curSchedGroup);
14190 } catch (RemoteException e) {
14191 }
14192 }
14193 }
14194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014195 }
14196
14197 return true;
14198 }
14199
14200 private final HistoryRecord resumedAppLocked() {
14201 HistoryRecord resumedActivity = mResumedActivity;
14202 if (resumedActivity == null || resumedActivity.app == null) {
14203 resumedActivity = mPausingActivity;
14204 if (resumedActivity == null || resumedActivity.app == null) {
14205 resumedActivity = topRunningActivityLocked(null);
14206 }
14207 }
14208 return resumedActivity;
14209 }
14210
14211 private final boolean updateOomAdjLocked(ProcessRecord app) {
14212 final HistoryRecord TOP_ACT = resumedAppLocked();
14213 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14214 int curAdj = app.curAdj;
14215 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14216 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14217
14218 mAdjSeq++;
14219
14220 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14221 if (res) {
14222 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14223 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14224 if (nowHidden != wasHidden) {
14225 // Changed to/from hidden state, so apps after it in the LRU
14226 // list may also be changed.
14227 updateOomAdjLocked();
14228 }
14229 }
14230 return res;
14231 }
14232
14233 private final boolean updateOomAdjLocked() {
14234 boolean didOomAdj = true;
14235 final HistoryRecord TOP_ACT = resumedAppLocked();
14236 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14237
14238 if (false) {
14239 RuntimeException e = new RuntimeException();
14240 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014241 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014242 }
14243
14244 mAdjSeq++;
14245
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014246 // Let's determine how many processes we have running vs.
14247 // how many slots we have for background processes; we may want
14248 // to put multiple processes in a slot of there are enough of
14249 // them.
14250 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14251 int factor = (mLruProcesses.size()-4)/numSlots;
14252 if (factor < 1) factor = 1;
14253 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014254 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014256 // First try updating the OOM adjustment for each of the
14257 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014258 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014259 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14260 while (i > 0) {
14261 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014262 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014263 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014264 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014265 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014266 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014267 step++;
14268 if (step >= factor) {
14269 step = 0;
14270 curHiddenAdj++;
14271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014272 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014273 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
14274 numHidden++;
14275 if (numHidden > MAX_HIDDEN_APPS) {
14276 Slog.i(TAG, "Kill " + app.processName
14277 + " (pid " + app.pid + "): hidden #" + numHidden
14278 + " beyond limit " + MAX_HIDDEN_APPS);
14279 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14280 app.processName, app.setAdj, "too many background");
14281 Process.killProcess(app.pid);
14282 }
14283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014284 } else {
14285 didOomAdj = false;
14286 }
14287 }
14288
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014289 // If we return false, we will fall back on killing processes to
14290 // have a fixed limit. Do this if a limit has been requested; else
14291 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014292 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14293 }
14294
14295 private final void trimApplications() {
14296 synchronized (this) {
14297 int i;
14298
14299 // First remove any unused application processes whose package
14300 // has been removed.
14301 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14302 final ProcessRecord app = mRemovedProcesses.get(i);
14303 if (app.activities.size() == 0
14304 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014305 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014306 TAG, "Exiting empty application process "
14307 + app.processName + " ("
14308 + (app.thread != null ? app.thread.asBinder() : null)
14309 + ")\n");
14310 if (app.pid > 0 && app.pid != MY_PID) {
14311 Process.killProcess(app.pid);
14312 } else {
14313 try {
14314 app.thread.scheduleExit();
14315 } catch (Exception e) {
14316 // Ignore exceptions.
14317 }
14318 }
14319 cleanUpApplicationRecordLocked(app, false, -1);
14320 mRemovedProcesses.remove(i);
14321
14322 if (app.persistent) {
14323 if (app.persistent) {
14324 addAppLocked(app.info);
14325 }
14326 }
14327 }
14328 }
14329
14330 // Now try updating the OOM adjustment for each of the
14331 // application processes based on their current state.
14332 // If the setOomAdj() API is not supported, then go with our
14333 // back-up plan...
14334 if (!updateOomAdjLocked()) {
14335
14336 // Count how many processes are running services.
14337 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014338 for (i=mLruProcesses.size()-1; i>=0; i--) {
14339 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014340
14341 if (app.persistent || app.services.size() != 0
14342 || app.curReceiver != null
14343 || app.persistentActivities > 0) {
14344 // Don't count processes holding services against our
14345 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014346 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014347 TAG, "Not trimming app " + app + " with services: "
14348 + app.services);
14349 numServiceProcs++;
14350 }
14351 }
14352
14353 int curMaxProcs = mProcessLimit;
14354 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14355 if (mAlwaysFinishActivities) {
14356 curMaxProcs = 1;
14357 }
14358 curMaxProcs += numServiceProcs;
14359
14360 // Quit as many processes as we can to get down to the desired
14361 // process count. First remove any processes that no longer
14362 // have activites running in them.
14363 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014364 i<mLruProcesses.size()
14365 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014366 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014367 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014368 // Quit an application only if it is not currently
14369 // running any activities.
14370 if (!app.persistent && app.activities.size() == 0
14371 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014372 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014373 TAG, "Exiting empty application process "
14374 + app.processName + " ("
14375 + (app.thread != null ? app.thread.asBinder() : null)
14376 + ")\n");
14377 if (app.pid > 0 && app.pid != MY_PID) {
14378 Process.killProcess(app.pid);
14379 } else {
14380 try {
14381 app.thread.scheduleExit();
14382 } catch (Exception e) {
14383 // Ignore exceptions.
14384 }
14385 }
14386 // todo: For now we assume the application is not buggy
14387 // or evil, and will quit as a result of our request.
14388 // Eventually we need to drive this off of the death
14389 // notification, and kill the process if it takes too long.
14390 cleanUpApplicationRecordLocked(app, false, i);
14391 i--;
14392 }
14393 }
14394
14395 // If we still have too many processes, now from the least
14396 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014397 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014398 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014399 " of " + curMaxProcs + " processes");
14400 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014401 i<mLruProcesses.size()
14402 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014403 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014404 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014405 // Quit the application only if we have a state saved for
14406 // all of its activities.
14407 boolean canQuit = !app.persistent && app.curReceiver == null
14408 && app.services.size() == 0
14409 && app.persistentActivities == 0;
14410 int NUMA = app.activities.size();
14411 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014412 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014413 TAG, "Looking to quit " + app.processName);
14414 for (j=0; j<NUMA && canQuit; j++) {
14415 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014416 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014417 TAG, " " + r.intent.getComponent().flattenToShortString()
14418 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14419 canQuit = (r.haveState || !r.stateNotNeeded)
14420 && !r.visible && r.stopped;
14421 }
14422 if (canQuit) {
14423 // Finish all of the activities, and then the app itself.
14424 for (j=0; j<NUMA; j++) {
14425 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14426 if (!r.finishing) {
14427 destroyActivityLocked(r, false);
14428 }
14429 r.resultTo = null;
14430 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014431 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014432 + app.processName + " ("
14433 + (app.thread != null ? app.thread.asBinder() : null)
14434 + ")\n");
14435 if (app.pid > 0 && app.pid != MY_PID) {
14436 Process.killProcess(app.pid);
14437 } else {
14438 try {
14439 app.thread.scheduleExit();
14440 } catch (Exception e) {
14441 // Ignore exceptions.
14442 }
14443 }
14444 // todo: For now we assume the application is not buggy
14445 // or evil, and will quit as a result of our request.
14446 // Eventually we need to drive this off of the death
14447 // notification, and kill the process if it takes too long.
14448 cleanUpApplicationRecordLocked(app, false, i);
14449 i--;
14450 //dump();
14451 }
14452 }
14453
14454 }
14455
14456 int curMaxActivities = MAX_ACTIVITIES;
14457 if (mAlwaysFinishActivities) {
14458 curMaxActivities = 1;
14459 }
14460
14461 // Finally, if there are too many activities now running, try to
14462 // finish as many as we can to get back down to the limit.
14463 for ( i=0;
14464 i<mLRUActivities.size()
14465 && mLRUActivities.size() > curMaxActivities;
14466 i++) {
14467 final HistoryRecord r
14468 = (HistoryRecord)mLRUActivities.get(i);
14469
14470 // We can finish this one if we have its icicle saved and
14471 // it is not persistent.
14472 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14473 && r.stopped && !r.persistent && !r.finishing) {
14474 final int origSize = mLRUActivities.size();
14475 destroyActivityLocked(r, true);
14476
14477 // This will remove it from the LRU list, so keep
14478 // our index at the same value. Note that this check to
14479 // see if the size changes is just paranoia -- if
14480 // something unexpected happens, we don't want to end up
14481 // in an infinite loop.
14482 if (origSize > mLRUActivities.size()) {
14483 i--;
14484 }
14485 }
14486 }
14487 }
14488 }
14489
14490 /** This method sends the specified signal to each of the persistent apps */
14491 public void signalPersistentProcesses(int sig) throws RemoteException {
14492 if (sig != Process.SIGNAL_USR1) {
14493 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14494 }
14495
14496 synchronized (this) {
14497 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14498 != PackageManager.PERMISSION_GRANTED) {
14499 throw new SecurityException("Requires permission "
14500 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14501 }
14502
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014503 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14504 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014505 if (r.thread != null && r.persistent) {
14506 Process.sendSignal(r.pid, sig);
14507 }
14508 }
14509 }
14510 }
14511
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014512 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014513 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014514
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014515 try {
14516 synchronized (this) {
14517 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14518 // its own permission.
14519 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14520 != PackageManager.PERMISSION_GRANTED) {
14521 throw new SecurityException("Requires permission "
14522 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014523 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014524
14525 if (start && fd == null) {
14526 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014527 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014528
14529 ProcessRecord proc = null;
14530 try {
14531 int pid = Integer.parseInt(process);
14532 synchronized (mPidsSelfLocked) {
14533 proc = mPidsSelfLocked.get(pid);
14534 }
14535 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014536 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014537
14538 if (proc == null) {
14539 HashMap<String, SparseArray<ProcessRecord>> all
14540 = mProcessNames.getMap();
14541 SparseArray<ProcessRecord> procs = all.get(process);
14542 if (procs != null && procs.size() > 0) {
14543 proc = procs.valueAt(0);
14544 }
14545 }
14546
14547 if (proc == null || proc.thread == null) {
14548 throw new IllegalArgumentException("Unknown process: " + process);
14549 }
14550
14551 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14552 if (isSecure) {
14553 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14554 throw new SecurityException("Process not debuggable: " + proc);
14555 }
14556 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014557
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014558 proc.thread.profilerControl(start, path, fd);
14559 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014560 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014561 }
14562 } catch (RemoteException e) {
14563 throw new IllegalStateException("Process disappeared");
14564 } finally {
14565 if (fd != null) {
14566 try {
14567 fd.close();
14568 } catch (IOException e) {
14569 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014570 }
14571 }
14572 }
14573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014574 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14575 public void monitor() {
14576 synchronized (this) { }
14577 }
14578}