blob: d1edc350ef72c4bd298d7420fda830ee53c636f7 [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;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -070072import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.res.Configuration;
74import android.graphics.Bitmap;
75import android.net.Uri;
76import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080077import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080078import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070079import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080080import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080082import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083import android.os.FileUtils;
84import android.os.Handler;
85import android.os.IBinder;
86import android.os.IPermissionController;
87import android.os.Looper;
88import android.os.Message;
89import android.os.Parcel;
90import android.os.ParcelFileDescriptor;
91import android.os.PowerManager;
92import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070093import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.RemoteException;
95import android.os.ServiceManager;
96import android.os.SystemClock;
97import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.util.Config;
100import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800101import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800102import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.util.PrintWriterPrinter;
104import android.util.SparseArray;
105import android.view.Gravity;
106import android.view.LayoutInflater;
107import android.view.View;
108import android.view.WindowManager;
109import android.view.WindowManagerPolicy;
110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import java.io.File;
112import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200114import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800115import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116import java.io.PrintWriter;
117import java.lang.IllegalStateException;
118import java.lang.ref.WeakReference;
119import java.util.ArrayList;
120import java.util.HashMap;
121import java.util.HashSet;
122import java.util.Iterator;
123import java.util.List;
124import java.util.Locale;
125import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700126import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127
128public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
129 static final String TAG = "ActivityManager";
130 static final boolean DEBUG = false;
131 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
132 static final boolean DEBUG_SWITCH = localLOGV || false;
133 static final boolean DEBUG_TASKS = localLOGV || false;
134 static final boolean DEBUG_PAUSE = localLOGV || false;
135 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
136 static final boolean DEBUG_TRANSITION = localLOGV || false;
137 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700138 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 static final boolean DEBUG_SERVICE = localLOGV || false;
140 static final boolean DEBUG_VISBILITY = localLOGV || false;
141 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700142 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800143 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700145 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700146 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700147 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 static final boolean VALIDATE_TOKENS = false;
149 static final boolean SHOW_ACTIVITY_START_TIME = true;
150
151 // Control over CPU and battery monitoring.
152 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
153 static final boolean MONITOR_CPU_USAGE = true;
154 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
155 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
156 static final boolean MONITOR_THREAD_CPU_USAGE = false;
157
Dianne Hackborn1655be42009-05-08 14:29:01 -0700158 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700159 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 private static final String SYSTEM_SECURE = "ro.secure";
162
163 // This is the maximum number of application processes we would like
164 // to have running. Due to the asynchronous nature of things, we can
165 // temporarily go beyond this limit.
166 static final int MAX_PROCESSES = 2;
167
168 // Set to false to leave processes running indefinitely, relying on
169 // the kernel killing them as resources are required.
170 static final boolean ENFORCE_PROCESS_LIMIT = false;
171
172 // This is the maximum number of activities that we would like to have
173 // running at a given time.
174 static final int MAX_ACTIVITIES = 20;
175
176 // Maximum number of recent tasks that we can remember.
177 static final int MAX_RECENT_TASKS = 20;
178
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700179 // Amount of time after a call to stopAppSwitches() during which we will
180 // prevent further untrusted switches from happening.
181 static final long APP_SWITCH_DELAY_TIME = 5*1000;
182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 // How long until we reset a task when the user returns to it. Currently
184 // 30 minutes.
185 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
186
187 // Set to true to disable the icon that is shown while a new activity
188 // is being started.
189 static final boolean SHOW_APP_STARTING_ICON = true;
190
191 // How long we wait until giving up on the last activity to pause. This
192 // is short because it directly impacts the responsiveness of starting the
193 // next activity.
194 static final int PAUSE_TIMEOUT = 500;
195
196 /**
197 * How long we can hold the launch wake lock before giving up.
198 */
199 static final int LAUNCH_TIMEOUT = 10*1000;
200
201 // How long we wait for a launched process to attach to the activity manager
202 // before we decide it's never going to come up for real.
203 static final int PROC_START_TIMEOUT = 10*1000;
204
205 // How long we wait until giving up on the last activity telling us it
206 // is idle.
207 static final int IDLE_TIMEOUT = 10*1000;
208
209 // How long to wait after going idle before forcing apps to GC.
210 static final int GC_TIMEOUT = 5*1000;
211
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700212 // The minimum amount of time between successive GC requests for a process.
213 static final int GC_MIN_INTERVAL = 60*1000;
214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 // How long we wait until giving up on an activity telling us it has
216 // finished destroying itself.
217 static final int DESTROY_TIMEOUT = 10*1000;
218
219 // How long we allow a receiver to run before giving up on it.
220 static final int BROADCAST_TIMEOUT = 10*1000;
221
222 // How long we wait for a service to finish executing.
223 static final int SERVICE_TIMEOUT = 20*1000;
224
225 // How long a service needs to be running until restarting its process
226 // is no longer considered to be a relaunch of the service.
227 static final int SERVICE_RESTART_DURATION = 5*1000;
228
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700229 // How long a service needs to be running until it will start back at
230 // SERVICE_RESTART_DURATION after being killed.
231 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
232
233 // Multiplying factor to increase restart duration time by, for each time
234 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
235 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
236
237 // The minimum amount of time between restarting services that we allow.
238 // That is, when multiple services are restarting, we won't allow each
239 // to restart less than this amount of time from the last one.
240 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 // Maximum amount of time for there to be no activity on a service before
243 // we consider it non-essential and allow its process to go on the
244 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700245 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246
247 // How long we wait until we timeout on key dispatching.
248 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
249
250 // The minimum time we allow between crashes, for us to consider this
251 // application to be bad and stop and its services and reject broadcasts.
252 static final int MIN_CRASH_INTERVAL = 60*1000;
253
254 // How long we wait until we timeout on key dispatching during instrumentation.
255 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
256
257 // OOM adjustments for processes in various states:
258
259 // This is a process without anything currently running in it. Definitely
260 // the first to go! Value set in system/rootdir/init.rc on startup.
261 // This value is initalized in the constructor, careful when refering to
262 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800263 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264
265 // This is a process only hosting activities that are not visible,
266 // so it can be killed without any disruption. Value set in
267 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800268 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 static int HIDDEN_APP_MIN_ADJ;
270
The Android Open Source Project4df24232009-03-05 14:34:35 -0800271 // This is a process holding the home application -- we want to try
272 // avoiding killing it, even if it would normally be in the background,
273 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800274 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800275
Christopher Tate6fa95972009-06-05 18:43:55 -0700276 // This is a process currently hosting a backup operation. Killing it
277 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800278 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 // This is a process holding a secondary server -- killing it will not
281 // have much of an impact as far as the user is concerned. Value set in
282 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800283 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284
285 // This is a process only hosting activities that are visible to the
286 // user, so we'd prefer they don't disappear. Value set in
287 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800288 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289
290 // This is the process running the current foreground app. We'd really
291 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800292 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293
294 // This is a process running a core server, such as telephony. Definitely
295 // don't want to kill it, but doing so is not completely fatal.
296 static final int CORE_SERVER_ADJ = -12;
297
298 // The system process runs at the default adjustment.
299 static final int SYSTEM_ADJ = -16;
300
301 // Memory pages are 4K.
302 static final int PAGE_SIZE = 4*1024;
303
304 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800305 static final int EMPTY_APP_MEM;
306 static final int HIDDEN_APP_MEM;
307 static final int HOME_APP_MEM;
308 static final int BACKUP_APP_MEM;
309 static final int SECONDARY_SERVER_MEM;
310 static final int VISIBLE_APP_MEM;
311 static final int FOREGROUND_APP_MEM;
312
313 // The minimum number of hidden apps we want to be able to keep around,
314 // without empty apps being able to push them out of memory.
315 static final int MIN_HIDDEN_APPS = 2;
316
317 // We put empty content processes after any hidden processes that have
318 // been idle for less than 30 seconds.
319 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
320
321 // We put empty content processes after any hidden processes that have
322 // been idle for less than 60 seconds.
323 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
324
325 static {
326 // These values are set in system/rootdir/init.rc on startup.
327 FOREGROUND_APP_ADJ =
328 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
329 VISIBLE_APP_ADJ =
330 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
331 SECONDARY_SERVER_ADJ =
332 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
333 BACKUP_APP_ADJ =
334 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
335 HOME_APP_ADJ =
336 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
337 HIDDEN_APP_MIN_ADJ =
338 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
339 EMPTY_APP_ADJ =
340 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
341 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
342 FOREGROUND_APP_MEM =
343 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
344 VISIBLE_APP_MEM =
345 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
346 SECONDARY_SERVER_MEM =
347 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
348 BACKUP_APP_MEM =
349 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
350 HOME_APP_MEM =
351 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
352 HIDDEN_APP_MEM =
353 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
354 EMPTY_APP_MEM =
355 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357
Dan Egnor42471dd2010-01-07 17:25:22 -0800358 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359
360 static final String[] EMPTY_STRING_ARRAY = new String[0];
361
362 enum ActivityState {
363 INITIALIZING,
364 RESUMED,
365 PAUSING,
366 PAUSED,
367 STOPPING,
368 STOPPED,
369 FINISHING,
370 DESTROYING,
371 DESTROYED
372 }
373
374 /**
375 * The back history of all previous (and possibly still
376 * running) activities. It contains HistoryRecord objects.
377 */
378 final ArrayList mHistory = new ArrayList();
379
380 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700381 * Description of a request to start a new activity, which has been held
382 * due to app switches being disabled.
383 */
384 class PendingActivityLaunch {
385 HistoryRecord r;
386 HistoryRecord sourceRecord;
387 Uri[] grantedUriPermissions;
388 int grantedMode;
389 boolean onlyIfNeeded;
390 }
391
392 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
393 = new ArrayList<PendingActivityLaunch>();
394
395 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800396 * List of people waiting to find out about the next launched activity.
397 */
398 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
399 = new ArrayList<IActivityManager.WaitResult>();
400
401 /**
402 * List of people waiting to find out about the next visible activity.
403 */
404 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
405 = new ArrayList<IActivityManager.WaitResult>();
406
407 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * List of all active broadcasts that are to be executed immediately
409 * (without waiting for another broadcast to finish). Currently this only
410 * contains broadcasts to registered receivers, to avoid spinning up
411 * a bunch of processes to execute IntentReceiver components.
412 */
413 final ArrayList<BroadcastRecord> mParallelBroadcasts
414 = new ArrayList<BroadcastRecord>();
415
416 /**
417 * List of all active broadcasts that are to be executed one at a time.
418 * The object at the top of the list is the currently activity broadcasts;
419 * those after it are waiting for the top to finish..
420 */
421 final ArrayList<BroadcastRecord> mOrderedBroadcasts
422 = new ArrayList<BroadcastRecord>();
423
424 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800425 * Historical data of past broadcasts, for debugging.
426 */
427 static final int MAX_BROADCAST_HISTORY = 100;
428 final BroadcastRecord[] mBroadcastHistory
429 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
430
431 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 * Set when we current have a BROADCAST_INTENT_MSG in flight.
433 */
434 boolean mBroadcastsScheduled = false;
435
436 /**
437 * Set to indicate whether to issue an onUserLeaving callback when a
438 * newly launched activity is being brought in front of us.
439 */
440 boolean mUserLeaving = false;
441
442 /**
443 * When we are in the process of pausing an activity, before starting the
444 * next one, this variable holds the activity that is currently being paused.
445 */
446 HistoryRecord mPausingActivity = null;
447
448 /**
449 * Current activity that is resumed, or null if there is none.
450 */
451 HistoryRecord mResumedActivity = null;
452
453 /**
454 * Activity we have told the window manager to have key focus.
455 */
456 HistoryRecord mFocusedActivity = null;
457
458 /**
459 * This is the last activity that we put into the paused state. This is
460 * used to determine if we need to do an activity transition while sleeping,
461 * when we normally hold the top activity paused.
462 */
463 HistoryRecord mLastPausedActivity = null;
464
465 /**
466 * List of activities that are waiting for a new activity
467 * to become visible before completing whatever operation they are
468 * supposed to do.
469 */
470 final ArrayList mWaitingVisibleActivities = new ArrayList();
471
472 /**
473 * List of activities that are ready to be stopped, but waiting
474 * for the next activity to settle down before doing so. It contains
475 * HistoryRecord objects.
476 */
477 final ArrayList<HistoryRecord> mStoppingActivities
478 = new ArrayList<HistoryRecord>();
479
480 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700481 * Animations that for the current transition have requested not to
482 * be considered for the transition animation.
483 */
484 final ArrayList<HistoryRecord> mNoAnimActivities
485 = new ArrayList<HistoryRecord>();
486
487 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488 * List of intents that were used to start the most recent tasks.
489 */
490 final ArrayList<TaskRecord> mRecentTasks
491 = new ArrayList<TaskRecord>();
492
493 /**
494 * List of activities that are ready to be finished, but waiting
495 * for the previous activity to settle down before doing so. It contains
496 * HistoryRecord objects.
497 */
498 final ArrayList mFinishingActivities = new ArrayList();
499
500 /**
501 * All of the applications we currently have running organized by name.
502 * The keys are strings of the application package name (as
503 * returned by the package manager), and the keys are ApplicationRecord
504 * objects.
505 */
506 final ProcessMap<ProcessRecord> mProcessNames
507 = new ProcessMap<ProcessRecord>();
508
509 /**
510 * The last time that various processes have crashed.
511 */
512 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
513
514 /**
515 * Set of applications that we consider to be bad, and will reject
516 * incoming broadcasts from (which the user has no control over).
517 * Processes are added to this set when they have crashed twice within
518 * a minimum amount of time; they are removed from it when they are
519 * later restarted (hopefully due to some user action). The value is the
520 * time it was added to the list.
521 */
522 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
523
524 /**
525 * All of the processes we currently have running organized by pid.
526 * The keys are the pid running the application.
527 *
528 * <p>NOTE: This object is protected by its own lock, NOT the global
529 * activity manager lock!
530 */
531 final SparseArray<ProcessRecord> mPidsSelfLocked
532 = new SparseArray<ProcessRecord>();
533
534 /**
535 * All of the processes that have been forced to be foreground. The key
536 * is the pid of the caller who requested it (we hold a death
537 * link on it).
538 */
539 abstract class ForegroundToken implements IBinder.DeathRecipient {
540 int pid;
541 IBinder token;
542 }
543 final SparseArray<ForegroundToken> mForegroundProcesses
544 = new SparseArray<ForegroundToken>();
545
546 /**
547 * List of records for processes that someone had tried to start before the
548 * system was ready. We don't start them at that point, but ensure they
549 * are started by the time booting is complete.
550 */
551 final ArrayList<ProcessRecord> mProcessesOnHold
552 = new ArrayList<ProcessRecord>();
553
554 /**
555 * List of records for processes that we have started and are waiting
556 * for them to call back. This is really only needed when running in
557 * single processes mode, in which case we do not have a unique pid for
558 * each process.
559 */
560 final ArrayList<ProcessRecord> mStartingProcesses
561 = new ArrayList<ProcessRecord>();
562
563 /**
564 * List of persistent applications that are in the process
565 * of being started.
566 */
567 final ArrayList<ProcessRecord> mPersistentStartingProcesses
568 = new ArrayList<ProcessRecord>();
569
570 /**
571 * Processes that are being forcibly torn down.
572 */
573 final ArrayList<ProcessRecord> mRemovedProcesses
574 = new ArrayList<ProcessRecord>();
575
576 /**
577 * List of running applications, sorted by recent usage.
578 * The first entry in the list is the least recently used.
579 * It contains ApplicationRecord objects. This list does NOT include
580 * any persistent application records (since we never want to exit them).
581 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800582 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 = new ArrayList<ProcessRecord>();
584
585 /**
586 * List of processes that should gc as soon as things are idle.
587 */
588 final ArrayList<ProcessRecord> mProcessesToGc
589 = new ArrayList<ProcessRecord>();
590
591 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800592 * This is the process holding what we currently consider to be
593 * the "home" activity.
594 */
595 private ProcessRecord mHomeProcess;
596
597 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 * List of running activities, sorted by recent usage.
599 * The first entry in the list is the least recently used.
600 * It contains HistoryRecord objects.
601 */
602 private final ArrayList mLRUActivities = new ArrayList();
603
604 /**
605 * Set of PendingResultRecord objects that are currently active.
606 */
607 final HashSet mPendingResultRecords = new HashSet();
608
609 /**
610 * Set of IntentSenderRecord objects that are currently active.
611 */
612 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
613 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
614
615 /**
616 * Intent broadcast that we have tried to start, but are
617 * waiting for its application's process to be created. We only
618 * need one (instead of a list) because we always process broadcasts
619 * one at a time, so no others can be started while waiting for this
620 * one.
621 */
622 BroadcastRecord mPendingBroadcast = null;
623
624 /**
625 * Keeps track of all IIntentReceivers that have been registered for
626 * broadcasts. Hash keys are the receiver IBinder, hash value is
627 * a ReceiverList.
628 */
629 final HashMap mRegisteredReceivers = new HashMap();
630
631 /**
632 * Resolver for broadcast intents to registered receivers.
633 * Holds BroadcastFilter (subclass of IntentFilter).
634 */
635 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
636 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
637 @Override
638 protected boolean allowFilterResult(
639 BroadcastFilter filter, List<BroadcastFilter> dest) {
640 IBinder target = filter.receiverList.receiver.asBinder();
641 for (int i=dest.size()-1; i>=0; i--) {
642 if (dest.get(i).receiverList.receiver.asBinder() == target) {
643 return false;
644 }
645 }
646 return true;
647 }
648 };
649
650 /**
651 * State of all active sticky broadcasts. Keys are the action of the
652 * sticky Intent, values are an ArrayList of all broadcasted intents with
653 * that action (which should usually be one).
654 */
655 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
656 new HashMap<String, ArrayList<Intent>>();
657
658 /**
659 * All currently running services.
660 */
661 final HashMap<ComponentName, ServiceRecord> mServices =
662 new HashMap<ComponentName, ServiceRecord>();
663
664 /**
665 * All currently running services indexed by the Intent used to start them.
666 */
667 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
668 new HashMap<Intent.FilterComparison, ServiceRecord>();
669
670 /**
671 * All currently bound service connections. Keys are the IBinder of
672 * the client's IServiceConnection.
673 */
674 final HashMap<IBinder, ConnectionRecord> mServiceConnections
675 = new HashMap<IBinder, ConnectionRecord>();
676
677 /**
678 * List of services that we have been asked to start,
679 * but haven't yet been able to. It is used to hold start requests
680 * while waiting for their corresponding application thread to get
681 * going.
682 */
683 final ArrayList<ServiceRecord> mPendingServices
684 = new ArrayList<ServiceRecord>();
685
686 /**
687 * List of services that are scheduled to restart following a crash.
688 */
689 final ArrayList<ServiceRecord> mRestartingServices
690 = new ArrayList<ServiceRecord>();
691
692 /**
693 * List of services that are in the process of being stopped.
694 */
695 final ArrayList<ServiceRecord> mStoppingServices
696 = new ArrayList<ServiceRecord>();
697
698 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700699 * Backup/restore process management
700 */
701 String mBackupAppName = null;
702 BackupRecord mBackupTarget = null;
703
704 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 * List of PendingThumbnailsRecord objects of clients who are still
706 * waiting to receive all of the thumbnails for a task.
707 */
708 final ArrayList mPendingThumbnails = new ArrayList();
709
710 /**
711 * List of HistoryRecord objects that have been finished and must
712 * still report back to a pending thumbnail receiver.
713 */
714 final ArrayList mCancelledThumbnails = new ArrayList();
715
716 /**
717 * All of the currently running global content providers. Keys are a
718 * string containing the provider name and values are a
719 * ContentProviderRecord object containing the data about it. Note
720 * that a single provider may be published under multiple names, so
721 * there may be multiple entries here for a single one in mProvidersByClass.
722 */
723 final HashMap mProvidersByName = new HashMap();
724
725 /**
726 * All of the currently running global content providers. Keys are a
727 * string containing the provider's implementation class and values are a
728 * ContentProviderRecord object containing the data about it.
729 */
730 final HashMap mProvidersByClass = new HashMap();
731
732 /**
733 * List of content providers who have clients waiting for them. The
734 * application is currently being launched and the provider will be
735 * removed from this list once it is published.
736 */
737 final ArrayList mLaunchingProviders = new ArrayList();
738
739 /**
740 * Global set of specific Uri permissions that have been granted.
741 */
742 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
743 = new SparseArray<HashMap<Uri, UriPermission>>();
744
745 /**
746 * Thread-local storage used to carry caller permissions over through
747 * indirect content-provider access.
748 * @see #ActivityManagerService.openContentUri()
749 */
750 private class Identity {
751 public int pid;
752 public int uid;
753
754 Identity(int _pid, int _uid) {
755 pid = _pid;
756 uid = _uid;
757 }
758 }
759 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
760
761 /**
762 * All information we have collected about the runtime performance of
763 * any user id that can impact battery performance.
764 */
765 final BatteryStatsService mBatteryStatsService;
766
767 /**
768 * information about component usage
769 */
770 final UsageStatsService mUsageStatsService;
771
772 /**
773 * Current configuration information. HistoryRecord objects are given
774 * a reference to this object to indicate which configuration they are
775 * currently running in, so this object must be kept immutable.
776 */
777 Configuration mConfiguration = new Configuration();
778
779 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800780 * Current sequencing integer of the configuration, for skipping old
781 * configurations.
782 */
783 int mConfigurationSeq = 0;
784
785 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700786 * Hardware-reported OpenGLES version.
787 */
788 final int GL_ES_VERSION;
789
790 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 * List of initialization arguments to pass to all processes when binding applications to them.
792 * For example, references to the commonly used services.
793 */
794 HashMap<String, IBinder> mAppBindArgs;
795
796 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700797 * Temporary to avoid allocations. Protected by main lock.
798 */
799 final StringBuilder mStringBuilder = new StringBuilder(256);
800
801 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 * Used to control how we initialize the service.
803 */
804 boolean mStartRunning = false;
805 ComponentName mTopComponent;
806 String mTopAction;
807 String mTopData;
808 boolean mSystemReady = false;
809 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700810 boolean mWaitingUpdate = false;
811 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812
813 Context mContext;
814
815 int mFactoryTest;
816
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700817 boolean mCheckedForSetup;
818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700820 * The time at which we will allow normal application switches again,
821 * after a call to {@link #stopAppSwitches()}.
822 */
823 long mAppSwitchesAllowedTime;
824
825 /**
826 * This is set to true after the first switch after mAppSwitchesAllowedTime
827 * is set; any switches after that will clear the time.
828 */
829 boolean mDidAppSwitch;
830
831 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 * Set while we are wanting to sleep, to prevent any
833 * activities from being started/resumed.
834 */
835 boolean mSleeping = false;
836
837 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700838 * Set if we are shutting down the system, similar to sleeping.
839 */
840 boolean mShuttingDown = false;
841
842 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 * Set when the system is going to sleep, until we have
844 * successfully paused the current activity and released our wake lock.
845 * At that point the system is allowed to actually sleep.
846 */
847 PowerManager.WakeLock mGoingToSleep;
848
849 /**
850 * We don't want to allow the device to go to sleep while in the process
851 * of launching an activity. This is primarily to allow alarm intent
852 * receivers to launch an activity and get that to run before the device
853 * goes back to sleep.
854 */
855 PowerManager.WakeLock mLaunchingActivity;
856
857 /**
858 * Task identifier that activities are currently being started
859 * in. Incremented each time a new task is created.
860 * todo: Replace this with a TokenSpace class that generates non-repeating
861 * integers that won't wrap.
862 */
863 int mCurTask = 1;
864
865 /**
866 * Current sequence id for oom_adj computation traversal.
867 */
868 int mAdjSeq = 0;
869
870 /**
871 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
872 * is set, indicating the user wants processes started in such a way
873 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
874 * running in each process (thus no pre-initialized process, etc).
875 */
876 boolean mSimpleProcessManagement = false;
877
878 /**
879 * System monitoring: number of processes that died since the last
880 * N procs were started.
881 */
882 int[] mProcDeaths = new int[20];
883
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700884 /**
885 * This is set if we had to do a delayed dexopt of an app before launching
886 * it, to increasing the ANR timeouts in that case.
887 */
888 boolean mDidDexOpt;
889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 String mDebugApp = null;
891 boolean mWaitForDebugger = false;
892 boolean mDebugTransient = false;
893 String mOrigDebugApp = null;
894 boolean mOrigWaitForDebugger = false;
895 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700896 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700898 final RemoteCallbackList<IActivityWatcher> mWatchers
899 = new RemoteCallbackList<IActivityWatcher>();
900
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 /**
902 * Callback of last caller to {@link #requestPss}.
903 */
904 Runnable mRequestPssCallback;
905
906 /**
907 * Remaining processes for which we are waiting results from the last
908 * call to {@link #requestPss}.
909 */
910 final ArrayList<ProcessRecord> mRequestPssList
911 = new ArrayList<ProcessRecord>();
912
913 /**
914 * Runtime statistics collection thread. This object's lock is used to
915 * protect all related state.
916 */
917 final Thread mProcessStatsThread;
918
919 /**
920 * Used to collect process stats when showing not responding dialog.
921 * Protected by mProcessStatsThread.
922 */
923 final ProcessStats mProcessStats = new ProcessStats(
924 MONITOR_THREAD_CPU_USAGE);
925 long mLastCpuTime = 0;
926 long mLastWriteTime = 0;
927
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700928 long mInitialStartTime = 0;
929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 /**
931 * Set to true after the system has finished booting.
932 */
933 boolean mBooted = false;
934
935 int mProcessLimit = 0;
936
937 WindowManagerService mWindowManager;
938
939 static ActivityManagerService mSelf;
940 static ActivityThread mSystemThread;
941
942 private final class AppDeathRecipient implements IBinder.DeathRecipient {
943 final ProcessRecord mApp;
944 final int mPid;
945 final IApplicationThread mAppThread;
946
947 AppDeathRecipient(ProcessRecord app, int pid,
948 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800949 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 TAG, "New death recipient " + this
951 + " for thread " + thread.asBinder());
952 mApp = app;
953 mPid = pid;
954 mAppThread = thread;
955 }
956
957 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800958 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 TAG, "Death received in " + this
960 + " for thread " + mAppThread.asBinder());
961 removeRequestedPss(mApp);
962 synchronized(ActivityManagerService.this) {
963 appDiedLocked(mApp, mPid, mAppThread);
964 }
965 }
966 }
967
968 static final int SHOW_ERROR_MSG = 1;
969 static final int SHOW_NOT_RESPONDING_MSG = 2;
970 static final int SHOW_FACTORY_ERROR_MSG = 3;
971 static final int UPDATE_CONFIGURATION_MSG = 4;
972 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
973 static final int WAIT_FOR_DEBUGGER_MSG = 6;
974 static final int BROADCAST_INTENT_MSG = 7;
975 static final int BROADCAST_TIMEOUT_MSG = 8;
976 static final int PAUSE_TIMEOUT_MSG = 9;
977 static final int IDLE_TIMEOUT_MSG = 10;
978 static final int IDLE_NOW_MSG = 11;
979 static final int SERVICE_TIMEOUT_MSG = 12;
980 static final int UPDATE_TIME_ZONE = 13;
981 static final int SHOW_UID_ERROR_MSG = 14;
982 static final int IM_FEELING_LUCKY_MSG = 15;
983 static final int LAUNCH_TIMEOUT_MSG = 16;
984 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800985 static final int RESUME_TOP_ACTIVITY_MSG = 19;
986 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700987 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700988 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800989 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990
991 AlertDialog mUidAlert;
992
993 final Handler mHandler = new Handler() {
994 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800995 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 //}
997
998 public void handleMessage(Message msg) {
999 switch (msg.what) {
1000 case SHOW_ERROR_MSG: {
1001 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 synchronized (ActivityManagerService.this) {
1003 ProcessRecord proc = (ProcessRecord)data.get("app");
1004 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001005 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 return;
1007 }
1008 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001009 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001010 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 d.show();
1012 proc.crashDialog = d;
1013 } else {
1014 // The device is asleep, so just pretend that the user
1015 // saw a crash dialog and hit "force quit".
1016 res.set(0);
1017 }
1018 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001019
1020 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 } break;
1022 case SHOW_NOT_RESPONDING_MSG: {
1023 synchronized (ActivityManagerService.this) {
1024 HashMap data = (HashMap) msg.obj;
1025 ProcessRecord proc = (ProcessRecord)data.get("app");
1026 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001027 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001028 return;
1029 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001030
1031 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1032 null, null, 0, null, null, null,
1033 false, false, MY_PID, Process.SYSTEM_UID);
1034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1036 mContext, proc, (HistoryRecord)data.get("activity"));
1037 d.show();
1038 proc.anrDialog = d;
1039 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001040
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001041 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 } break;
1043 case SHOW_FACTORY_ERROR_MSG: {
1044 Dialog d = new FactoryErrorDialog(
1045 mContext, msg.getData().getCharSequence("msg"));
1046 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001047 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 } break;
1049 case UPDATE_CONFIGURATION_MSG: {
1050 final ContentResolver resolver = mContext.getContentResolver();
1051 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1052 } break;
1053 case GC_BACKGROUND_PROCESSES_MSG: {
1054 synchronized (ActivityManagerService.this) {
1055 performAppGcsIfAppropriateLocked();
1056 }
1057 } break;
1058 case WAIT_FOR_DEBUGGER_MSG: {
1059 synchronized (ActivityManagerService.this) {
1060 ProcessRecord app = (ProcessRecord)msg.obj;
1061 if (msg.arg1 != 0) {
1062 if (!app.waitedForDebugger) {
1063 Dialog d = new AppWaitingForDebuggerDialog(
1064 ActivityManagerService.this,
1065 mContext, app);
1066 app.waitDialog = d;
1067 app.waitedForDebugger = true;
1068 d.show();
1069 }
1070 } else {
1071 if (app.waitDialog != null) {
1072 app.waitDialog.dismiss();
1073 app.waitDialog = null;
1074 }
1075 }
1076 }
1077 } break;
1078 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001079 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 TAG, "Received BROADCAST_INTENT_MSG");
1081 processNextBroadcast(true);
1082 } break;
1083 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001084 if (mDidDexOpt) {
1085 mDidDexOpt = false;
1086 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1087 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1088 return;
1089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 broadcastTimeout();
1091 } break;
1092 case PAUSE_TIMEOUT_MSG: {
1093 IBinder token = (IBinder)msg.obj;
1094 // We don't at this point know if the activity is fullscreen,
1095 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001096 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 activityPaused(token, null, true);
1098 } break;
1099 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001100 if (mDidDexOpt) {
1101 mDidDexOpt = false;
1102 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1103 nmsg.obj = msg.obj;
1104 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1105 return;
1106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 // We don't at this point know if the activity is fullscreen,
1108 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001109 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001110 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001111 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 } break;
1113 case DESTROY_TIMEOUT_MSG: {
1114 IBinder token = (IBinder)msg.obj;
1115 // We don't at this point know if the activity is fullscreen,
1116 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001117 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 activityDestroyed(token);
1119 } break;
1120 case IDLE_NOW_MSG: {
1121 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001122 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123 } break;
1124 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001125 if (mDidDexOpt) {
1126 mDidDexOpt = false;
1127 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1128 nmsg.obj = msg.obj;
1129 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1130 return;
1131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 serviceTimeout((ProcessRecord)msg.obj);
1133 } break;
1134 case UPDATE_TIME_ZONE: {
1135 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001136 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1137 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 if (r.thread != null) {
1139 try {
1140 r.thread.updateTimeZone();
1141 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001142 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143 }
1144 }
1145 }
1146 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001147 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 case SHOW_UID_ERROR_MSG: {
1149 // XXX This is a temporary dialog, no need to localize.
1150 AlertDialog d = new BaseErrorDialog(mContext);
1151 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1152 d.setCancelable(false);
1153 d.setTitle("System UIDs Inconsistent");
1154 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1155 d.setButton("I'm Feeling Lucky",
1156 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1157 mUidAlert = d;
1158 d.show();
1159 } break;
1160 case IM_FEELING_LUCKY_MSG: {
1161 if (mUidAlert != null) {
1162 mUidAlert.dismiss();
1163 mUidAlert = null;
1164 }
1165 } break;
1166 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001167 if (mDidDexOpt) {
1168 mDidDexOpt = false;
1169 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1170 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1171 return;
1172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 synchronized (ActivityManagerService.this) {
1174 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001175 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 mLaunchingActivity.release();
1177 }
1178 }
1179 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 case RESUME_TOP_ACTIVITY_MSG: {
1181 synchronized (ActivityManagerService.this) {
1182 resumeTopActivityLocked(null);
1183 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001184 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001186 if (mDidDexOpt) {
1187 mDidDexOpt = false;
1188 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1189 nmsg.obj = msg.obj;
1190 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1191 return;
1192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 ProcessRecord app = (ProcessRecord)msg.obj;
1194 synchronized (ActivityManagerService.this) {
1195 processStartTimedOutLocked(app);
1196 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001197 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001198 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1199 synchronized (ActivityManagerService.this) {
1200 doPendingActivityLaunchesLocked(true);
1201 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001202 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001203 case KILL_APPLICATION_MSG: {
1204 synchronized (ActivityManagerService.this) {
1205 int uid = msg.arg1;
1206 boolean restart = (msg.arg2 == 1);
1207 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001208 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001209 }
1210 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001211 case FINALIZE_PENDING_INTENT_MSG: {
1212 ((PendingIntentRecord)msg.obj).completeFinalize();
1213 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 }
1215 }
1216 };
1217
1218 public static void setSystemProcess() {
1219 try {
1220 ActivityManagerService m = mSelf;
1221
1222 ServiceManager.addService("activity", m);
1223 ServiceManager.addService("meminfo", new MemBinder(m));
1224 if (MONITOR_CPU_USAGE) {
1225 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 ServiceManager.addService("permission", new PermissionController(m));
1228
1229 ApplicationInfo info =
1230 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001231 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001232 mSystemThread.installSystemApplicationInfo(info);
1233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 synchronized (mSelf) {
1235 ProcessRecord app = mSelf.newProcessRecordLocked(
1236 mSystemThread.getApplicationThread(), info,
1237 info.processName);
1238 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001239 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 app.maxAdj = SYSTEM_ADJ;
1241 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1242 synchronized (mSelf.mPidsSelfLocked) {
1243 mSelf.mPidsSelfLocked.put(app.pid, app);
1244 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001245 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001246 }
1247 } catch (PackageManager.NameNotFoundException e) {
1248 throw new RuntimeException(
1249 "Unable to find android system package", e);
1250 }
1251 }
1252
1253 public void setWindowManager(WindowManagerService wm) {
1254 mWindowManager = wm;
1255 }
1256
1257 public static final Context main(int factoryTest) {
1258 AThread thr = new AThread();
1259 thr.start();
1260
1261 synchronized (thr) {
1262 while (thr.mService == null) {
1263 try {
1264 thr.wait();
1265 } catch (InterruptedException e) {
1266 }
1267 }
1268 }
1269
1270 ActivityManagerService m = thr.mService;
1271 mSelf = m;
1272 ActivityThread at = ActivityThread.systemMain();
1273 mSystemThread = at;
1274 Context context = at.getSystemContext();
1275 m.mContext = context;
1276 m.mFactoryTest = factoryTest;
1277 PowerManager pm =
1278 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1279 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1280 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1281 m.mLaunchingActivity.setReferenceCounted(false);
1282
1283 m.mBatteryStatsService.publish(context);
1284 m.mUsageStatsService.publish(context);
1285
1286 synchronized (thr) {
1287 thr.mReady = true;
1288 thr.notifyAll();
1289 }
1290
1291 m.startRunning(null, null, null, null);
1292
1293 return context;
1294 }
1295
1296 public static ActivityManagerService self() {
1297 return mSelf;
1298 }
1299
1300 static class AThread extends Thread {
1301 ActivityManagerService mService;
1302 boolean mReady = false;
1303
1304 public AThread() {
1305 super("ActivityManager");
1306 }
1307
1308 public void run() {
1309 Looper.prepare();
1310
1311 android.os.Process.setThreadPriority(
1312 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1313
1314 ActivityManagerService m = new ActivityManagerService();
1315
1316 synchronized (this) {
1317 mService = m;
1318 notifyAll();
1319 }
1320
1321 synchronized (this) {
1322 while (!mReady) {
1323 try {
1324 wait();
1325 } catch (InterruptedException e) {
1326 }
1327 }
1328 }
1329
1330 Looper.loop();
1331 }
1332 }
1333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 static class MemBinder extends Binder {
1335 ActivityManagerService mActivityManagerService;
1336 MemBinder(ActivityManagerService activityManagerService) {
1337 mActivityManagerService = activityManagerService;
1338 }
1339
1340 @Override
1341 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1342 ActivityManagerService service = mActivityManagerService;
1343 ArrayList<ProcessRecord> procs;
1344 synchronized (mActivityManagerService) {
1345 if (args != null && args.length > 0
1346 && args[0].charAt(0) != '-') {
1347 procs = new ArrayList<ProcessRecord>();
1348 int pid = -1;
1349 try {
1350 pid = Integer.parseInt(args[0]);
1351 } catch (NumberFormatException e) {
1352
1353 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001354 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1355 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 if (proc.pid == pid) {
1357 procs.add(proc);
1358 } else if (proc.processName.equals(args[0])) {
1359 procs.add(proc);
1360 }
1361 }
1362 if (procs.size() <= 0) {
1363 pw.println("No process found for: " + args[0]);
1364 return;
1365 }
1366 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001367 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 }
1369 }
1370 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1371 }
1372 }
1373
1374 static class CpuBinder extends Binder {
1375 ActivityManagerService mActivityManagerService;
1376 CpuBinder(ActivityManagerService activityManagerService) {
1377 mActivityManagerService = activityManagerService;
1378 }
1379
1380 @Override
1381 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1382 synchronized (mActivityManagerService.mProcessStatsThread) {
1383 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1384 }
1385 }
1386 }
1387
1388 private ActivityManagerService() {
1389 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1390 if (v != null && Integer.getInteger(v) != 0) {
1391 mSimpleProcessManagement = true;
1392 }
1393 v = System.getenv("ANDROID_DEBUG_APP");
1394 if (v != null) {
1395 mSimpleProcessManagement = true;
1396 }
1397
Joe Onorato8a9b2202010-02-26 18:56:32 -08001398 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 File dataDir = Environment.getDataDirectory();
1401 File systemDir = new File(dataDir, "system");
1402 systemDir.mkdirs();
1403 mBatteryStatsService = new BatteryStatsService(new File(
1404 systemDir, "batterystats.bin").toString());
1405 mBatteryStatsService.getActiveStatistics().readLocked();
1406 mBatteryStatsService.getActiveStatistics().writeLocked();
1407
1408 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001409 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410
Jack Palevichb90d28c2009-07-22 15:35:24 -07001411 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1412 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1413
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001414 mConfiguration.setToDefaults();
1415 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 mProcessStats.init();
1417
1418 // Add ourself to the Watchdog monitors.
1419 Watchdog.getInstance().addMonitor(this);
1420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 mProcessStatsThread = new Thread("ProcessStats") {
1422 public void run() {
1423 while (true) {
1424 try {
1425 try {
1426 synchronized(this) {
1427 final long now = SystemClock.uptimeMillis();
1428 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1429 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001430 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 // + ", write delay=" + nextWriteDelay);
1432 if (nextWriteDelay < nextCpuDelay) {
1433 nextCpuDelay = nextWriteDelay;
1434 }
1435 if (nextCpuDelay > 0) {
1436 this.wait(nextCpuDelay);
1437 }
1438 }
1439 } catch (InterruptedException e) {
1440 }
1441
1442 updateCpuStatsNow();
1443 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001444 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 }
1446 }
1447 }
1448 };
1449 mProcessStatsThread.start();
1450 }
1451
1452 @Override
1453 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1454 throws RemoteException {
1455 try {
1456 return super.onTransact(code, data, reply, flags);
1457 } catch (RuntimeException e) {
1458 // The activity manager only throws security exceptions, so let's
1459 // log all others.
1460 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001461 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 }
1463 throw e;
1464 }
1465 }
1466
1467 void updateCpuStats() {
1468 synchronized (mProcessStatsThread) {
1469 final long now = SystemClock.uptimeMillis();
1470 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1471 mProcessStatsThread.notify();
1472 }
1473 }
1474 }
1475
1476 void updateCpuStatsNow() {
1477 synchronized (mProcessStatsThread) {
1478 final long now = SystemClock.uptimeMillis();
1479 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 if (MONITOR_CPU_USAGE &&
1482 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1483 mLastCpuTime = now;
1484 haveNewCpuStats = true;
1485 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001486 //Slog.i(TAG, mProcessStats.printCurrentState());
1487 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 // + mProcessStats.getTotalCpuPercent() + "%");
1489
Joe Onorato8a9b2202010-02-26 18:56:32 -08001490 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 if ("true".equals(SystemProperties.get("events.cpu"))) {
1492 int user = mProcessStats.getLastUserTime();
1493 int system = mProcessStats.getLastSystemTime();
1494 int iowait = mProcessStats.getLastIoWaitTime();
1495 int irq = mProcessStats.getLastIrqTime();
1496 int softIrq = mProcessStats.getLastSoftIrqTime();
1497 int idle = mProcessStats.getLastIdleTime();
1498
1499 int total = user + system + iowait + irq + softIrq + idle;
1500 if (total == 0) total = 1;
1501
Doug Zongker2bec3d42009-12-04 12:52:44 -08001502 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 ((user+system+iowait+irq+softIrq) * 100) / total,
1504 (user * 100) / total,
1505 (system * 100) / total,
1506 (iowait * 100) / total,
1507 (irq * 100) / total,
1508 (softIrq * 100) / total);
1509 }
1510 }
1511
Amith Yamasanie43530a2009-08-21 13:11:37 -07001512 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001513 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001514 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 synchronized(mPidsSelfLocked) {
1516 if (haveNewCpuStats) {
1517 if (mBatteryStatsService.isOnBattery()) {
1518 final int N = mProcessStats.countWorkingStats();
1519 for (int i=0; i<N; i++) {
1520 ProcessStats.Stats st
1521 = mProcessStats.getWorkingStats(i);
1522 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1523 if (pr != null) {
1524 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1525 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001526 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001527 } else {
1528 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001529 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001530 if (ps != null) {
1531 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001532 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 }
1535 }
1536 }
1537 }
1538 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1541 mLastWriteTime = now;
1542 mBatteryStatsService.getActiveStatistics().writeLocked();
1543 }
1544 }
1545 }
1546 }
1547
1548 /**
1549 * Initialize the application bind args. These are passed to each
1550 * process when the bindApplication() IPC is sent to the process. They're
1551 * lazily setup to make sure the services are running when they're asked for.
1552 */
1553 private HashMap<String, IBinder> getCommonServicesLocked() {
1554 if (mAppBindArgs == null) {
1555 mAppBindArgs = new HashMap<String, IBinder>();
1556
1557 // Setup the application init args
1558 mAppBindArgs.put("package", ServiceManager.getService("package"));
1559 mAppBindArgs.put("window", ServiceManager.getService("window"));
1560 mAppBindArgs.put(Context.ALARM_SERVICE,
1561 ServiceManager.getService(Context.ALARM_SERVICE));
1562 }
1563 return mAppBindArgs;
1564 }
1565
1566 private final void setFocusedActivityLocked(HistoryRecord r) {
1567 if (mFocusedActivity != r) {
1568 mFocusedActivity = r;
1569 mWindowManager.setFocusedApp(r, true);
1570 }
1571 }
1572
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001573 private final void updateLruProcessLocked(ProcessRecord app,
1574 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001576 int lrui = mLruProcesses.indexOf(app);
1577 if (lrui >= 0) mLruProcesses.remove(lrui);
1578
1579 int i = mLruProcesses.size()-1;
1580 int skipTop = 0;
1581
1582 // compute the new weight for this process.
1583 if (updateActivityTime) {
1584 app.lastActivityTime = SystemClock.uptimeMillis();
1585 }
1586 if (app.activities.size() > 0) {
1587 // If this process has activities, we more strongly want to keep
1588 // it around.
1589 app.lruWeight = app.lastActivityTime;
1590 } else if (app.pubProviders.size() > 0) {
1591 // If this process contains content providers, we want to keep
1592 // it a little more strongly.
1593 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1594 // Also don't let it kick out the first few "real" hidden processes.
1595 skipTop = MIN_HIDDEN_APPS;
1596 } else {
1597 // If this process doesn't have activities, we less strongly
1598 // want to keep it around, and generally want to avoid getting
1599 // in front of any very recently used activities.
1600 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1601 // Also don't let it kick out the first few "real" hidden processes.
1602 skipTop = MIN_HIDDEN_APPS;
1603 }
1604 while (i >= 0) {
1605 ProcessRecord p = mLruProcesses.get(i);
1606 // If this app shouldn't be in front of the first N background
1607 // apps, then skip over that many that are currently hidden.
1608 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1609 skipTop--;
1610 }
1611 if (p.lruWeight <= app.lruWeight){
1612 mLruProcesses.add(i+1, app);
1613 break;
1614 }
1615 i--;
1616 }
1617 if (i < 0) {
1618 mLruProcesses.add(0, app);
1619 }
1620
Joe Onorato8a9b2202010-02-26 18:56:32 -08001621 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 if (oomAdj) {
1623 updateOomAdjLocked();
1624 }
1625 }
1626
1627 private final boolean updateLRUListLocked(HistoryRecord r) {
1628 final boolean hadit = mLRUActivities.remove(r);
1629 mLRUActivities.add(r);
1630 return hadit;
1631 }
1632
1633 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1634 int i = mHistory.size()-1;
1635 while (i >= 0) {
1636 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1637 if (!r.finishing && r != notTop) {
1638 return r;
1639 }
1640 i--;
1641 }
1642 return null;
1643 }
1644
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001645 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1646 int i = mHistory.size()-1;
1647 while (i >= 0) {
1648 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1649 if (!r.finishing && !r.delayedResume && r != notTop) {
1650 return r;
1651 }
1652 i--;
1653 }
1654 return null;
1655 }
1656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 /**
1658 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001659 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 *
1661 * @param token If non-null, any history records matching this token will be skipped.
1662 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1663 *
1664 * @return Returns the HistoryRecord of the next activity on the stack.
1665 */
1666 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1667 int i = mHistory.size()-1;
1668 while (i >= 0) {
1669 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1670 // Note: the taskId check depends on real taskId fields being non-zero
1671 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1672 return r;
1673 }
1674 i--;
1675 }
1676 return null;
1677 }
1678
1679 private final ProcessRecord getProcessRecordLocked(
1680 String processName, int uid) {
1681 if (uid == Process.SYSTEM_UID) {
1682 // The system gets to run in any process. If there are multiple
1683 // processes with the same uid, just pick the first (this
1684 // should never happen).
1685 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1686 processName);
1687 return procs != null ? procs.valueAt(0) : null;
1688 }
1689 ProcessRecord proc = mProcessNames.get(processName, uid);
1690 return proc;
1691 }
1692
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001693 private void ensurePackageDexOpt(String packageName) {
1694 IPackageManager pm = ActivityThread.getPackageManager();
1695 try {
1696 if (pm.performDexOpt(packageName)) {
1697 mDidDexOpt = true;
1698 }
1699 } catch (RemoteException e) {
1700 }
1701 }
1702
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703 private boolean isNextTransitionForward() {
1704 int transit = mWindowManager.getPendingAppTransition();
1705 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1706 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1707 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1708 }
1709
1710 private final boolean realStartActivityLocked(HistoryRecord r,
1711 ProcessRecord app, boolean andResume, boolean checkConfig)
1712 throws RemoteException {
1713
1714 r.startFreezingScreenLocked(app, 0);
1715 mWindowManager.setAppVisibility(r, true);
1716
1717 // Have the window manager re-evaluate the orientation of
1718 // the screen based on the new activity order. Note that
1719 // as a result of this, it can call back into the activity
1720 // manager with a new orientation. We don't care about that,
1721 // because the activity is not currently running so we are
1722 // just restarting it anyway.
1723 if (checkConfig) {
1724 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001725 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 r.mayFreezeScreenLocked(app) ? r : null);
1727 updateConfigurationLocked(config, r);
1728 }
1729
1730 r.app = app;
1731
Joe Onorato8a9b2202010-02-26 18:56:32 -08001732 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733
1734 int idx = app.activities.indexOf(r);
1735 if (idx < 0) {
1736 app.activities.add(r);
1737 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001738 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739
1740 try {
1741 if (app.thread == null) {
1742 throw new RemoteException();
1743 }
1744 List<ResultInfo> results = null;
1745 List<Intent> newIntents = null;
1746 if (andResume) {
1747 results = r.results;
1748 newIntents = r.newIntents;
1749 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001750 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 + " icicle=" + r.icicle
1752 + " with results=" + results + " newIntents=" + newIntents
1753 + " andResume=" + andResume);
1754 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001755 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 System.identityHashCode(r),
1757 r.task.taskId, r.shortComponentName);
1758 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001759 if (r.isHomeActivity) {
1760 mHomeProcess = app;
1761 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001762 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001764 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 r.info, r.icicle, results, newIntents, !andResume,
1766 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 } catch (RemoteException e) {
1768 if (r.launchFailed) {
1769 // This is the second time we failed -- finish activity
1770 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001771 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 + r.intent.getComponent().flattenToShortString()
1773 + ", giving up", e);
1774 appDiedLocked(app, app.pid, app.thread);
1775 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1776 "2nd-crash");
1777 return false;
1778 }
1779
1780 // This is the first time we failed -- restart process and
1781 // retry.
1782 app.activities.remove(r);
1783 throw e;
1784 }
1785
1786 r.launchFailed = false;
1787 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001788 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 + " being launched, but already in LRU list");
1790 }
1791
1792 if (andResume) {
1793 // As part of the process of launching, ActivityThread also performs
1794 // a resume.
1795 r.state = ActivityState.RESUMED;
1796 r.icicle = null;
1797 r.haveState = false;
1798 r.stopped = false;
1799 mResumedActivity = r;
1800 r.task.touchActiveTime();
1801 completeResumeLocked(r);
1802 pauseIfSleepingLocked();
1803 } else {
1804 // This activity is not starting in the resumed state... which
1805 // should look like we asked it to pause+stop (but remain visible),
1806 // and it has done so and reported back the current icicle and
1807 // other state.
1808 r.state = ActivityState.STOPPED;
1809 r.stopped = true;
1810 }
1811
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001812 // Launch the new version setup screen if needed. We do this -after-
1813 // launching the initial activity (that is, home), so that it can have
1814 // a chance to initialize itself while in the background, making the
1815 // switch back to it faster and look better.
1816 startSetupActivityLocked();
1817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 return true;
1819 }
1820
1821 private final void startSpecificActivityLocked(HistoryRecord r,
1822 boolean andResume, boolean checkConfig) {
1823 // Is this activity's application already running?
1824 ProcessRecord app = getProcessRecordLocked(r.processName,
1825 r.info.applicationInfo.uid);
1826
1827 if (r.startTime == 0) {
1828 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001829 if (mInitialStartTime == 0) {
1830 mInitialStartTime = r.startTime;
1831 }
1832 } else if (mInitialStartTime == 0) {
1833 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001834 }
1835
1836 if (app != null && app.thread != null) {
1837 try {
1838 realStartActivityLocked(r, app, andResume, checkConfig);
1839 return;
1840 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001841 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001842 + r.intent.getComponent().flattenToShortString(), e);
1843 }
1844
1845 // If a dead object exception was thrown -- fall through to
1846 // restart the application.
1847 }
1848
1849 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001850 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 }
1852
1853 private final ProcessRecord startProcessLocked(String processName,
1854 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001855 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1857 // We don't have to do anything more if:
1858 // (1) There is an existing application record; and
1859 // (2) The caller doesn't think it is dead, OR there is no thread
1860 // object attached to it so we know it couldn't have crashed; and
1861 // (3) There is a pid assigned to it, so it is either starting or
1862 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001863 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 + " app=" + app + " knownToBeDead=" + knownToBeDead
1865 + " thread=" + (app != null ? app.thread : null)
1866 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001867 if (app != null && app.pid > 0) {
1868 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001869 // We already have the app running, or are waiting for it to
1870 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001871 return app;
1872 } else {
1873 // An application record is attached to a previous process,
1874 // clean it up now.
1875 handleAppDiedLocked(app, true);
1876 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 String hostingNameStr = hostingName != null
1880 ? hostingName.flattenToShortString() : null;
1881
1882 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1883 // If we are in the background, then check to see if this process
1884 // is bad. If so, we will just silently fail.
1885 if (mBadProcesses.get(info.processName, info.uid) != null) {
1886 return null;
1887 }
1888 } else {
1889 // When the user is explicitly starting a process, then clear its
1890 // crash count so that we won't make it bad until they see at
1891 // least one crash dialog again, and make the process good again
1892 // if it had been bad.
1893 mProcessCrashTimes.remove(info.processName, info.uid);
1894 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001895 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 info.processName);
1897 mBadProcesses.remove(info.processName, info.uid);
1898 if (app != null) {
1899 app.bad = false;
1900 }
1901 }
1902 }
1903
1904 if (app == null) {
1905 app = newProcessRecordLocked(null, info, processName);
1906 mProcessNames.put(processName, info.uid, app);
1907 } else {
1908 // If this is a new package in the process, add the package to the list
1909 app.addPackage(info.packageName);
1910 }
1911
1912 // If the system is not ready yet, then hold off on starting this
1913 // process until it is.
1914 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001915 && !isAllowedWhileBooting(info)
1916 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 if (!mProcessesOnHold.contains(app)) {
1918 mProcessesOnHold.add(app);
1919 }
1920 return app;
1921 }
1922
1923 startProcessLocked(app, hostingType, hostingNameStr);
1924 return (app.pid != 0) ? app : null;
1925 }
1926
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001927 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1928 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1929 }
1930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001931 private final void startProcessLocked(ProcessRecord app,
1932 String hostingType, String hostingNameStr) {
1933 if (app.pid > 0 && app.pid != MY_PID) {
1934 synchronized (mPidsSelfLocked) {
1935 mPidsSelfLocked.remove(app.pid);
1936 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1937 }
1938 app.pid = 0;
1939 }
1940
1941 mProcessesOnHold.remove(app);
1942
1943 updateCpuStats();
1944
1945 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1946 mProcDeaths[0] = 0;
1947
1948 try {
1949 int uid = app.info.uid;
1950 int[] gids = null;
1951 try {
1952 gids = mContext.getPackageManager().getPackageGids(
1953 app.info.packageName);
1954 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001955 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 }
1957 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1958 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1959 && mTopComponent != null
1960 && app.processName.equals(mTopComponent.getPackageName())) {
1961 uid = 0;
1962 }
1963 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1964 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1965 uid = 0;
1966 }
1967 }
1968 int debugFlags = 0;
1969 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1970 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1971 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001972 // Run the app in safe mode if its manifest requests so or the
1973 // system is booted in safe mode.
1974 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1975 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001976 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001978 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1979 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1980 }
1981 if ("1".equals(SystemProperties.get("debug.assert"))) {
1982 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1983 }
1984 int pid = Process.start("android.app.ActivityThread",
1985 mSimpleProcessManagement ? app.processName : null, uid, uid,
1986 gids, debugFlags, null);
1987 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1988 synchronized (bs) {
1989 if (bs.isOnBattery()) {
1990 app.batteryStats.incStartsLocked();
1991 }
1992 }
1993
Doug Zongker2bec3d42009-12-04 12:52:44 -08001994 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001995 app.processName, hostingType,
1996 hostingNameStr != null ? hostingNameStr : "");
1997
1998 if (app.persistent) {
1999 Watchdog.getInstance().processStarted(app, app.processName, pid);
2000 }
2001
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002002 StringBuilder buf = mStringBuilder;
2003 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002004 buf.append("Start proc ");
2005 buf.append(app.processName);
2006 buf.append(" for ");
2007 buf.append(hostingType);
2008 if (hostingNameStr != null) {
2009 buf.append(" ");
2010 buf.append(hostingNameStr);
2011 }
2012 buf.append(": pid=");
2013 buf.append(pid);
2014 buf.append(" uid=");
2015 buf.append(uid);
2016 buf.append(" gids={");
2017 if (gids != null) {
2018 for (int gi=0; gi<gids.length; gi++) {
2019 if (gi != 0) buf.append(", ");
2020 buf.append(gids[gi]);
2021
2022 }
2023 }
2024 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002025 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 if (pid == 0 || pid == MY_PID) {
2027 // Processes are being emulated with threads.
2028 app.pid = MY_PID;
2029 app.removed = false;
2030 mStartingProcesses.add(app);
2031 } else if (pid > 0) {
2032 app.pid = pid;
2033 app.removed = false;
2034 synchronized (mPidsSelfLocked) {
2035 this.mPidsSelfLocked.put(pid, app);
2036 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2037 msg.obj = app;
2038 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2039 }
2040 } else {
2041 app.pid = 0;
2042 RuntimeException e = new RuntimeException(
2043 "Failure starting process " + app.processName
2044 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002045 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 }
2047 } catch (RuntimeException e) {
2048 // XXX do better error recovery.
2049 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002050 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 }
2052 }
2053
2054 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2055 if (mPausingActivity != null) {
2056 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002057 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002058 + mPausingActivity, e);
2059 }
2060 HistoryRecord prev = mResumedActivity;
2061 if (prev == null) {
2062 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002063 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 resumeTopActivityLocked(null);
2065 return;
2066 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002067 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068 mResumedActivity = null;
2069 mPausingActivity = prev;
2070 mLastPausedActivity = prev;
2071 prev.state = ActivityState.PAUSING;
2072 prev.task.touchActiveTime();
2073
2074 updateCpuStats();
2075
2076 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002077 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002079 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002080 System.identityHashCode(prev),
2081 prev.shortComponentName);
2082 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2083 prev.configChangeFlags);
2084 updateUsageStats(prev, false);
2085 } catch (Exception e) {
2086 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002087 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002088 mPausingActivity = null;
2089 mLastPausedActivity = null;
2090 }
2091 } else {
2092 mPausingActivity = null;
2093 mLastPausedActivity = null;
2094 }
2095
2096 // If we are not going to sleep, we want to ensure the device is
2097 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002098 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 mLaunchingActivity.acquire();
2100 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2101 // To be safe, don't allow the wake lock to be held for too long.
2102 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2103 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2104 }
2105 }
2106
2107
2108 if (mPausingActivity != null) {
2109 // Have the window manager pause its key dispatching until the new
2110 // activity has started. If we're pausing the activity just because
2111 // the screen is being turned off and the UI is sleeping, don't interrupt
2112 // key dispatch; the same activity will pick it up again on wakeup.
2113 if (!uiSleeping) {
2114 prev.pauseKeyDispatchingLocked();
2115 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002116 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 }
2118
2119 // Schedule a pause timeout in case the app doesn't respond.
2120 // We don't give it much time because this directly impacts the
2121 // responsiveness seen by the user.
2122 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2123 msg.obj = prev;
2124 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002125 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 } else {
2127 // This activity failed to schedule the
2128 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002129 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 resumeTopActivityLocked(null);
2131 }
2132 }
2133
2134 private final void completePauseLocked() {
2135 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002136 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002137
2138 if (prev != null) {
2139 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002140 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2142 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002143 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 if (prev.waitingVisible) {
2145 prev.waitingVisible = false;
2146 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002147 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 TAG, "Complete pause, no longer waiting: " + prev);
2149 }
2150 if (prev.configDestroy) {
2151 // The previous is being paused because the configuration
2152 // is changing, which means it is actually stopping...
2153 // To juggle the fact that we are also starting a new
2154 // instance right now, we need to first completely stop
2155 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002156 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 destroyActivityLocked(prev, true);
2158 } else {
2159 mStoppingActivities.add(prev);
2160 if (mStoppingActivities.size() > 3) {
2161 // If we already have a few activities waiting to stop,
2162 // then give up on things going idle and start clearing
2163 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002164 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 Message msg = Message.obtain();
2166 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2167 mHandler.sendMessage(msg);
2168 }
2169 }
2170 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002171 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 prev = null;
2173 }
2174 mPausingActivity = null;
2175 }
2176
Dianne Hackborn55280a92009-05-07 15:53:46 -07002177 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 resumeTopActivityLocked(prev);
2179 } else {
2180 if (mGoingToSleep.isHeld()) {
2181 mGoingToSleep.release();
2182 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002183 if (mShuttingDown) {
2184 notifyAll();
2185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 }
2187
2188 if (prev != null) {
2189 prev.resumeKeyDispatchingLocked();
2190 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002191
2192 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2193 long diff = 0;
2194 synchronized (mProcessStatsThread) {
2195 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2196 }
2197 if (diff > 0) {
2198 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2199 synchronized (bsi) {
2200 BatteryStatsImpl.Uid.Proc ps =
2201 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2202 prev.info.packageName);
2203 if (ps != null) {
2204 ps.addForegroundTimeLocked(diff);
2205 }
2206 }
2207 }
2208 }
2209 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 }
2211
2212 /**
2213 * Once we know that we have asked an application to put an activity in
2214 * the resumed state (either by launching it or explicitly telling it),
2215 * this function updates the rest of our state to match that fact.
2216 */
2217 private final void completeResumeLocked(HistoryRecord next) {
2218 next.idle = false;
2219 next.results = null;
2220 next.newIntents = null;
2221
2222 // schedule an idle timeout in case the app doesn't do it for us.
2223 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2224 msg.obj = next;
2225 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2226
2227 if (false) {
2228 // The activity was never told to pause, so just keep
2229 // things going as-is. To maintain our own state,
2230 // we need to emulate it coming back and saying it is
2231 // idle.
2232 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2233 msg.obj = next;
2234 mHandler.sendMessage(msg);
2235 }
2236
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002237 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002239 next.thumbnail = null;
2240 setFocusedActivityLocked(next);
2241 next.resumeKeyDispatchingLocked();
2242 ensureActivitiesVisibleLocked(null, 0);
2243 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002244 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002245
2246 // Mark the point when the activity is resuming
2247 // TODO: To be more accurate, the mark should be before the onCreate,
2248 // not after the onResume. But for subsequent starts, onResume is fine.
2249 if (next.app != null) {
2250 synchronized (mProcessStatsThread) {
2251 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2252 }
2253 } else {
2254 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 }
2257
2258 /**
2259 * Make sure that all activities that need to be visible (that is, they
2260 * currently can be seen by the user) actually are.
2261 */
2262 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2263 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002264 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002265 TAG, "ensureActivitiesVisible behind " + top
2266 + " configChanges=0x" + Integer.toHexString(configChanges));
2267
2268 // If the top activity is not fullscreen, then we need to
2269 // make sure any activities under it are now visible.
2270 final int count = mHistory.size();
2271 int i = count-1;
2272 while (mHistory.get(i) != top) {
2273 i--;
2274 }
2275 HistoryRecord r;
2276 boolean behindFullscreen = false;
2277 for (; i>=0; i--) {
2278 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002279 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 TAG, "Make visible? " + r + " finishing=" + r.finishing
2281 + " state=" + r.state);
2282 if (r.finishing) {
2283 continue;
2284 }
2285
2286 final boolean doThisProcess = onlyThisProcess == null
2287 || onlyThisProcess.equals(r.processName);
2288
2289 // First: if this is not the current activity being started, make
2290 // sure it matches the current configuration.
2291 if (r != starting && doThisProcess) {
2292 ensureActivityConfigurationLocked(r, 0);
2293 }
2294
2295 if (r.app == null || r.app.thread == null) {
2296 if (onlyThisProcess == null
2297 || onlyThisProcess.equals(r.processName)) {
2298 // This activity needs to be visible, but isn't even
2299 // running... get it started, but don't resume it
2300 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002301 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302 TAG, "Start and freeze screen for " + r);
2303 if (r != starting) {
2304 r.startFreezingScreenLocked(r.app, configChanges);
2305 }
2306 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002307 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002308 TAG, "Starting and making visible: " + r);
2309 mWindowManager.setAppVisibility(r, true);
2310 }
2311 if (r != starting) {
2312 startSpecificActivityLocked(r, false, false);
2313 }
2314 }
2315
2316 } else if (r.visible) {
2317 // If this activity is already visible, then there is nothing
2318 // else to do here.
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, "Skipping: already visible at " + r);
2321 r.stopFreezingScreenLocked(false);
2322
2323 } else if (onlyThisProcess == null) {
2324 // This activity is not currently visible, but is running.
2325 // Tell it to become visible.
2326 r.visible = true;
2327 if (r.state != ActivityState.RESUMED && r != starting) {
2328 // If this activity is paused, tell it
2329 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002330 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 TAG, "Making visible and scheduling visibility: " + r);
2332 try {
2333 mWindowManager.setAppVisibility(r, true);
2334 r.app.thread.scheduleWindowVisibility(r, true);
2335 r.stopFreezingScreenLocked(false);
2336 } catch (Exception e) {
2337 // Just skip on any failure; we'll make it
2338 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002339 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002340 + r.intent.getComponent(), e);
2341 }
2342 }
2343 }
2344
2345 // Aggregate current change flags.
2346 configChanges |= r.configChangeFlags;
2347
2348 if (r.fullscreen) {
2349 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002350 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 TAG, "Stopping: fullscreen at " + r);
2352 behindFullscreen = true;
2353 i--;
2354 break;
2355 }
2356 }
2357
2358 // Now for any activities that aren't visible to the user, make
2359 // sure they no longer are keeping the screen frozen.
2360 while (i >= 0) {
2361 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002362 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2364 + " state=" + r.state
2365 + " behindFullscreen=" + behindFullscreen);
2366 if (!r.finishing) {
2367 if (behindFullscreen) {
2368 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002369 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 TAG, "Making invisible: " + r);
2371 r.visible = false;
2372 try {
2373 mWindowManager.setAppVisibility(r, false);
2374 if ((r.state == ActivityState.STOPPING
2375 || r.state == ActivityState.STOPPED)
2376 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002377 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002378 TAG, "Scheduling invisibility: " + r);
2379 r.app.thread.scheduleWindowVisibility(r, false);
2380 }
2381 } catch (Exception e) {
2382 // Just skip on any failure; we'll make it
2383 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002384 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 + r.intent.getComponent(), e);
2386 }
2387 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002388 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002389 TAG, "Already invisible: " + r);
2390 }
2391 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002392 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393 TAG, "Now behindFullscreen: " + r);
2394 behindFullscreen = true;
2395 }
2396 }
2397 i--;
2398 }
2399 }
2400
2401 /**
2402 * Version of ensureActivitiesVisible that can easily be called anywhere.
2403 */
2404 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2405 int configChanges) {
2406 HistoryRecord r = topRunningActivityLocked(null);
2407 if (r != null) {
2408 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2409 }
2410 }
2411
2412 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2413 if (resumed) {
2414 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2415 } else {
2416 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2417 }
2418 }
2419
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002420 private boolean startHomeActivityLocked() {
2421 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2422 && mTopAction == null) {
2423 // We are running in factory test mode, but unable to find
2424 // the factory test app, so just sit around displaying the
2425 // error message and don't try to start anything.
2426 return false;
2427 }
2428 Intent intent = new Intent(
2429 mTopAction,
2430 mTopData != null ? Uri.parse(mTopData) : null);
2431 intent.setComponent(mTopComponent);
2432 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2433 intent.addCategory(Intent.CATEGORY_HOME);
2434 }
2435 ActivityInfo aInfo =
2436 intent.resolveActivityInfo(mContext.getPackageManager(),
2437 STOCK_PM_FLAGS);
2438 if (aInfo != null) {
2439 intent.setComponent(new ComponentName(
2440 aInfo.applicationInfo.packageName, aInfo.name));
2441 // Don't do this if the home app is currently being
2442 // instrumented.
2443 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2444 aInfo.applicationInfo.uid);
2445 if (app == null || app.instrumentationClass == null) {
2446 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2447 startActivityLocked(null, intent, null, null, 0, aInfo,
2448 null, null, 0, 0, 0, false, false);
2449 }
2450 }
2451
2452
2453 return true;
2454 }
2455
2456 /**
2457 * Starts the "new version setup screen" if appropriate.
2458 */
2459 private void startSetupActivityLocked() {
2460 // Only do this once per boot.
2461 if (mCheckedForSetup) {
2462 return;
2463 }
2464
2465 // We will show this screen if the current one is a different
2466 // version than the last one shown, and we are not running in
2467 // low-level factory test mode.
2468 final ContentResolver resolver = mContext.getContentResolver();
2469 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2470 Settings.Secure.getInt(resolver,
2471 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2472 mCheckedForSetup = true;
2473
2474 // See if we should be showing the platform update setup UI.
2475 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2476 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2477 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2478
2479 // We don't allow third party apps to replace this.
2480 ResolveInfo ri = null;
2481 for (int i=0; ris != null && i<ris.size(); i++) {
2482 if ((ris.get(i).activityInfo.applicationInfo.flags
2483 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2484 ri = ris.get(i);
2485 break;
2486 }
2487 }
2488
2489 if (ri != null) {
2490 String vers = ri.activityInfo.metaData != null
2491 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2492 : null;
2493 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2494 vers = ri.activityInfo.applicationInfo.metaData.getString(
2495 Intent.METADATA_SETUP_VERSION);
2496 }
2497 String lastVers = Settings.Secure.getString(
2498 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2499 if (vers != null && !vers.equals(lastVers)) {
2500 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2501 intent.setComponent(new ComponentName(
2502 ri.activityInfo.packageName, ri.activityInfo.name));
2503 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2504 null, null, 0, 0, 0, false, false);
2505 }
2506 }
2507 }
2508 }
2509
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002510 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002511 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002512
2513 final int identHash = System.identityHashCode(r);
2514 updateUsageStats(r, true);
2515
2516 int i = mWatchers.beginBroadcast();
2517 while (i > 0) {
2518 i--;
2519 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2520 if (w != null) {
2521 try {
2522 w.activityResuming(identHash);
2523 } catch (RemoteException e) {
2524 }
2525 }
2526 }
2527 mWatchers.finishBroadcast();
2528 }
2529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530 /**
2531 * Ensure that the top activity in the stack is resumed.
2532 *
2533 * @param prev The previously resumed activity, for when in the process
2534 * of pausing; can be null to call from elsewhere.
2535 *
2536 * @return Returns true if something is being resumed, or false if
2537 * nothing happened.
2538 */
2539 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2540 // Find the first activity that is not finishing.
2541 HistoryRecord next = topRunningActivityLocked(null);
2542
2543 // Remember how we'll process this pause/resume situation, and ensure
2544 // that the state is reset however we wind up proceeding.
2545 final boolean userLeaving = mUserLeaving;
2546 mUserLeaving = false;
2547
2548 if (next == null) {
2549 // There are no more activities! Let's just start up the
2550 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002551 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 }
2553
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002554 next.delayedResume = false;
2555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002556 // If the top activity is the resumed one, nothing to do.
2557 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2558 // Make sure we have executed any pending transitions, since there
2559 // should be nothing left to do at this point.
2560 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002561 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 return false;
2563 }
2564
2565 // If we are sleeping, and there is no resumed activity, and the top
2566 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002567 if ((mSleeping || mShuttingDown)
2568 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 // Make sure we have executed any pending transitions, since there
2570 // should be nothing left to do at this point.
2571 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002572 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002573 return false;
2574 }
2575
2576 // The activity may be waiting for stop, but that is no longer
2577 // appropriate for it.
2578 mStoppingActivities.remove(next);
2579 mWaitingVisibleActivities.remove(next);
2580
Joe Onorato8a9b2202010-02-26 18:56:32 -08002581 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582
2583 // If we are currently pausing an activity, then don't do anything
2584 // until that is done.
2585 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002586 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 return false;
2588 }
2589
2590 // We need to start pausing the current activity so the top one
2591 // can be resumed...
2592 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002593 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 startPausingLocked(userLeaving, false);
2595 return true;
2596 }
2597
2598 if (prev != null && prev != next) {
2599 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2600 prev.waitingVisible = true;
2601 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002602 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603 TAG, "Resuming top, waiting visible to hide: " + prev);
2604 } else {
2605 // The next activity is already visible, so hide the previous
2606 // activity's windows right now so we can show the new one ASAP.
2607 // We only do this if the previous is finishing, which should mean
2608 // it is on top of the one being resumed so hiding it quickly
2609 // is good. Otherwise, we want to do the normal route of allowing
2610 // the resumed activity to be shown so we can decide if the
2611 // previous should actually be hidden depending on whether the
2612 // new one is found to be full-screen or not.
2613 if (prev.finishing) {
2614 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002615 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616 + prev + ", waitingVisible="
2617 + (prev != null ? prev.waitingVisible : null)
2618 + ", nowVisible=" + next.nowVisible);
2619 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002620 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 + prev + ", waitingVisible="
2622 + (prev != null ? prev.waitingVisible : null)
2623 + ", nowVisible=" + next.nowVisible);
2624 }
2625 }
2626 }
2627
2628 // We are starting up the next activity, so tell the window manager
2629 // that the previous one will be hidden soon. This way it can know
2630 // to ignore it when computing the desired screen orientation.
2631 if (prev != null) {
2632 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002633 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002635 if (mNoAnimActivities.contains(prev)) {
2636 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2637 } else {
2638 mWindowManager.prepareAppTransition(prev.task == next.task
2639 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2640 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2641 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002642 mWindowManager.setAppWillBeHidden(prev);
2643 mWindowManager.setAppVisibility(prev, false);
2644 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002645 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002646 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002647 if (mNoAnimActivities.contains(next)) {
2648 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2649 } else {
2650 mWindowManager.prepareAppTransition(prev.task == next.task
2651 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2652 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 }
2655 if (false) {
2656 mWindowManager.setAppWillBeHidden(prev);
2657 mWindowManager.setAppVisibility(prev, false);
2658 }
2659 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002660 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002662 if (mNoAnimActivities.contains(next)) {
2663 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2664 } else {
2665 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002667 }
2668
2669 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002670 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671
2672 // This activity is now becoming visible.
2673 mWindowManager.setAppVisibility(next, true);
2674
2675 HistoryRecord lastResumedActivity = mResumedActivity;
2676 ActivityState lastState = next.state;
2677
2678 updateCpuStats();
2679
2680 next.state = ActivityState.RESUMED;
2681 mResumedActivity = next;
2682 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002683 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 updateLRUListLocked(next);
2685
2686 // Have the window manager re-evaluate the orientation of
2687 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002688 boolean updated;
2689 synchronized (this) {
2690 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2691 mConfiguration,
2692 next.mayFreezeScreenLocked(next.app) ? next : null);
2693 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002694 next.frozenBeforeDestroy = true;
2695 }
2696 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002698 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 // The configuration update wasn't able to keep the existing
2700 // instance of the activity, and instead started a new one.
2701 // We should be all done, but let's just make sure our activity
2702 // is still at the top and schedule another run if something
2703 // weird happened.
2704 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002705 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002706 "Activity config changed during resume: " + next
2707 + ", new next: " + nextNext);
2708 if (nextNext != next) {
2709 // Do over!
2710 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2711 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002712 setFocusedActivityLocked(next);
2713 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002715 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716 return true;
2717 }
2718
2719 try {
2720 // Deliver all pending results.
2721 ArrayList a = next.results;
2722 if (a != null) {
2723 final int N = a.size();
2724 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002725 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 TAG, "Delivering results to " + next
2727 + ": " + a);
2728 next.app.thread.scheduleSendResult(next, a);
2729 }
2730 }
2731
2732 if (next.newIntents != null) {
2733 next.app.thread.scheduleNewIntent(next.newIntents, next);
2734 }
2735
Doug Zongker2bec3d42009-12-04 12:52:44 -08002736 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 System.identityHashCode(next),
2738 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002739
2740 next.app.thread.scheduleResumeActivity(next,
2741 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002743 pauseIfSleepingLocked();
2744
2745 } catch (Exception e) {
2746 // Whoops, need to restart this activity!
2747 next.state = lastState;
2748 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002749 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 if (!next.hasBeenLaunched) {
2751 next.hasBeenLaunched = true;
2752 } else {
2753 if (SHOW_APP_STARTING_ICON) {
2754 mWindowManager.setAppStartingWindow(
2755 next, next.packageName, next.theme,
2756 next.nonLocalizedLabel,
2757 next.labelRes, next.icon, null, true);
2758 }
2759 }
2760 startSpecificActivityLocked(next, true, false);
2761 return true;
2762 }
2763
2764 // From this point on, if something goes wrong there is no way
2765 // to recover the activity.
2766 try {
2767 next.visible = true;
2768 completeResumeLocked(next);
2769 } catch (Exception e) {
2770 // If any exception gets thrown, toss away this
2771 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002772 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002773 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2774 "resume-exception");
2775 return true;
2776 }
2777
2778 // Didn't need to use the icicle, and it is now out of date.
2779 next.icicle = null;
2780 next.haveState = false;
2781 next.stopped = false;
2782
2783 } else {
2784 // Whoops, need to restart this activity!
2785 if (!next.hasBeenLaunched) {
2786 next.hasBeenLaunched = true;
2787 } else {
2788 if (SHOW_APP_STARTING_ICON) {
2789 mWindowManager.setAppStartingWindow(
2790 next, next.packageName, next.theme,
2791 next.nonLocalizedLabel,
2792 next.labelRes, next.icon, null, true);
2793 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002794 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 }
2796 startSpecificActivityLocked(next, true, true);
2797 }
2798
2799 return true;
2800 }
2801
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002802 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2803 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002804 final int NH = mHistory.size();
2805
2806 int addPos = -1;
2807
2808 if (!newTask) {
2809 // If starting in an existing task, find where that is...
2810 HistoryRecord next = null;
2811 boolean startIt = true;
2812 for (int i = NH-1; i >= 0; i--) {
2813 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2814 if (p.finishing) {
2815 continue;
2816 }
2817 if (p.task == r.task) {
2818 // Here it is! Now, if this is not yet visible to the
2819 // user, then just add it without starting; it will
2820 // get started when the user navigates back to it.
2821 addPos = i+1;
2822 if (!startIt) {
2823 mHistory.add(addPos, r);
2824 r.inHistory = true;
2825 r.task.numActivities++;
2826 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2827 r.info.screenOrientation, r.fullscreen);
2828 if (VALIDATE_TOKENS) {
2829 mWindowManager.validateAppTokens(mHistory);
2830 }
2831 return;
2832 }
2833 break;
2834 }
2835 if (p.fullscreen) {
2836 startIt = false;
2837 }
2838 next = p;
2839 }
2840 }
2841
2842 // Place a new activity at top of stack, so it is next to interact
2843 // with the user.
2844 if (addPos < 0) {
2845 addPos = mHistory.size();
2846 }
2847
2848 // If we are not placing the new activity frontmost, we do not want
2849 // to deliver the onUserLeaving callback to the actual frontmost
2850 // activity
2851 if (addPos < NH) {
2852 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002853 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002854 }
2855
2856 // Slot the activity into the history stack and proceed
2857 mHistory.add(addPos, r);
2858 r.inHistory = true;
2859 r.frontOfTask = newTask;
2860 r.task.numActivities++;
2861 if (NH > 0) {
2862 // We want to show the starting preview window if we are
2863 // switching to a new task, or the next activity's process is
2864 // not currently running.
2865 boolean showStartingIcon = newTask;
2866 ProcessRecord proc = r.app;
2867 if (proc == null) {
2868 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2869 }
2870 if (proc == null || proc.thread == null) {
2871 showStartingIcon = true;
2872 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002873 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002875 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2876 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2877 mNoAnimActivities.add(r);
2878 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2879 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2880 mNoAnimActivities.remove(r);
2881 } else {
2882 mWindowManager.prepareAppTransition(newTask
2883 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2884 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2885 mNoAnimActivities.remove(r);
2886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 mWindowManager.addAppToken(
2888 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2889 boolean doShow = true;
2890 if (newTask) {
2891 // Even though this activity is starting fresh, we still need
2892 // to reset it to make sure we apply affinities to move any
2893 // existing activities from other tasks in to it.
2894 // If the caller has requested that the target task be
2895 // reset, then do so.
2896 if ((r.intent.getFlags()
2897 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2898 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002899 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 }
2901 }
2902 if (SHOW_APP_STARTING_ICON && doShow) {
2903 // Figure out if we are transitioning from another activity that is
2904 // "has the same starting icon" as the next one. This allows the
2905 // window manager to keep the previous window it had previously
2906 // created, if it still had one.
2907 HistoryRecord prev = mResumedActivity;
2908 if (prev != null) {
2909 // We don't want to reuse the previous starting preview if:
2910 // (1) The current activity is in a different task.
2911 if (prev.task != r.task) prev = null;
2912 // (2) The current activity is already displayed.
2913 else if (prev.nowVisible) prev = null;
2914 }
2915 mWindowManager.setAppStartingWindow(
2916 r, r.packageName, r.theme, r.nonLocalizedLabel,
2917 r.labelRes, r.icon, prev, showStartingIcon);
2918 }
2919 } else {
2920 // If this is the first activity, don't do any fancy animations,
2921 // because there is nothing for it to animate on top of.
2922 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2923 r.info.screenOrientation, r.fullscreen);
2924 }
2925 if (VALIDATE_TOKENS) {
2926 mWindowManager.validateAppTokens(mHistory);
2927 }
2928
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002929 if (doResume) {
2930 resumeTopActivityLocked(null);
2931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 }
2933
2934 /**
2935 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002936 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2937 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 * an instance of that activity in the stack and, if found, finish all
2939 * activities on top of it and return the instance.
2940 *
2941 * @param newR Description of the new activity being started.
2942 * @return Returns the old activity that should be continue to be used,
2943 * or null if none was found.
2944 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002945 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002946 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002948
2949 // First find the requested task.
2950 while (i > 0) {
2951 i--;
2952 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2953 if (r.task.taskId == taskId) {
2954 i++;
2955 break;
2956 }
2957 }
2958
2959 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 while (i > 0) {
2961 i--;
2962 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2963 if (r.finishing) {
2964 continue;
2965 }
2966 if (r.task.taskId != taskId) {
2967 return null;
2968 }
2969 if (r.realActivity.equals(newR.realActivity)) {
2970 // Here it is! Now finish everything in front...
2971 HistoryRecord ret = r;
2972 if (doClear) {
2973 while (i < (mHistory.size()-1)) {
2974 i++;
2975 r = (HistoryRecord)mHistory.get(i);
2976 if (r.finishing) {
2977 continue;
2978 }
2979 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2980 null, "clear")) {
2981 i--;
2982 }
2983 }
2984 }
2985
2986 // Finally, if this is a normal launch mode (that is, not
2987 // expecting onNewIntent()), then we will finish the current
2988 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002989 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2990 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002992 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 if (index >= 0) {
2994 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2995 null, "clear");
2996 }
2997 return null;
2998 }
2999 }
3000
3001 return ret;
3002 }
3003 }
3004
3005 return null;
3006 }
3007
3008 /**
3009 * Find the activity in the history stack within the given task. Returns
3010 * the index within the history at which it's found, or < 0 if not found.
3011 */
3012 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3013 int i = mHistory.size();
3014 while (i > 0) {
3015 i--;
3016 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3017 if (candidate.task.taskId != task) {
3018 break;
3019 }
3020 if (candidate.realActivity.equals(r.realActivity)) {
3021 return i;
3022 }
3023 }
3024
3025 return -1;
3026 }
3027
3028 /**
3029 * Reorder the history stack so that the activity at the given index is
3030 * brought to the front.
3031 */
3032 private final HistoryRecord moveActivityToFrontLocked(int where) {
3033 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3034 int top = mHistory.size();
3035 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3036 mHistory.add(top, newTop);
3037 oldTop.frontOfTask = false;
3038 newTop.frontOfTask = true;
3039 return newTop;
3040 }
3041
3042 /**
3043 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3044 * method will be called at the proper time.
3045 */
3046 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3047 boolean sent = false;
3048 if (r.state == ActivityState.RESUMED
3049 && r.app != null && r.app.thread != null) {
3050 try {
3051 ArrayList<Intent> ar = new ArrayList<Intent>();
3052 ar.add(new Intent(intent));
3053 r.app.thread.scheduleNewIntent(ar, r);
3054 sent = true;
3055 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003056 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 }
3058 }
3059 if (!sent) {
3060 r.addNewIntentLocked(new Intent(intent));
3061 }
3062 }
3063
3064 private final void logStartActivity(int tag, HistoryRecord r,
3065 TaskRecord task) {
3066 EventLog.writeEvent(tag,
3067 System.identityHashCode(r), task.taskId,
3068 r.shortComponentName, r.intent.getAction(),
3069 r.intent.getType(), r.intent.getDataString(),
3070 r.intent.getFlags());
3071 }
3072
3073 private final int startActivityLocked(IApplicationThread caller,
3074 Intent intent, String resolvedType,
3075 Uri[] grantedUriPermissions,
3076 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3077 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003078 int callingPid, int callingUid, boolean onlyIfNeeded,
3079 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003080 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081
3082 HistoryRecord sourceRecord = null;
3083 HistoryRecord resultRecord = null;
3084 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003085 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003086 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3088 if (index >= 0) {
3089 sourceRecord = (HistoryRecord)mHistory.get(index);
3090 if (requestCode >= 0 && !sourceRecord.finishing) {
3091 resultRecord = sourceRecord;
3092 }
3093 }
3094 }
3095
3096 int launchFlags = intent.getFlags();
3097
3098 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3099 && sourceRecord != null) {
3100 // Transfer the result target from the source activity to the new
3101 // one being started, including any failures.
3102 if (requestCode >= 0) {
3103 return START_FORWARD_AND_REQUEST_CONFLICT;
3104 }
3105 resultRecord = sourceRecord.resultTo;
3106 resultWho = sourceRecord.resultWho;
3107 requestCode = sourceRecord.requestCode;
3108 sourceRecord.resultTo = null;
3109 if (resultRecord != null) {
3110 resultRecord.removeResultsLocked(
3111 sourceRecord, resultWho, requestCode);
3112 }
3113 }
3114
3115 int err = START_SUCCESS;
3116
3117 if (intent.getComponent() == null) {
3118 // We couldn't find a class that can handle the given Intent.
3119 // That's the end of that!
3120 err = START_INTENT_NOT_RESOLVED;
3121 }
3122
3123 if (err == START_SUCCESS && aInfo == null) {
3124 // We couldn't find the specific class specified in the Intent.
3125 // Also the end of the line.
3126 err = START_CLASS_NOT_FOUND;
3127 }
3128
3129 ProcessRecord callerApp = null;
3130 if (err == START_SUCCESS && caller != null) {
3131 callerApp = getRecordForAppLocked(caller);
3132 if (callerApp != null) {
3133 callingPid = callerApp.pid;
3134 callingUid = callerApp.info.uid;
3135 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003136 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 + " (pid=" + callingPid + ") when starting: "
3138 + intent.toString());
3139 err = START_PERMISSION_DENIED;
3140 }
3141 }
3142
3143 if (err != START_SUCCESS) {
3144 if (resultRecord != null) {
3145 sendActivityResultLocked(-1,
3146 resultRecord, resultWho, requestCode,
3147 Activity.RESULT_CANCELED, null);
3148 }
3149 return err;
3150 }
3151
3152 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3153 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3154 if (perm != PackageManager.PERMISSION_GRANTED) {
3155 if (resultRecord != null) {
3156 sendActivityResultLocked(-1,
3157 resultRecord, resultWho, requestCode,
3158 Activity.RESULT_CANCELED, null);
3159 }
3160 String msg = "Permission Denial: starting " + intent.toString()
3161 + " from " + callerApp + " (pid=" + callingPid
3162 + ", uid=" + callingUid + ")"
3163 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003164 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 throw new SecurityException(msg);
3166 }
3167
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003168 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003169 boolean abort = false;
3170 try {
3171 // The Intent we give to the watcher has the extra data
3172 // stripped off, since it can contain private information.
3173 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003174 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 aInfo.applicationInfo.packageName);
3176 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003177 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 }
3179
3180 if (abort) {
3181 if (resultRecord != null) {
3182 sendActivityResultLocked(-1,
3183 resultRecord, resultWho, requestCode,
3184 Activity.RESULT_CANCELED, null);
3185 }
3186 // We pretend to the caller that it was really started, but
3187 // they will just get a cancel result.
3188 return START_SUCCESS;
3189 }
3190 }
3191
3192 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3193 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003194 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003196 if (mResumedActivity == null
3197 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3198 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3199 PendingActivityLaunch pal = new PendingActivityLaunch();
3200 pal.r = r;
3201 pal.sourceRecord = sourceRecord;
3202 pal.grantedUriPermissions = grantedUriPermissions;
3203 pal.grantedMode = grantedMode;
3204 pal.onlyIfNeeded = onlyIfNeeded;
3205 mPendingActivityLaunches.add(pal);
3206 return START_SWITCHES_CANCELED;
3207 }
3208 }
3209
3210 if (mDidAppSwitch) {
3211 // This is the second allowed switch since we stopped switches,
3212 // so now just generally allow switches. Use case: user presses
3213 // home (switches disabled, switch to home, mDidAppSwitch now true);
3214 // user taps a home icon (coming from home so allowed, we hit here
3215 // and now allow anyone to switch again).
3216 mAppSwitchesAllowedTime = 0;
3217 } else {
3218 mDidAppSwitch = true;
3219 }
3220
3221 doPendingActivityLaunchesLocked(false);
3222
3223 return startActivityUncheckedLocked(r, sourceRecord,
3224 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3225 }
3226
3227 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3228 final int N = mPendingActivityLaunches.size();
3229 if (N <= 0) {
3230 return;
3231 }
3232 for (int i=0; i<N; i++) {
3233 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3234 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3235 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3236 doResume && i == (N-1));
3237 }
3238 mPendingActivityLaunches.clear();
3239 }
3240
3241 private final int startActivityUncheckedLocked(HistoryRecord r,
3242 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3243 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3244 final Intent intent = r.intent;
3245 final int callingUid = r.launchedFromUid;
3246
3247 int launchFlags = intent.getFlags();
3248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 // We'll invoke onUserLeaving before onPause only if the launching
3250 // activity did not explicitly state that this is an automated launch.
3251 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003252 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 "startActivity() => mUserLeaving=" + mUserLeaving);
3254
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003255 // If the caller has asked not to resume at this point, we make note
3256 // of this in the record so that we can skip it when trying to find
3257 // the top running activity.
3258 if (!doResume) {
3259 r.delayedResume = true;
3260 }
3261
3262 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3263 != 0 ? r : null;
3264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265 // If the onlyIfNeeded flag is set, then we can do this if the activity
3266 // being launched is the same as the one making the call... or, as
3267 // a special case, if we do not know the caller then we count the
3268 // current top activity as the caller.
3269 if (onlyIfNeeded) {
3270 HistoryRecord checkedCaller = sourceRecord;
3271 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003272 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273 }
3274 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3275 // Caller is not the same as launcher, so always needed.
3276 onlyIfNeeded = false;
3277 }
3278 }
3279
3280 if (grantedUriPermissions != null && callingUid > 0) {
3281 for (int i=0; i<grantedUriPermissions.length; i++) {
3282 grantUriPermissionLocked(callingUid, r.packageName,
3283 grantedUriPermissions[i], grantedMode, r);
3284 }
3285 }
3286
3287 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3288 intent, r);
3289
3290 if (sourceRecord == null) {
3291 // This activity is not being started from another... in this
3292 // case we -always- start a new task.
3293 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003294 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 -08003295 + intent);
3296 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3297 }
3298 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3299 // The original activity who is starting us is running as a single
3300 // instance... this new activity it is starting must go on its
3301 // own task.
3302 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3303 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3304 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3305 // The activity being started is a single instance... it always
3306 // gets launched into its own task.
3307 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3308 }
3309
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003310 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 // For whatever reason this activity is being launched into a new
3312 // task... yet the caller has requested a result back. Well, that
3313 // is pretty messed up, so instead immediately send back a cancel
3314 // and let the new task continue launched as normal without a
3315 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003316 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003318 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 Activity.RESULT_CANCELED, null);
3320 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003321 }
3322
3323 boolean addingToTask = false;
3324 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3325 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3326 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3327 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3328 // If bring to front is requested, and no result is requested, and
3329 // we can find a task that was started with this same
3330 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003331 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 // See if there is a task to bring to the front. If this is
3333 // a SINGLE_INSTANCE activity, there can be one and only one
3334 // instance of it in the history, and it is always in its own
3335 // unique task, so we do a special search.
3336 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3337 ? findTaskLocked(intent, r.info)
3338 : findActivityLocked(intent, r.info);
3339 if (taskTop != null) {
3340 if (taskTop.task.intent == null) {
3341 // This task was started because of movement of
3342 // the activity based on affinity... now that we
3343 // are actually launching it, we can assign the
3344 // base intent.
3345 taskTop.task.setIntent(intent, r.info);
3346 }
3347 // If the target task is not in the front, then we need
3348 // to bring it to the front... except... well, with
3349 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3350 // to have the same behavior as if a new instance was
3351 // being started, which means not bringing it to the front
3352 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003353 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354 if (curTop.task != taskTop.task) {
3355 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3356 boolean callerAtFront = sourceRecord == null
3357 || curTop.task == sourceRecord.task;
3358 if (callerAtFront) {
3359 // We really do want to push this one into the
3360 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003361 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 }
3363 }
3364 // If the caller has requested that the target task be
3365 // reset, then do so.
3366 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3367 taskTop = resetTaskIfNeededLocked(taskTop, r);
3368 }
3369 if (onlyIfNeeded) {
3370 // We don't need to start a new activity, and
3371 // the client said not to do anything if that
3372 // is the case, so this is it! And for paranoia, make
3373 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003374 if (doResume) {
3375 resumeTopActivityLocked(null);
3376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 return START_RETURN_INTENT_TO_CALLER;
3378 }
3379 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3380 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3381 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3382 // In this situation we want to remove all activities
3383 // from the task up to the one being started. In most
3384 // cases this means we are resetting the task to its
3385 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003386 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003387 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 if (top != null) {
3389 if (top.frontOfTask) {
3390 // Activity aliases may mean we use different
3391 // intents for the top activity, so make sure
3392 // the task now has the identity of the new
3393 // intent.
3394 top.task.setIntent(r.intent, r.info);
3395 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003396 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003397 deliverNewIntentLocked(top, r.intent);
3398 } else {
3399 // A special case: we need to
3400 // start the activity because it is not currently
3401 // running, and the caller has asked to clear the
3402 // current task to have this activity at the top.
3403 addingToTask = true;
3404 // Now pretend like this activity is being started
3405 // by the top of its task, so it is put in the
3406 // right place.
3407 sourceRecord = taskTop;
3408 }
3409 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3410 // In this case the top activity on the task is the
3411 // same as the one being launched, so we take that
3412 // as a request to bring the task to the foreground.
3413 // If the top activity in the task is the root
3414 // activity, deliver this new intent to it if it
3415 // desires.
3416 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3417 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003418 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003419 if (taskTop.frontOfTask) {
3420 taskTop.task.setIntent(r.intent, r.info);
3421 }
3422 deliverNewIntentLocked(taskTop, r.intent);
3423 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3424 // In this case we are launching the root activity
3425 // of the task, but with a different intent. We
3426 // should start a new instance on top.
3427 addingToTask = true;
3428 sourceRecord = taskTop;
3429 }
3430 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3431 // In this case an activity is being launched in to an
3432 // existing task, without resetting that task. This
3433 // is typically the situation of launching an activity
3434 // from a notification or shortcut. We want to place
3435 // the new activity on top of the current task.
3436 addingToTask = true;
3437 sourceRecord = taskTop;
3438 } else if (!taskTop.task.rootWasReset) {
3439 // In this case we are launching in to an existing task
3440 // that has not yet been started from its front door.
3441 // The current task has been brought to the front.
3442 // Ideally, we'd probably like to place this new task
3443 // at the bottom of its stack, but that's a little hard
3444 // to do with the current organization of the code so
3445 // for now we'll just drop it.
3446 taskTop.task.setIntent(r.intent, r.info);
3447 }
3448 if (!addingToTask) {
3449 // We didn't do anything... but it was needed (a.k.a., client
3450 // don't use that intent!) And for paranoia, make
3451 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003452 if (doResume) {
3453 resumeTopActivityLocked(null);
3454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 return START_TASK_TO_FRONT;
3456 }
3457 }
3458 }
3459 }
3460
3461 //String uri = r.intent.toURI();
3462 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003463 //Slog.i(TAG, "Given intent: " + r.intent);
3464 //Slog.i(TAG, "URI is: " + uri);
3465 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003466
3467 if (r.packageName != null) {
3468 // If the activity being launched is the same as the one currently
3469 // at the top, then we need to check if it should only be launched
3470 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003471 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3472 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 if (top.realActivity.equals(r.realActivity)) {
3474 if (top.app != null && top.app.thread != null) {
3475 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3476 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3477 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003478 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 // For paranoia, make sure we have correctly
3480 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003481 if (doResume) {
3482 resumeTopActivityLocked(null);
3483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 if (onlyIfNeeded) {
3485 // We don't need to start a new activity, and
3486 // the client said not to do anything if that
3487 // is the case, so this is it!
3488 return START_RETURN_INTENT_TO_CALLER;
3489 }
3490 deliverNewIntentLocked(top, r.intent);
3491 return START_DELIVERED_TO_TOP;
3492 }
3493 }
3494 }
3495 }
3496
3497 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003498 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003500 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003501 Activity.RESULT_CANCELED, null);
3502 }
3503 return START_CLASS_NOT_FOUND;
3504 }
3505
3506 boolean newTask = false;
3507
3508 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003509 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3511 // todo: should do better management of integers.
3512 mCurTask++;
3513 if (mCurTask <= 0) {
3514 mCurTask = 1;
3515 }
3516 r.task = new TaskRecord(mCurTask, r.info, intent,
3517 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003518 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 + " in new task " + r.task);
3520 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003521 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003522
3523 } else if (sourceRecord != null) {
3524 if (!addingToTask &&
3525 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3526 // In this case, we are adding the activity to an existing
3527 // task, but the caller has asked to clear that task if the
3528 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003529 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003530 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003532 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 deliverNewIntentLocked(top, r.intent);
3534 // For paranoia, make sure we have correctly
3535 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003536 if (doResume) {
3537 resumeTopActivityLocked(null);
3538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 return START_DELIVERED_TO_TOP;
3540 }
3541 } else if (!addingToTask &&
3542 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3543 // In this case, we are launching an activity in our own task
3544 // that may already be running somewhere in the history, and
3545 // we want to shuffle it to the front of the stack if so.
3546 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3547 if (where >= 0) {
3548 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003549 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003550 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003551 if (doResume) {
3552 resumeTopActivityLocked(null);
3553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003554 return START_DELIVERED_TO_TOP;
3555 }
3556 }
3557 // An existing activity is starting this new activity, so we want
3558 // to keep the new one in the same task as the one that is starting
3559 // it.
3560 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003561 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 + " in existing task " + r.task);
3563
3564 } else {
3565 // This not being started from an existing activity, and not part
3566 // of a new task... just put it in the top task, though these days
3567 // this case should never happen.
3568 final int N = mHistory.size();
3569 HistoryRecord prev =
3570 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3571 r.task = prev != null
3572 ? prev.task
3573 : new TaskRecord(mCurTask, r.info, intent,
3574 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003575 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003576 + " in new guessed " + r.task);
3577 }
3578 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003579 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003581 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003582 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 return START_SUCCESS;
3584 }
3585
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003586 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3587 long thisTime, long totalTime) {
3588 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3589 WaitResult w = mWaitingActivityLaunched.get(i);
3590 w.timeout = timeout;
3591 if (r != null) {
3592 w.who = new ComponentName(r.info.packageName, r.info.name);
3593 }
3594 w.thisTime = thisTime;
3595 w.totalTime = totalTime;
3596 }
3597 notify();
3598 }
3599
3600 void reportActivityVisibleLocked(HistoryRecord r) {
3601 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3602 WaitResult w = mWaitingActivityVisible.get(i);
3603 w.timeout = false;
3604 if (r != null) {
3605 w.who = new ComponentName(r.info.packageName, r.info.name);
3606 }
3607 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3608 w.thisTime = w.totalTime;
3609 }
3610 notify();
3611 }
3612
3613 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3615 int grantedMode, IBinder resultTo,
3616 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003617 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 // Refuse possible leaked file descriptors
3619 if (intent != null && intent.hasFileDescriptors()) {
3620 throw new IllegalArgumentException("File descriptors passed in Intent");
3621 }
3622
The Android Open Source Project4df24232009-03-05 14:34:35 -08003623 final boolean componentSpecified = intent.getComponent() != null;
3624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003625 // Don't modify the client's object!
3626 intent = new Intent(intent);
3627
3628 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 ActivityInfo aInfo;
3630 try {
3631 ResolveInfo rInfo =
3632 ActivityThread.getPackageManager().resolveIntent(
3633 intent, resolvedType,
3634 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003635 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 aInfo = rInfo != null ? rInfo.activityInfo : null;
3637 } catch (RemoteException e) {
3638 aInfo = null;
3639 }
3640
3641 if (aInfo != null) {
3642 // Store the found target back into the intent, because now that
3643 // we have it we never want to do this again. For example, if the
3644 // user navigates back to this point in the history, we should
3645 // always restart the exact same activity.
3646 intent.setComponent(new ComponentName(
3647 aInfo.applicationInfo.packageName, aInfo.name));
3648
3649 // Don't debug things in the system process
3650 if (debug) {
3651 if (!aInfo.processName.equals("system")) {
3652 setDebugApp(aInfo.processName, true, false);
3653 }
3654 }
3655 }
3656
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003657 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003658 int callingPid;
3659 int callingUid;
3660 if (caller == null) {
3661 callingPid = Binder.getCallingPid();
3662 callingUid = Binder.getCallingUid();
3663 } else {
3664 callingPid = callingUid = -1;
3665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003666 final long origId = Binder.clearCallingIdentity();
3667 int res = startActivityLocked(caller, intent, resolvedType,
3668 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003669 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003670 onlyIfNeeded, componentSpecified);
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003671 if (config != null) {
3672 // If the caller also wants to switch to a new configuration,
3673 // do so now. This allows a clean switch, as we are waiting
3674 // for the current activity to pause (so we will not destroy
3675 // it), and have not yet started the next activity.
3676 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3677 "updateConfiguration()");
3678 updateConfigurationLocked(config, null);
3679 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003681
3682 if (outResult != null) {
3683 outResult.result = res;
3684 if (res == IActivityManager.START_SUCCESS) {
3685 mWaitingActivityLaunched.add(outResult);
3686 do {
3687 try {
3688 wait();
3689 } catch (InterruptedException e) {
3690 }
3691 } while (!outResult.timeout && outResult.who == null);
3692 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3693 HistoryRecord r = this.topRunningActivityLocked(null);
3694 if (r.nowVisible) {
3695 outResult.timeout = false;
3696 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3697 outResult.totalTime = 0;
3698 outResult.thisTime = 0;
3699 } else {
3700 outResult.thisTime = SystemClock.uptimeMillis();
3701 mWaitingActivityVisible.add(outResult);
3702 do {
3703 try {
3704 wait();
3705 } catch (InterruptedException e) {
3706 }
3707 } while (!outResult.timeout && outResult.who == null);
3708 }
3709 }
3710 }
3711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 return res;
3713 }
3714 }
3715
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003716 public final int startActivity(IApplicationThread caller,
3717 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3718 int grantedMode, IBinder resultTo,
3719 String resultWho, int requestCode, boolean onlyIfNeeded,
3720 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003721 return startActivityMayWait(caller, intent, resolvedType,
3722 grantedUriPermissions, grantedMode, resultTo, resultWho,
3723 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003724 }
3725
3726 public final WaitResult startActivityAndWait(IApplicationThread caller,
3727 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3728 int grantedMode, IBinder resultTo,
3729 String resultWho, int requestCode, boolean onlyIfNeeded,
3730 boolean debug) {
3731 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003732 startActivityMayWait(caller, intent, resolvedType,
3733 grantedUriPermissions, grantedMode, resultTo, resultWho,
3734 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003735 return res;
3736 }
3737
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003738 public final int startActivityWithConfig(IApplicationThread caller,
3739 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3740 int grantedMode, IBinder resultTo,
3741 String resultWho, int requestCode, boolean onlyIfNeeded,
3742 boolean debug, Configuration config) {
3743 return startActivityMayWait(caller, intent, resolvedType,
3744 grantedUriPermissions, grantedMode, resultTo, resultWho,
3745 requestCode, onlyIfNeeded, debug, null, config);
3746 }
3747
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003748 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003749 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003750 IBinder resultTo, String resultWho, int requestCode,
3751 int flagsMask, int flagsValues) {
3752 // Refuse possible leaked file descriptors
3753 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3754 throw new IllegalArgumentException("File descriptors passed in Intent");
3755 }
3756
3757 IIntentSender sender = intent.getTarget();
3758 if (!(sender instanceof PendingIntentRecord)) {
3759 throw new IllegalArgumentException("Bad PendingIntent object");
3760 }
3761
3762 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003763
3764 synchronized (this) {
3765 // If this is coming from the currently resumed activity, it is
3766 // effectively saying that app switches are allowed at this point.
3767 if (mResumedActivity != null
3768 && mResumedActivity.info.applicationInfo.uid ==
3769 Binder.getCallingUid()) {
3770 mAppSwitchesAllowedTime = 0;
3771 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003772 }
3773
3774 return pir.sendInner(0, fillInIntent, resolvedType,
3775 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3776 }
3777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 public boolean startNextMatchingActivity(IBinder callingActivity,
3779 Intent intent) {
3780 // Refuse possible leaked file descriptors
3781 if (intent != null && intent.hasFileDescriptors() == true) {
3782 throw new IllegalArgumentException("File descriptors passed in Intent");
3783 }
3784
3785 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003786 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787 if (index < 0) {
3788 return false;
3789 }
3790 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3791 if (r.app == null || r.app.thread == null) {
3792 // The caller is not running... d'oh!
3793 return false;
3794 }
3795 intent = new Intent(intent);
3796 // The caller is not allowed to change the data.
3797 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3798 // And we are resetting to find the next component...
3799 intent.setComponent(null);
3800
3801 ActivityInfo aInfo = null;
3802 try {
3803 List<ResolveInfo> resolves =
3804 ActivityThread.getPackageManager().queryIntentActivities(
3805 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003806 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807
3808 // Look for the original activity in the list...
3809 final int N = resolves != null ? resolves.size() : 0;
3810 for (int i=0; i<N; i++) {
3811 ResolveInfo rInfo = resolves.get(i);
3812 if (rInfo.activityInfo.packageName.equals(r.packageName)
3813 && rInfo.activityInfo.name.equals(r.info.name)) {
3814 // We found the current one... the next matching is
3815 // after it.
3816 i++;
3817 if (i<N) {
3818 aInfo = resolves.get(i).activityInfo;
3819 }
3820 break;
3821 }
3822 }
3823 } catch (RemoteException e) {
3824 }
3825
3826 if (aInfo == null) {
3827 // Nobody who is next!
3828 return false;
3829 }
3830
3831 intent.setComponent(new ComponentName(
3832 aInfo.applicationInfo.packageName, aInfo.name));
3833 intent.setFlags(intent.getFlags()&~(
3834 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3835 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3836 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3837 Intent.FLAG_ACTIVITY_NEW_TASK));
3838
3839 // Okay now we need to start the new activity, replacing the
3840 // currently running activity. This is a little tricky because
3841 // we want to start the new one as if the current one is finished,
3842 // but not finish the current one first so that there is no flicker.
3843 // And thus...
3844 final boolean wasFinishing = r.finishing;
3845 r.finishing = true;
3846
3847 // Propagate reply information over to the new activity.
3848 final HistoryRecord resultTo = r.resultTo;
3849 final String resultWho = r.resultWho;
3850 final int requestCode = r.requestCode;
3851 r.resultTo = null;
3852 if (resultTo != null) {
3853 resultTo.removeResultsLocked(r, resultWho, requestCode);
3854 }
3855
3856 final long origId = Binder.clearCallingIdentity();
3857 // XXX we are not dealing with propagating grantedUriPermissions...
3858 // those are not yet exposed to user code, so there is no need.
3859 int res = startActivityLocked(r.app.thread, intent,
3860 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003861 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 Binder.restoreCallingIdentity(origId);
3863
3864 r.finishing = wasFinishing;
3865 if (res != START_SUCCESS) {
3866 return false;
3867 }
3868 return true;
3869 }
3870 }
3871
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003872 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873 Intent intent, String resolvedType, IBinder resultTo,
3874 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003875
3876 // This is so super not safe, that only the system (or okay root)
3877 // can do it.
3878 final int callingUid = Binder.getCallingUid();
3879 if (callingUid != 0 && callingUid != Process.myUid()) {
3880 throw new SecurityException(
3881 "startActivityInPackage only available to the system");
3882 }
3883
The Android Open Source Project4df24232009-03-05 14:34:35 -08003884 final boolean componentSpecified = intent.getComponent() != null;
3885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003886 // Don't modify the client's object!
3887 intent = new Intent(intent);
3888
3889 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 ActivityInfo aInfo;
3891 try {
3892 ResolveInfo rInfo =
3893 ActivityThread.getPackageManager().resolveIntent(
3894 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003895 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 aInfo = rInfo != null ? rInfo.activityInfo : null;
3897 } catch (RemoteException e) {
3898 aInfo = null;
3899 }
3900
3901 if (aInfo != null) {
3902 // Store the found target back into the intent, because now that
3903 // we have it we never want to do this again. For example, if the
3904 // user navigates back to this point in the history, we should
3905 // always restart the exact same activity.
3906 intent.setComponent(new ComponentName(
3907 aInfo.applicationInfo.packageName, aInfo.name));
3908 }
3909
3910 synchronized(this) {
3911 return startActivityLocked(null, intent, resolvedType,
3912 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003913 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003914 }
3915 }
3916
Josh Bartel7f208742010-02-25 11:01:44 -06003917 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 // Remove any existing entries that are the same kind of task.
3919 int N = mRecentTasks.size();
3920 for (int i=0; i<N; i++) {
3921 TaskRecord tr = mRecentTasks.get(i);
3922 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3923 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3924 mRecentTasks.remove(i);
3925 i--;
3926 N--;
3927 if (task.intent == null) {
3928 // If the new recent task we are adding is not fully
3929 // specified, then replace it with the existing recent task.
3930 task = tr;
3931 }
3932 }
3933 }
3934 if (N >= MAX_RECENT_TASKS) {
3935 mRecentTasks.remove(N-1);
3936 }
3937 mRecentTasks.add(0, task);
3938 }
3939
3940 public void setRequestedOrientation(IBinder token,
3941 int requestedOrientation) {
3942 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003943 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 if (index < 0) {
3945 return;
3946 }
3947 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3948 final long origId = Binder.clearCallingIdentity();
3949 mWindowManager.setAppOrientation(r, requestedOrientation);
3950 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003951 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 r.mayFreezeScreenLocked(r.app) ? r : null);
3953 if (config != null) {
3954 r.frozenBeforeDestroy = true;
3955 if (!updateConfigurationLocked(config, r)) {
3956 resumeTopActivityLocked(null);
3957 }
3958 }
3959 Binder.restoreCallingIdentity(origId);
3960 }
3961 }
3962
3963 public int getRequestedOrientation(IBinder token) {
3964 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003965 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 if (index < 0) {
3967 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3968 }
3969 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3970 return mWindowManager.getAppOrientation(r);
3971 }
3972 }
3973
3974 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003975 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003976 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3977 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3978 if (!r.finishing) {
3979 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3980 "no-history");
3981 }
3982 } else if (r.app != null && r.app.thread != null) {
3983 if (mFocusedActivity == r) {
3984 setFocusedActivityLocked(topRunningActivityLocked(null));
3985 }
3986 r.resumeKeyDispatchingLocked();
3987 try {
3988 r.stopped = false;
3989 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003990 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003991 TAG, "Stopping visible=" + r.visible + " for " + r);
3992 if (!r.visible) {
3993 mWindowManager.setAppVisibility(r, false);
3994 }
3995 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3996 } catch (Exception e) {
3997 // Maybe just ignore exceptions here... if the process
3998 // has crashed, our death notification will clean things
3999 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004000 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004001 // Just in case, assume it to be stopped.
4002 r.stopped = true;
4003 r.state = ActivityState.STOPPED;
4004 if (r.configDestroy) {
4005 destroyActivityLocked(r, true);
4006 }
4007 }
4008 }
4009 }
4010
4011 /**
4012 * @return Returns true if the activity is being finished, false if for
4013 * some reason it is being left as-is.
4014 */
4015 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4016 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004017 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 TAG, "Finishing activity: token=" + token
4019 + ", result=" + resultCode + ", data=" + resultData);
4020
Dianne Hackborn75b03852009-06-12 15:43:26 -07004021 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 if (index < 0) {
4023 return false;
4024 }
4025 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4026
4027 // Is this the last activity left?
4028 boolean lastActivity = true;
4029 for (int i=mHistory.size()-1; i>=0; i--) {
4030 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4031 if (!p.finishing && p != r) {
4032 lastActivity = false;
4033 break;
4034 }
4035 }
4036
4037 // If this is the last activity, but it is the home activity, then
4038 // just don't finish it.
4039 if (lastActivity) {
4040 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4041 return false;
4042 }
4043 }
4044
4045 finishActivityLocked(r, index, resultCode, resultData, reason);
4046 return true;
4047 }
4048
4049 /**
4050 * @return Returns true if this activity has been removed from the history
4051 * list, or false if it is still in the list and will be removed later.
4052 */
4053 private final boolean finishActivityLocked(HistoryRecord r, int index,
4054 int resultCode, Intent resultData, String reason) {
4055 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004056 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 return false;
4058 }
4059
4060 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004061 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004062 System.identityHashCode(r),
4063 r.task.taskId, r.shortComponentName, reason);
4064 r.task.numActivities--;
4065 if (r.frontOfTask && index < (mHistory.size()-1)) {
4066 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4067 if (next.task == r.task) {
4068 next.frontOfTask = true;
4069 }
4070 }
4071
4072 r.pauseKeyDispatchingLocked();
4073 if (mFocusedActivity == r) {
4074 setFocusedActivityLocked(topRunningActivityLocked(null));
4075 }
4076
4077 // send the result
4078 HistoryRecord resultTo = r.resultTo;
4079 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004080 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004081 + " who=" + r.resultWho + " req=" + r.requestCode
4082 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004083 if (r.info.applicationInfo.uid > 0) {
4084 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4085 r.packageName, resultData, r);
4086 }
4087 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4088 resultData);
4089 r.resultTo = null;
4090 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004091 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004092
4093 // Make sure this HistoryRecord is not holding on to other resources,
4094 // because clients have remote IPC references to this object so we
4095 // can't assume that will go away and want to avoid circular IPC refs.
4096 r.results = null;
4097 r.pendingResults = null;
4098 r.newIntents = null;
4099 r.icicle = null;
4100
4101 if (mPendingThumbnails.size() > 0) {
4102 // There are clients waiting to receive thumbnails so, in case
4103 // this is an activity that someone is waiting for, add it
4104 // to the pending list so we can correctly update the clients.
4105 mCancelledThumbnails.add(r);
4106 }
4107
4108 if (mResumedActivity == r) {
4109 boolean endTask = index <= 0
4110 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004111 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004112 "Prepare close transition: finishing " + r);
4113 mWindowManager.prepareAppTransition(endTask
4114 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4115 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4116
4117 // Tell window manager to prepare for this one to be removed.
4118 mWindowManager.setAppVisibility(r, false);
4119
4120 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004121 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4122 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 startPausingLocked(false, false);
4124 }
4125
4126 } else if (r.state != ActivityState.PAUSING) {
4127 // If the activity is PAUSING, we will complete the finish once
4128 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004129 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 return finishCurrentActivityLocked(r, index,
4131 FINISH_AFTER_PAUSE) == null;
4132 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004133 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004134 }
4135
4136 return false;
4137 }
4138
4139 private static final int FINISH_IMMEDIATELY = 0;
4140 private static final int FINISH_AFTER_PAUSE = 1;
4141 private static final int FINISH_AFTER_VISIBLE = 2;
4142
4143 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4144 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004145 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004146 if (index < 0) {
4147 return null;
4148 }
4149
4150 return finishCurrentActivityLocked(r, index, mode);
4151 }
4152
4153 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4154 int index, int mode) {
4155 // First things first: if this activity is currently visible,
4156 // and the resumed activity is not yet visible, then hold off on
4157 // finishing until the resumed one becomes visible.
4158 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4159 if (!mStoppingActivities.contains(r)) {
4160 mStoppingActivities.add(r);
4161 if (mStoppingActivities.size() > 3) {
4162 // If we already have a few activities waiting to stop,
4163 // then give up on things going idle and start clearing
4164 // them out.
4165 Message msg = Message.obtain();
4166 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4167 mHandler.sendMessage(msg);
4168 }
4169 }
4170 r.state = ActivityState.STOPPING;
4171 updateOomAdjLocked();
4172 return r;
4173 }
4174
4175 // make sure the record is cleaned out of other places.
4176 mStoppingActivities.remove(r);
4177 mWaitingVisibleActivities.remove(r);
4178 if (mResumedActivity == r) {
4179 mResumedActivity = null;
4180 }
4181 final ActivityState prevState = r.state;
4182 r.state = ActivityState.FINISHING;
4183
4184 if (mode == FINISH_IMMEDIATELY
4185 || prevState == ActivityState.STOPPED
4186 || prevState == ActivityState.INITIALIZING) {
4187 // If this activity is already stopped, we can just finish
4188 // it right now.
4189 return destroyActivityLocked(r, true) ? null : r;
4190 } else {
4191 // Need to go through the full pause cycle to get this
4192 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004193 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 mFinishingActivities.add(r);
4195 resumeTopActivityLocked(null);
4196 }
4197 return r;
4198 }
4199
4200 /**
4201 * This is the internal entry point for handling Activity.finish().
4202 *
4203 * @param token The Binder token referencing the Activity we want to finish.
4204 * @param resultCode Result code, if any, from this Activity.
4205 * @param resultData Result data (Intent), if any, from this Activity.
4206 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004207 * @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 -08004208 */
4209 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4210 // Refuse possible leaked file descriptors
4211 if (resultData != null && resultData.hasFileDescriptors() == true) {
4212 throw new IllegalArgumentException("File descriptors passed in Intent");
4213 }
4214
4215 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004216 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 // Find the first activity that is not finishing.
4218 HistoryRecord next = topRunningActivityLocked(token, 0);
4219 if (next != null) {
4220 // ask watcher if this is allowed
4221 boolean resumeOK = true;
4222 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004223 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004225 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004226 }
4227
4228 if (!resumeOK) {
4229 return false;
4230 }
4231 }
4232 }
4233 final long origId = Binder.clearCallingIdentity();
4234 boolean res = requestFinishActivityLocked(token, resultCode,
4235 resultData, "app-request");
4236 Binder.restoreCallingIdentity(origId);
4237 return res;
4238 }
4239 }
4240
4241 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4242 String resultWho, int requestCode, int resultCode, Intent data) {
4243
4244 if (callingUid > 0) {
4245 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4246 data, r);
4247 }
4248
Joe Onorato8a9b2202010-02-26 18:56:32 -08004249 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004250 + " : who=" + resultWho + " req=" + requestCode
4251 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004252 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4253 try {
4254 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4255 list.add(new ResultInfo(resultWho, requestCode,
4256 resultCode, data));
4257 r.app.thread.scheduleSendResult(r, list);
4258 return;
4259 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004260 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004261 }
4262 }
4263
4264 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4265 }
4266
4267 public final void finishSubActivity(IBinder token, String resultWho,
4268 int requestCode) {
4269 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004270 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 if (index < 0) {
4272 return;
4273 }
4274 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4275
4276 final long origId = Binder.clearCallingIdentity();
4277
4278 int i;
4279 for (i=mHistory.size()-1; i>=0; i--) {
4280 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4281 if (r.resultTo == self && r.requestCode == requestCode) {
4282 if ((r.resultWho == null && resultWho == null) ||
4283 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4284 finishActivityLocked(r, i,
4285 Activity.RESULT_CANCELED, null, "request-sub");
4286 }
4287 }
4288 }
4289
4290 Binder.restoreCallingIdentity(origId);
4291 }
4292 }
4293
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004294 public boolean willActivityBeVisible(IBinder token) {
4295 synchronized(this) {
4296 int i;
4297 for (i=mHistory.size()-1; i>=0; i--) {
4298 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4299 if (r == token) {
4300 return true;
4301 }
4302 if (r.fullscreen && !r.finishing) {
4303 return false;
4304 }
4305 }
4306 return true;
4307 }
4308 }
4309
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004310 public void overridePendingTransition(IBinder token, String packageName,
4311 int enterAnim, int exitAnim) {
4312 synchronized(this) {
4313 int index = indexOfTokenLocked(token);
4314 if (index < 0) {
4315 return;
4316 }
4317 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4318
4319 final long origId = Binder.clearCallingIdentity();
4320
4321 if (self.state == ActivityState.RESUMED
4322 || self.state == ActivityState.PAUSING) {
4323 mWindowManager.overridePendingAppTransition(packageName,
4324 enterAnim, exitAnim);
4325 }
4326
4327 Binder.restoreCallingIdentity(origId);
4328 }
4329 }
4330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004331 /**
4332 * Perform clean-up of service connections in an activity record.
4333 */
4334 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4335 // Throw away any services that have been bound by this activity.
4336 if (r.connections != null) {
4337 Iterator<ConnectionRecord> it = r.connections.iterator();
4338 while (it.hasNext()) {
4339 ConnectionRecord c = it.next();
4340 removeConnectionLocked(c, null, r);
4341 }
4342 r.connections = null;
4343 }
4344 }
4345
4346 /**
4347 * Perform the common clean-up of an activity record. This is called both
4348 * as part of destroyActivityLocked() (when destroying the client-side
4349 * representation) and cleaning things up as a result of its hosting
4350 * processing going away, in which case there is no remaining client-side
4351 * state to destroy so only the cleanup here is needed.
4352 */
4353 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4354 if (mResumedActivity == r) {
4355 mResumedActivity = null;
4356 }
4357 if (mFocusedActivity == r) {
4358 mFocusedActivity = null;
4359 }
4360
4361 r.configDestroy = false;
4362 r.frozenBeforeDestroy = false;
4363
4364 // Make sure this record is no longer in the pending finishes list.
4365 // This could happen, for example, if we are trimming activities
4366 // down to the max limit while they are still waiting to finish.
4367 mFinishingActivities.remove(r);
4368 mWaitingVisibleActivities.remove(r);
4369
4370 // Remove any pending results.
4371 if (r.finishing && r.pendingResults != null) {
4372 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4373 PendingIntentRecord rec = apr.get();
4374 if (rec != null) {
4375 cancelIntentSenderLocked(rec, false);
4376 }
4377 }
4378 r.pendingResults = null;
4379 }
4380
4381 if (cleanServices) {
4382 cleanUpActivityServicesLocked(r);
4383 }
4384
4385 if (mPendingThumbnails.size() > 0) {
4386 // There are clients waiting to receive thumbnails so, in case
4387 // this is an activity that someone is waiting for, add it
4388 // to the pending list so we can correctly update the clients.
4389 mCancelledThumbnails.add(r);
4390 }
4391
4392 // Get rid of any pending idle timeouts.
4393 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4394 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4395 }
4396
4397 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4398 if (r.state != ActivityState.DESTROYED) {
4399 mHistory.remove(r);
4400 r.inHistory = false;
4401 r.state = ActivityState.DESTROYED;
4402 mWindowManager.removeAppToken(r);
4403 if (VALIDATE_TOKENS) {
4404 mWindowManager.validateAppTokens(mHistory);
4405 }
4406 cleanUpActivityServicesLocked(r);
4407 removeActivityUriPermissionsLocked(r);
4408 }
4409 }
4410
4411 /**
4412 * Destroy the current CLIENT SIDE instance of an activity. This may be
4413 * called both when actually finishing an activity, or when performing
4414 * a configuration switch where we destroy the current client-side object
4415 * but then create a new client-side object for this same HistoryRecord.
4416 */
4417 private final boolean destroyActivityLocked(HistoryRecord r,
4418 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004419 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004420 TAG, "Removing activity: token=" + r
4421 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004422 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 System.identityHashCode(r),
4424 r.task.taskId, r.shortComponentName);
4425
4426 boolean removedFromHistory = false;
4427
4428 cleanUpActivityLocked(r, false);
4429
Dianne Hackborn03abb812010-01-04 18:43:19 -08004430 final boolean hadApp = r.app != null;
4431
4432 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004433 if (removeFromApp) {
4434 int idx = r.app.activities.indexOf(r);
4435 if (idx >= 0) {
4436 r.app.activities.remove(idx);
4437 }
4438 if (r.persistent) {
4439 decPersistentCountLocked(r.app);
4440 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004441 if (r.app.activities.size() == 0) {
4442 // No longer have activities, so update location in
4443 // LRU list.
4444 updateLruProcessLocked(r.app, true, false);
4445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004446 }
4447
4448 boolean skipDestroy = false;
4449
4450 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004451 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004452 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4453 r.configChangeFlags);
4454 } catch (Exception e) {
4455 // We can just ignore exceptions here... if the process
4456 // has crashed, our death notification will clean things
4457 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004458 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004459 if (r.finishing) {
4460 removeActivityFromHistoryLocked(r);
4461 removedFromHistory = true;
4462 skipDestroy = true;
4463 }
4464 }
4465
4466 r.app = null;
4467 r.nowVisible = false;
4468
4469 if (r.finishing && !skipDestroy) {
4470 r.state = ActivityState.DESTROYING;
4471 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4472 msg.obj = r;
4473 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4474 } else {
4475 r.state = ActivityState.DESTROYED;
4476 }
4477 } else {
4478 // remove this record from the history.
4479 if (r.finishing) {
4480 removeActivityFromHistoryLocked(r);
4481 removedFromHistory = true;
4482 } else {
4483 r.state = ActivityState.DESTROYED;
4484 }
4485 }
4486
4487 r.configChangeFlags = 0;
4488
Dianne Hackborn03abb812010-01-04 18:43:19 -08004489 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004490 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 }
4492
4493 return removedFromHistory;
4494 }
4495
Dianne Hackborn03abb812010-01-04 18:43:19 -08004496 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004498 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004499 TAG, "Removing app " + app + " from list " + list
4500 + " with " + i + " entries");
4501 while (i > 0) {
4502 i--;
4503 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004504 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4506 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004507 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 list.remove(i);
4509 }
4510 }
4511 }
4512
4513 /**
4514 * Main function for removing an existing process from the activity manager
4515 * as a result of that process going away. Clears out all connections
4516 * to the process.
4517 */
4518 private final void handleAppDiedLocked(ProcessRecord app,
4519 boolean restarting) {
4520 cleanUpApplicationRecordLocked(app, restarting, -1);
4521 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004522 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004523 }
4524
4525 // Just in case...
4526 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004527 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004528 mPausingActivity = null;
4529 }
4530 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4531 mLastPausedActivity = null;
4532 }
4533
4534 // Remove this application's activities from active lists.
4535 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4536 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4537 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4538 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4539
4540 boolean atTop = true;
4541 boolean hasVisibleActivities = false;
4542
4543 // Clean out the history list.
4544 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004545 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004546 TAG, "Removing app " + app + " from history with " + i + " entries");
4547 while (i > 0) {
4548 i--;
4549 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004550 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4552 if (r.app == app) {
4553 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004554 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004555 TAG, "Removing this entry! frozen=" + r.haveState
4556 + " finishing=" + r.finishing);
4557 mHistory.remove(i);
4558
4559 r.inHistory = false;
4560 mWindowManager.removeAppToken(r);
4561 if (VALIDATE_TOKENS) {
4562 mWindowManager.validateAppTokens(mHistory);
4563 }
4564 removeActivityUriPermissionsLocked(r);
4565
4566 } else {
4567 // We have the current state for this activity, so
4568 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004569 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004570 TAG, "Keeping entry, setting app to null");
4571 if (r.visible) {
4572 hasVisibleActivities = true;
4573 }
4574 r.app = null;
4575 r.nowVisible = false;
4576 if (!r.haveState) {
4577 r.icicle = null;
4578 }
4579 }
4580
4581 cleanUpActivityLocked(r, true);
4582 r.state = ActivityState.STOPPED;
4583 }
4584 atTop = false;
4585 }
4586
4587 app.activities.clear();
4588
4589 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004590 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591 + " running instrumentation " + app.instrumentationClass);
4592 Bundle info = new Bundle();
4593 info.putString("shortMsg", "Process crashed.");
4594 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4595 }
4596
4597 if (!restarting) {
4598 if (!resumeTopActivityLocked(null)) {
4599 // If there was nothing to resume, and we are not already
4600 // restarting this process, but there is a visible activity that
4601 // is hosted by the process... then make sure all visible
4602 // activities are running, taking care of restarting this
4603 // process.
4604 if (hasVisibleActivities) {
4605 ensureActivitiesVisibleLocked(null, 0);
4606 }
4607 }
4608 }
4609 }
4610
4611 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4612 IBinder threadBinder = thread.asBinder();
4613
4614 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004615 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4616 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004617 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4618 return i;
4619 }
4620 }
4621 return -1;
4622 }
4623
4624 private final ProcessRecord getRecordForAppLocked(
4625 IApplicationThread thread) {
4626 if (thread == null) {
4627 return null;
4628 }
4629
4630 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004631 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004632 }
4633
4634 private final void appDiedLocked(ProcessRecord app, int pid,
4635 IApplicationThread thread) {
4636
4637 mProcDeaths[0]++;
4638
Magnus Edlund7bb25812010-02-24 15:45:06 +01004639 // Clean up already done if the process has been re-started.
4640 if (app.pid == pid && app.thread != null &&
4641 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004642 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004644 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004645 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004646 TAG, "Dying app: " + app + ", pid: " + pid
4647 + ", thread: " + thread.asBinder());
4648 boolean doLowMem = app.instrumentationClass == null;
4649 handleAppDiedLocked(app, false);
4650
4651 if (doLowMem) {
4652 // If there are no longer any background processes running,
4653 // and the app that died was not running instrumentation,
4654 // then tell everyone we are now low on memory.
4655 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004656 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4657 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004658 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4659 haveBg = true;
4660 break;
4661 }
4662 }
4663
4664 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004665 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004666 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004667 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004668 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4669 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004670 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004671 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4672 // The low memory report is overriding any current
4673 // state for a GC request. Make sure to do
4674 // visible/foreground processes first.
4675 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4676 rec.lastRequestedGc = 0;
4677 } else {
4678 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004680 rec.reportLowMemory = true;
4681 rec.lastLowMemory = now;
4682 mProcessesToGc.remove(rec);
4683 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 }
4685 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004686 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 }
4688 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004689 } else if (app.pid != pid) {
4690 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004691 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004692 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004693 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004694 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004695 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004696 + thread.asBinder());
4697 }
4698 }
4699
Dan Egnor42471dd2010-01-07 17:25:22 -08004700 /**
4701 * If a stack trace dump file is configured, dump process stack traces.
4702 * @param pids of dalvik VM processes to dump stack traces for
4703 * @return file containing stack traces, or null if no dump file is configured
4704 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004705 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004706 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4707 if (tracesPath == null || tracesPath.length() == 0) {
4708 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004710
4711 File tracesFile = new File(tracesPath);
4712 try {
4713 File tracesDir = tracesFile.getParentFile();
4714 if (!tracesDir.exists()) tracesFile.mkdirs();
4715 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4716
4717 if (tracesFile.exists()) tracesFile.delete();
4718 tracesFile.createNewFile();
4719 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4720 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004721 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004722 return null;
4723 }
4724
4725 // Use a FileObserver to detect when traces finish writing.
4726 // The order of traces is considered important to maintain for legibility.
4727 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4728 public synchronized void onEvent(int event, String path) { notify(); }
4729 };
4730
4731 try {
4732 observer.startWatching();
4733 int num = pids.size();
4734 for (int i = 0; i < num; i++) {
4735 synchronized (observer) {
4736 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4737 observer.wait(200); // Wait for write-close, give up after 200msec
4738 }
4739 }
4740 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004741 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004742 } finally {
4743 observer.stopWatching();
4744 }
4745
4746 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 }
4748
Dan Egnor42471dd2010-01-07 17:25:22 -08004749 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4750 HistoryRecord parent, final String annotation) {
Mike Lockwoodb62f9592010-03-12 07:55:23 -05004751 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4752 if (mShuttingDown || app.notResponding || app.crashing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004753 return;
4754 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004757 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4758 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759
Dan Egnor42471dd2010-01-07 17:25:22 -08004760 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4761 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4762 pids.add(app.pid);
4763
4764 int parentPid = app.pid;
4765 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4766 if (parentPid != app.pid) pids.add(parentPid);
4767
4768 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4769
4770 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4771 ProcessRecord r = mLruProcesses.get(i);
4772 if (r != null && r.thread != null) {
4773 int pid = r.pid;
4774 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775 }
4776 }
4777
Dan Egnor42471dd2010-01-07 17:25:22 -08004778 File tracesFile = dumpStackTraces(pids);
4779
4780 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004781 StringBuilder info = mStringBuilder;
4782 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004783 info.append("ANR in ").append(app.processName);
4784 if (activity != null && activity.shortComponentName != null) {
4785 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004786 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004787 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004789 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004790 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004791 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004792 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004794
Dan Egnor42471dd2010-01-07 17:25:22 -08004795 String cpuInfo = null;
4796 if (MONITOR_CPU_USAGE) {
4797 updateCpuStatsNow();
4798 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4799 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 }
4801
Joe Onorato8a9b2202010-02-26 18:56:32 -08004802 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004803 if (tracesFile == null) {
4804 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4805 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4806 }
4807
4808 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4809
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004810 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004812 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4813 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004815 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4816 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004817 }
4818 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004819 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004820 }
4821 }
4822
Dan Egnor42471dd2010-01-07 17:25:22 -08004823 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4824 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4825 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4826 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4827 Process.killProcess(app.pid);
4828 return;
4829 }
4830
4831 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 makeAppNotRespondingLocked(app,
4833 activity != null ? activity.shortComponentName : null,
4834 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004835 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004836
4837 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 Message msg = Message.obtain();
4839 HashMap map = new HashMap();
4840 msg.what = SHOW_NOT_RESPONDING_MSG;
4841 msg.obj = map;
4842 map.put("app", app);
4843 if (activity != null) {
4844 map.put("activity", activity);
4845 }
4846
4847 mHandler.sendMessage(msg);
4848 return;
4849 }
4850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851 private final void decPersistentCountLocked(ProcessRecord app)
4852 {
4853 app.persistentActivities--;
4854 if (app.persistentActivities > 0) {
4855 // Still more of 'em...
4856 return;
4857 }
4858 if (app.persistent) {
4859 // Ah, but the application itself is persistent. Whatever!
4860 return;
4861 }
4862
4863 // App is no longer persistent... make sure it and the ones
4864 // following it in the LRU list have the correc oom_adj.
4865 updateOomAdjLocked();
4866 }
4867
4868 public void setPersistent(IBinder token, boolean isPersistent) {
4869 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4870 != PackageManager.PERMISSION_GRANTED) {
4871 String msg = "Permission Denial: setPersistent() from pid="
4872 + Binder.getCallingPid()
4873 + ", uid=" + Binder.getCallingUid()
4874 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004875 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 throw new SecurityException(msg);
4877 }
4878
4879 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004880 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 if (index < 0) {
4882 return;
4883 }
4884 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4885 ProcessRecord app = r.app;
4886
Joe Onorato8a9b2202010-02-26 18:56:32 -08004887 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004888 TAG, "Setting persistence " + isPersistent + ": " + r);
4889
4890 if (isPersistent) {
4891 if (r.persistent) {
4892 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004893 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004894 return;
4895 }
4896 r.persistent = true;
4897 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004898 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004899 if (app.persistentActivities > 1) {
4900 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004901 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004902 return;
4903 }
4904 if (app.persistent) {
4905 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004906 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004907 return;
4908 }
4909
4910 // App is now persistent... make sure it and the ones
4911 // following it now have the correct oom_adj.
4912 final long origId = Binder.clearCallingIdentity();
4913 updateOomAdjLocked();
4914 Binder.restoreCallingIdentity(origId);
4915
4916 } else {
4917 if (!r.persistent) {
4918 // Okay okay, I heard you already!
4919 return;
4920 }
4921 r.persistent = false;
4922 final long origId = Binder.clearCallingIdentity();
4923 decPersistentCountLocked(app);
4924 Binder.restoreCallingIdentity(origId);
4925
4926 }
4927 }
4928 }
4929
4930 public boolean clearApplicationUserData(final String packageName,
4931 final IPackageDataObserver observer) {
4932 int uid = Binder.getCallingUid();
4933 int pid = Binder.getCallingPid();
4934 long callingId = Binder.clearCallingIdentity();
4935 try {
4936 IPackageManager pm = ActivityThread.getPackageManager();
4937 int pkgUid = -1;
4938 synchronized(this) {
4939 try {
4940 pkgUid = pm.getPackageUid(packageName);
4941 } catch (RemoteException e) {
4942 }
4943 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004944 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 return false;
4946 }
4947 if (uid == pkgUid || checkComponentPermission(
4948 android.Manifest.permission.CLEAR_APP_USER_DATA,
4949 pid, uid, -1)
4950 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004951 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 } else {
4953 throw new SecurityException(pid+" does not have permission:"+
4954 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4955 "for process:"+packageName);
4956 }
4957 }
4958
4959 try {
4960 //clear application user data
4961 pm.clearApplicationUserData(packageName, observer);
4962 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4963 Uri.fromParts("package", packageName, null));
4964 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06004965 synchronized (this) {
4966 broadcastIntentLocked(null, null, intent,
4967 null, null, 0, null, null, null,
4968 false, false, MY_PID, Process.SYSTEM_UID);
4969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004970 } catch (RemoteException e) {
4971 }
4972 } finally {
4973 Binder.restoreCallingIdentity(callingId);
4974 }
4975 return true;
4976 }
4977
Dianne Hackborn03abb812010-01-04 18:43:19 -08004978 public void killBackgroundProcesses(final String packageName) {
4979 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4980 != PackageManager.PERMISSION_GRANTED &&
4981 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4982 != PackageManager.PERMISSION_GRANTED) {
4983 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 + Binder.getCallingPid()
4985 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004986 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004987 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 throw new SecurityException(msg);
4989 }
4990
4991 long callingId = Binder.clearCallingIdentity();
4992 try {
4993 IPackageManager pm = ActivityThread.getPackageManager();
4994 int pkgUid = -1;
4995 synchronized(this) {
4996 try {
4997 pkgUid = pm.getPackageUid(packageName);
4998 } catch (RemoteException e) {
4999 }
5000 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005001 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 return;
5003 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005004 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005005 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005006 }
5007 } finally {
5008 Binder.restoreCallingIdentity(callingId);
5009 }
5010 }
5011
5012 public void forceStopPackage(final String packageName) {
5013 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5014 != PackageManager.PERMISSION_GRANTED) {
5015 String msg = "Permission Denial: forceStopPackage() from pid="
5016 + Binder.getCallingPid()
5017 + ", uid=" + Binder.getCallingUid()
5018 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005019 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005020 throw new SecurityException(msg);
5021 }
5022
5023 long callingId = Binder.clearCallingIdentity();
5024 try {
5025 IPackageManager pm = ActivityThread.getPackageManager();
5026 int pkgUid = -1;
5027 synchronized(this) {
5028 try {
5029 pkgUid = pm.getPackageUid(packageName);
5030 } catch (RemoteException e) {
5031 }
5032 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005033 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005034 return;
5035 }
5036 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 }
5038 } finally {
5039 Binder.restoreCallingIdentity(callingId);
5040 }
5041 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005042
5043 /*
5044 * The pkg name and uid have to be specified.
5045 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5046 */
5047 public void killApplicationWithUid(String pkg, int uid) {
5048 if (pkg == null) {
5049 return;
5050 }
5051 // Make sure the uid is valid.
5052 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005053 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005054 return;
5055 }
5056 int callerUid = Binder.getCallingUid();
5057 // Only the system server can kill an application
5058 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005059 // Post an aysnc message to kill the application
5060 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5061 msg.arg1 = uid;
5062 msg.arg2 = 0;
5063 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005064 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005065 } else {
5066 throw new SecurityException(callerUid + " cannot kill pkg: " +
5067 pkg);
5068 }
5069 }
5070
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005071 public void closeSystemDialogs(String reason) {
5072 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5073 if (reason != null) {
5074 intent.putExtra("reason", reason);
5075 }
5076
5077 final int uid = Binder.getCallingUid();
5078 final long origId = Binder.clearCallingIdentity();
5079 synchronized (this) {
5080 int i = mWatchers.beginBroadcast();
5081 while (i > 0) {
5082 i--;
5083 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5084 if (w != null) {
5085 try {
5086 w.closingSystemDialogs(reason);
5087 } catch (RemoteException e) {
5088 }
5089 }
5090 }
5091 mWatchers.finishBroadcast();
5092
Dianne Hackbornffa42482009-09-23 22:20:11 -07005093 mWindowManager.closeSystemDialogs(reason);
5094
5095 for (i=mHistory.size()-1; i>=0; i--) {
5096 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5097 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5098 finishActivityLocked(r, i,
5099 Activity.RESULT_CANCELED, null, "close-sys");
5100 }
5101 }
5102
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005103 broadcastIntentLocked(null, null, intent, null,
5104 null, 0, null, null, null, false, false, -1, uid);
5105 }
5106 Binder.restoreCallingIdentity(origId);
5107 }
5108
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005109 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005110 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005111 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5112 for (int i=pids.length-1; i>=0; i--) {
5113 infos[i] = new Debug.MemoryInfo();
5114 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005115 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005116 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005117 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005118
5119 public void killApplicationProcess(String processName, int uid) {
5120 if (processName == null) {
5121 return;
5122 }
5123
5124 int callerUid = Binder.getCallingUid();
5125 // Only the system server can kill an application
5126 if (callerUid == Process.SYSTEM_UID) {
5127 synchronized (this) {
5128 ProcessRecord app = getProcessRecordLocked(processName, uid);
5129 if (app != null) {
5130 try {
5131 app.thread.scheduleSuicide();
5132 } catch (RemoteException e) {
5133 // If the other end already died, then our work here is done.
5134 }
5135 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005136 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005137 + processName + " / " + uid);
5138 }
5139 }
5140 } else {
5141 throw new SecurityException(callerUid + " cannot kill app process: " +
5142 processName);
5143 }
5144 }
5145
Dianne Hackborn03abb812010-01-04 18:43:19 -08005146 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005147 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005148 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5149 Uri.fromParts("package", packageName, null));
5150 intent.putExtra(Intent.EXTRA_UID, uid);
5151 broadcastIntentLocked(null, null, intent,
5152 null, null, 0, null, null, null,
5153 false, false, MY_PID, Process.SYSTEM_UID);
5154 }
5155
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005156 private final boolean killPackageProcessesLocked(String packageName, int uid,
5157 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005158 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005159
Dianne Hackborn03abb812010-01-04 18:43:19 -08005160 // Remove all processes this package may have touched: all with the
5161 // same UID (except for the system or root user), and all whose name
5162 // matches the package name.
5163 final String procNamePrefix = packageName + ":";
5164 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5165 final int NA = apps.size();
5166 for (int ia=0; ia<NA; ia++) {
5167 ProcessRecord app = apps.valueAt(ia);
5168 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005169 if (doit) {
5170 procs.add(app);
5171 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005172 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5173 || app.processName.equals(packageName)
5174 || app.processName.startsWith(procNamePrefix)) {
5175 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005176 if (!doit) {
5177 return true;
5178 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005179 app.removed = true;
5180 procs.add(app);
5181 }
5182 }
5183 }
5184 }
5185
5186 int N = procs.size();
5187 for (int i=0; i<N; i++) {
5188 removeProcessLocked(procs.get(i), callerWillRestart);
5189 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005190 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005191 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005192
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005193 private final boolean forceStopPackageLocked(String name, int uid,
5194 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 int i, N;
5196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 if (uid < 0) {
5198 try {
5199 uid = ActivityThread.getPackageManager().getPackageUid(name);
5200 } catch (RemoteException e) {
5201 }
5202 }
5203
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005204 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005205 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005206
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005207 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5208 while (badApps.hasNext()) {
5209 SparseArray<Long> ba = badApps.next();
5210 if (ba.get(uid) != null) {
5211 badApps.remove();
5212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005213 }
5214 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005215
5216 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5217 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218
5219 for (i=mHistory.size()-1; i>=0; i--) {
5220 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5221 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005222 if (!doit) {
5223 return true;
5224 }
5225 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005226 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005227 if (r.app != null) {
5228 r.app.removed = true;
5229 }
5230 r.app = null;
5231 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5232 }
5233 }
5234
5235 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5236 for (ServiceRecord service : mServices.values()) {
5237 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005238 if (!doit) {
5239 return true;
5240 }
5241 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005242 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 if (service.app != null) {
5244 service.app.removed = true;
5245 }
5246 service.app = null;
5247 services.add(service);
5248 }
5249 }
5250
5251 N = services.size();
5252 for (i=0; i<N; i++) {
5253 bringDownServiceLocked(services.get(i), true);
5254 }
5255
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005256 if (doit) {
5257 if (purgeCache) {
5258 AttributeCache ac = AttributeCache.instance();
5259 if (ac != null) {
5260 ac.removePackage(name);
5261 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005262 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005263 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005264 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005265
5266 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005267 }
5268
5269 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5270 final String name = app.processName;
5271 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005272 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 TAG, "Force removing process " + app + " (" + name
5274 + "/" + uid + ")");
5275
5276 mProcessNames.remove(name, uid);
5277 boolean needRestart = false;
5278 if (app.pid > 0 && app.pid != MY_PID) {
5279 int pid = app.pid;
5280 synchronized (mPidsSelfLocked) {
5281 mPidsSelfLocked.remove(pid);
5282 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5283 }
5284 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005285 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 Process.killProcess(pid);
5287
5288 if (app.persistent) {
5289 if (!callerWillRestart) {
5290 addAppLocked(app.info);
5291 } else {
5292 needRestart = true;
5293 }
5294 }
5295 } else {
5296 mRemovedProcesses.add(app);
5297 }
5298
5299 return needRestart;
5300 }
5301
5302 private final void processStartTimedOutLocked(ProcessRecord app) {
5303 final int pid = app.pid;
5304 boolean gone = false;
5305 synchronized (mPidsSelfLocked) {
5306 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5307 if (knownApp != null && knownApp.thread == null) {
5308 mPidsSelfLocked.remove(pid);
5309 gone = true;
5310 }
5311 }
5312
5313 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005314 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005315 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005316 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005318 // Take care of any launching providers waiting for this process.
5319 checkAppInLaunchingProvidersLocked(app, true);
5320 // Take care of any services that are waiting for the process.
5321 for (int i=0; i<mPendingServices.size(); i++) {
5322 ServiceRecord sr = mPendingServices.get(i);
5323 if (app.info.uid == sr.appInfo.uid
5324 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005325 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005326 mPendingServices.remove(i);
5327 i--;
5328 bringDownServiceLocked(sr, true);
5329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005331 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005332 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005333 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005334 try {
5335 IBackupManager bm = IBackupManager.Stub.asInterface(
5336 ServiceManager.getService(Context.BACKUP_SERVICE));
5337 bm.agentDisconnected(app.info.packageName);
5338 } catch (RemoteException e) {
5339 // Can't happen; the backup manager is local
5340 }
5341 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005342 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005343 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005344 mPendingBroadcast = null;
5345 scheduleBroadcastsLocked();
5346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005348 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 }
5350 }
5351
5352 private final boolean attachApplicationLocked(IApplicationThread thread,
5353 int pid) {
5354
5355 // Find the application record that is being attached... either via
5356 // the pid if we are running in multiple processes, or just pull the
5357 // next app record if we are emulating process with anonymous threads.
5358 ProcessRecord app;
5359 if (pid != MY_PID && pid >= 0) {
5360 synchronized (mPidsSelfLocked) {
5361 app = mPidsSelfLocked.get(pid);
5362 }
5363 } else if (mStartingProcesses.size() > 0) {
5364 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005365 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005366 } else {
5367 app = null;
5368 }
5369
5370 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005371 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005372 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005373 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005374 if (pid > 0 && pid != MY_PID) {
5375 Process.killProcess(pid);
5376 } else {
5377 try {
5378 thread.scheduleExit();
5379 } catch (Exception e) {
5380 // Ignore exceptions.
5381 }
5382 }
5383 return false;
5384 }
5385
5386 // If this application record is still attached to a previous
5387 // process, clean it up now.
5388 if (app.thread != null) {
5389 handleAppDiedLocked(app, true);
5390 }
5391
5392 // Tell the process all about itself.
5393
Joe Onorato8a9b2202010-02-26 18:56:32 -08005394 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 TAG, "Binding process pid " + pid + " to record " + app);
5396
5397 String processName = app.processName;
5398 try {
5399 thread.asBinder().linkToDeath(new AppDeathRecipient(
5400 app, pid, thread), 0);
5401 } catch (RemoteException e) {
5402 app.resetPackageList();
5403 startProcessLocked(app, "link fail", processName);
5404 return false;
5405 }
5406
Doug Zongker2bec3d42009-12-04 12:52:44 -08005407 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408
5409 app.thread = thread;
5410 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005411 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5412 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005413 app.forcingToForeground = null;
5414 app.foregroundServices = false;
5415 app.debugging = false;
5416
5417 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5418
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005419 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5420 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005422 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005423 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005424 }
5425
Joe Onorato8a9b2202010-02-26 18:56:32 -08005426 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 TAG, "New app record " + app
5428 + " thread=" + thread.asBinder() + " pid=" + pid);
5429 try {
5430 int testMode = IApplicationThread.DEBUG_OFF;
5431 if (mDebugApp != null && mDebugApp.equals(processName)) {
5432 testMode = mWaitForDebugger
5433 ? IApplicationThread.DEBUG_WAIT
5434 : IApplicationThread.DEBUG_ON;
5435 app.debugging = true;
5436 if (mDebugTransient) {
5437 mDebugApp = mOrigDebugApp;
5438 mWaitForDebugger = mOrigWaitForDebugger;
5439 }
5440 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005441
Christopher Tate181fafa2009-05-14 11:12:14 -07005442 // If the app is being launched for restore or full backup, set it up specially
5443 boolean isRestrictedBackupMode = false;
5444 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5445 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5446 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5447 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005448
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005449 ensurePackageDexOpt(app.instrumentationInfo != null
5450 ? app.instrumentationInfo.packageName
5451 : app.info.packageName);
5452 if (app.instrumentationClass != null) {
5453 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005454 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005455 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005456 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005457 thread.bindApplication(processName, app.instrumentationInfo != null
5458 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 app.instrumentationClass, app.instrumentationProfileFile,
5460 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005461 isRestrictedBackupMode || !normalMode,
5462 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005463 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005464 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005465 } catch (Exception e) {
5466 // todo: Yikes! What should we do? For now we will try to
5467 // start another process, but that could easily get us in
5468 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005469 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005470
5471 app.resetPackageList();
5472 startProcessLocked(app, "bind fail", processName);
5473 return false;
5474 }
5475
5476 // Remove this record from the list of starting applications.
5477 mPersistentStartingProcesses.remove(app);
5478 mProcessesOnHold.remove(app);
5479
5480 boolean badApp = false;
5481 boolean didSomething = false;
5482
5483 // See if the top visible activity is waiting to run in this process...
5484 HistoryRecord hr = topRunningActivityLocked(null);
5485 if (hr != null) {
5486 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5487 && processName.equals(hr.processName)) {
5488 try {
5489 if (realStartActivityLocked(hr, app, true, true)) {
5490 didSomething = true;
5491 }
5492 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005493 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494 + hr.intent.getComponent().flattenToShortString(), e);
5495 badApp = true;
5496 }
5497 } else {
5498 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5499 }
5500 }
5501
5502 // Find any services that should be running in this process...
5503 if (!badApp && mPendingServices.size() > 0) {
5504 ServiceRecord sr = null;
5505 try {
5506 for (int i=0; i<mPendingServices.size(); i++) {
5507 sr = mPendingServices.get(i);
5508 if (app.info.uid != sr.appInfo.uid
5509 || !processName.equals(sr.processName)) {
5510 continue;
5511 }
5512
5513 mPendingServices.remove(i);
5514 i--;
5515 realStartServiceLocked(sr, app);
5516 didSomething = true;
5517 }
5518 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005519 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005520 + sr.shortName, e);
5521 badApp = true;
5522 }
5523 }
5524
5525 // Check if the next broadcast receiver is in this process...
5526 BroadcastRecord br = mPendingBroadcast;
5527 if (!badApp && br != null && br.curApp == app) {
5528 try {
5529 mPendingBroadcast = null;
5530 processCurBroadcastLocked(br, app);
5531 didSomething = true;
5532 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005533 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 + br.curComponent.flattenToShortString(), e);
5535 badApp = true;
5536 logBroadcastReceiverDiscard(br);
5537 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5538 br.resultExtras, br.resultAbort, true);
5539 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005540 // We need to reset the state if we fails to start the receiver.
5541 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005542 }
5543 }
5544
Christopher Tate181fafa2009-05-14 11:12:14 -07005545 // Check whether the next backup agent is in this process...
5546 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005547 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005548 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005549 try {
5550 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5551 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005552 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005553 e.printStackTrace();
5554 }
5555 }
5556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005557 if (badApp) {
5558 // todo: Also need to kill application to deal with all
5559 // kinds of exceptions.
5560 handleAppDiedLocked(app, false);
5561 return false;
5562 }
5563
5564 if (!didSomething) {
5565 updateOomAdjLocked();
5566 }
5567
5568 return true;
5569 }
5570
5571 public final void attachApplication(IApplicationThread thread) {
5572 synchronized (this) {
5573 int callingPid = Binder.getCallingPid();
5574 final long origId = Binder.clearCallingIdentity();
5575 attachApplicationLocked(thread, callingPid);
5576 Binder.restoreCallingIdentity(origId);
5577 }
5578 }
5579
Dianne Hackborne88846e2009-09-30 21:34:25 -07005580 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005582 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005583 Binder.restoreCallingIdentity(origId);
5584 }
5585
5586 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5587 boolean remove) {
5588 int N = mStoppingActivities.size();
5589 if (N <= 0) return null;
5590
5591 ArrayList<HistoryRecord> stops = null;
5592
5593 final boolean nowVisible = mResumedActivity != null
5594 && mResumedActivity.nowVisible
5595 && !mResumedActivity.waitingVisible;
5596 for (int i=0; i<N; i++) {
5597 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005598 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 + nowVisible + " waitingVisible=" + s.waitingVisible
5600 + " finishing=" + s.finishing);
5601 if (s.waitingVisible && nowVisible) {
5602 mWaitingVisibleActivities.remove(s);
5603 s.waitingVisible = false;
5604 if (s.finishing) {
5605 // If this activity is finishing, it is sitting on top of
5606 // everyone else but we now know it is no longer needed...
5607 // so get rid of it. Otherwise, we need to go through the
5608 // normal flow and hide it once we determine that it is
5609 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005610 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005611 mWindowManager.setAppVisibility(s, false);
5612 }
5613 }
5614 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005615 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 if (stops == null) {
5617 stops = new ArrayList<HistoryRecord>();
5618 }
5619 stops.add(s);
5620 mStoppingActivities.remove(i);
5621 N--;
5622 i--;
5623 }
5624 }
5625
5626 return stops;
5627 }
5628
5629 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005630 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005631 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 mWindowManager.enableScreenAfterBoot();
5633 }
5634
Dianne Hackborne88846e2009-09-30 21:34:25 -07005635 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5636 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005637 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005638
5639 ArrayList<HistoryRecord> stops = null;
5640 ArrayList<HistoryRecord> finishes = null;
5641 ArrayList<HistoryRecord> thumbnails = null;
5642 int NS = 0;
5643 int NF = 0;
5644 int NT = 0;
5645 IApplicationThread sendThumbnail = null;
5646 boolean booting = false;
5647 boolean enableScreen = false;
5648
5649 synchronized (this) {
5650 if (token != null) {
5651 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5652 }
5653
5654 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005655 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656 if (index >= 0) {
5657 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5658
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005659 if (fromTimeout) {
5660 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5661 }
5662
Dianne Hackborne88846e2009-09-30 21:34:25 -07005663 // This is a hack to semi-deal with a race condition
5664 // in the client where it can be constructed with a
5665 // newer configuration from when we asked it to launch.
5666 // We'll update with whatever configuration it now says
5667 // it used to launch.
5668 if (config != null) {
5669 r.configuration = config;
5670 }
5671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 // No longer need to keep the device awake.
5673 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5674 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5675 mLaunchingActivity.release();
5676 }
5677
5678 // We are now idle. If someone is waiting for a thumbnail from
5679 // us, we can now deliver.
5680 r.idle = true;
5681 scheduleAppGcsLocked();
5682 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5683 sendThumbnail = r.app.thread;
5684 r.thumbnailNeeded = false;
5685 }
5686
5687 // If this activity is fullscreen, set up to hide those under it.
5688
Joe Onorato8a9b2202010-02-26 18:56:32 -08005689 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005690 ensureActivitiesVisibleLocked(null, 0);
5691
Joe Onorato8a9b2202010-02-26 18:56:32 -08005692 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005693 if (!mBooted && !fromTimeout) {
5694 mBooted = true;
5695 enableScreen = true;
5696 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005697
5698 } else if (fromTimeout) {
5699 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 }
5701
5702 // Atomically retrieve all of the other things to do.
5703 stops = processStoppingActivitiesLocked(true);
5704 NS = stops != null ? stops.size() : 0;
5705 if ((NF=mFinishingActivities.size()) > 0) {
5706 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5707 mFinishingActivities.clear();
5708 }
5709 if ((NT=mCancelledThumbnails.size()) > 0) {
5710 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5711 mCancelledThumbnails.clear();
5712 }
5713
5714 booting = mBooting;
5715 mBooting = false;
5716 }
5717
5718 int i;
5719
5720 // Send thumbnail if requested.
5721 if (sendThumbnail != null) {
5722 try {
5723 sendThumbnail.requestThumbnail(token);
5724 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005725 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 sendPendingThumbnail(null, token, null, null, true);
5727 }
5728 }
5729
5730 // Stop any activities that are scheduled to do so but have been
5731 // waiting for the next one to start.
5732 for (i=0; i<NS; i++) {
5733 HistoryRecord r = (HistoryRecord)stops.get(i);
5734 synchronized (this) {
5735 if (r.finishing) {
5736 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5737 } else {
5738 stopActivityLocked(r);
5739 }
5740 }
5741 }
5742
5743 // Finish any activities that are scheduled to do so but have been
5744 // waiting for the next one to start.
5745 for (i=0; i<NF; i++) {
5746 HistoryRecord r = (HistoryRecord)finishes.get(i);
5747 synchronized (this) {
5748 destroyActivityLocked(r, true);
5749 }
5750 }
5751
5752 // Report back to any thumbnail receivers.
5753 for (i=0; i<NT; i++) {
5754 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5755 sendPendingThumbnail(r, null, null, null, true);
5756 }
5757
5758 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005759 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 }
5761
5762 trimApplications();
5763 //dump();
5764 //mWindowManager.dump();
5765
5766 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005767 enableScreenAfterBoot();
5768 }
5769 }
5770
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005771 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005772 IntentFilter pkgFilter = new IntentFilter();
5773 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5774 pkgFilter.addDataScheme("package");
5775 mContext.registerReceiver(new BroadcastReceiver() {
5776 @Override
5777 public void onReceive(Context context, Intent intent) {
5778 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5779 if (pkgs != null) {
5780 for (String pkg : pkgs) {
5781 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5782 setResultCode(Activity.RESULT_OK);
5783 return;
5784 }
5785 }
5786 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005787 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005788 }, pkgFilter);
5789
5790 synchronized (this) {
5791 // Ensure that any processes we had put on hold are now started
5792 // up.
5793 final int NP = mProcessesOnHold.size();
5794 if (NP > 0) {
5795 ArrayList<ProcessRecord> procs =
5796 new ArrayList<ProcessRecord>(mProcessesOnHold);
5797 for (int ip=0; ip<NP; ip++) {
5798 this.startProcessLocked(procs.get(ip), "on-hold", null);
5799 }
5800 }
5801
5802 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5803 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005804 broadcastIntentLocked(null, null,
5805 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5806 null, null, 0, null, null,
5807 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5808 false, false, MY_PID, Process.SYSTEM_UID);
5809 }
5810 }
5811 }
5812
5813 final void ensureBootCompleted() {
5814 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005815 boolean enableScreen;
5816 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005817 booting = mBooting;
5818 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005819 enableScreen = !mBooted;
5820 mBooted = true;
5821 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005822
5823 if (booting) {
5824 finishBooting();
5825 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005826
5827 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005828 enableScreenAfterBoot();
5829 }
5830 }
5831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 public final void activityPaused(IBinder token, Bundle icicle) {
5833 // Refuse possible leaked file descriptors
5834 if (icicle != null && icicle.hasFileDescriptors()) {
5835 throw new IllegalArgumentException("File descriptors passed in Bundle");
5836 }
5837
5838 final long origId = Binder.clearCallingIdentity();
5839 activityPaused(token, icicle, false);
5840 Binder.restoreCallingIdentity(origId);
5841 }
5842
5843 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005844 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005845 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5846 + ", timeout=" + timeout);
5847
5848 HistoryRecord r = null;
5849
5850 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005851 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005852 if (index >= 0) {
5853 r = (HistoryRecord)mHistory.get(index);
5854 if (!timeout) {
5855 r.icicle = icicle;
5856 r.haveState = true;
5857 }
5858 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5859 if (mPausingActivity == r) {
5860 r.state = ActivityState.PAUSED;
5861 completePauseLocked();
5862 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005863 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005864 System.identityHashCode(r), r.shortComponentName,
5865 mPausingActivity != null
5866 ? mPausingActivity.shortComponentName : "(none)");
5867 }
5868 }
5869 }
5870 }
5871
5872 public final void activityStopped(IBinder token, Bitmap thumbnail,
5873 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005874 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005875 TAG, "Activity stopped: token=" + token);
5876
5877 HistoryRecord r = null;
5878
5879 final long origId = Binder.clearCallingIdentity();
5880
5881 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005882 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005883 if (index >= 0) {
5884 r = (HistoryRecord)mHistory.get(index);
5885 r.thumbnail = thumbnail;
5886 r.description = description;
5887 r.stopped = true;
5888 r.state = ActivityState.STOPPED;
5889 if (!r.finishing) {
5890 if (r.configDestroy) {
5891 destroyActivityLocked(r, true);
5892 resumeTopActivityLocked(null);
5893 }
5894 }
5895 }
5896 }
5897
5898 if (r != null) {
5899 sendPendingThumbnail(r, null, null, null, false);
5900 }
5901
5902 trimApplications();
5903
5904 Binder.restoreCallingIdentity(origId);
5905 }
5906
5907 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005908 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005909 synchronized (this) {
5910 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5911
Dianne Hackborn75b03852009-06-12 15:43:26 -07005912 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005913 if (index >= 0) {
5914 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5915 if (r.state == ActivityState.DESTROYING) {
5916 final long origId = Binder.clearCallingIdentity();
5917 removeActivityFromHistoryLocked(r);
5918 Binder.restoreCallingIdentity(origId);
5919 }
5920 }
5921 }
5922 }
5923
5924 public String getCallingPackage(IBinder token) {
5925 synchronized (this) {
5926 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005927 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005928 }
5929 }
5930
5931 public ComponentName getCallingActivity(IBinder token) {
5932 synchronized (this) {
5933 HistoryRecord r = getCallingRecordLocked(token);
5934 return r != null ? r.intent.getComponent() : null;
5935 }
5936 }
5937
5938 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005939 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005940 if (index >= 0) {
5941 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5942 if (r != null) {
5943 return r.resultTo;
5944 }
5945 }
5946 return null;
5947 }
5948
5949 public ComponentName getActivityClassForToken(IBinder token) {
5950 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005951 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005952 if (index >= 0) {
5953 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5954 return r.intent.getComponent();
5955 }
5956 return null;
5957 }
5958 }
5959
5960 public String getPackageForToken(IBinder token) {
5961 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005962 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005963 if (index >= 0) {
5964 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5965 return r.packageName;
5966 }
5967 return null;
5968 }
5969 }
5970
5971 public IIntentSender getIntentSender(int type,
5972 String packageName, IBinder token, String resultWho,
5973 int requestCode, Intent intent, String resolvedType, int flags) {
5974 // Refuse possible leaked file descriptors
5975 if (intent != null && intent.hasFileDescriptors() == true) {
5976 throw new IllegalArgumentException("File descriptors passed in Intent");
5977 }
5978
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005979 if (type == INTENT_SENDER_BROADCAST) {
5980 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5981 throw new IllegalArgumentException(
5982 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5983 }
5984 }
5985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005986 synchronized(this) {
5987 int callingUid = Binder.getCallingUid();
5988 try {
5989 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5990 Process.supportsProcesses()) {
5991 int uid = ActivityThread.getPackageManager()
5992 .getPackageUid(packageName);
5993 if (uid != Binder.getCallingUid()) {
5994 String msg = "Permission Denial: getIntentSender() from pid="
5995 + Binder.getCallingPid()
5996 + ", uid=" + Binder.getCallingUid()
5997 + ", (need uid=" + uid + ")"
5998 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005999 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006000 throw new SecurityException(msg);
6001 }
6002 }
6003 } catch (RemoteException e) {
6004 throw new SecurityException(e);
6005 }
6006 HistoryRecord activity = null;
6007 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006008 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006009 if (index < 0) {
6010 return null;
6011 }
6012 activity = (HistoryRecord)mHistory.get(index);
6013 if (activity.finishing) {
6014 return null;
6015 }
6016 }
6017
6018 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6019 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6020 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6021 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6022 |PendingIntent.FLAG_UPDATE_CURRENT);
6023
6024 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6025 type, packageName, activity, resultWho,
6026 requestCode, intent, resolvedType, flags);
6027 WeakReference<PendingIntentRecord> ref;
6028 ref = mIntentSenderRecords.get(key);
6029 PendingIntentRecord rec = ref != null ? ref.get() : null;
6030 if (rec != null) {
6031 if (!cancelCurrent) {
6032 if (updateCurrent) {
6033 rec.key.requestIntent.replaceExtras(intent);
6034 }
6035 return rec;
6036 }
6037 rec.canceled = true;
6038 mIntentSenderRecords.remove(key);
6039 }
6040 if (noCreate) {
6041 return rec;
6042 }
6043 rec = new PendingIntentRecord(this, key, callingUid);
6044 mIntentSenderRecords.put(key, rec.ref);
6045 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6046 if (activity.pendingResults == null) {
6047 activity.pendingResults
6048 = new HashSet<WeakReference<PendingIntentRecord>>();
6049 }
6050 activity.pendingResults.add(rec.ref);
6051 }
6052 return rec;
6053 }
6054 }
6055
6056 public void cancelIntentSender(IIntentSender sender) {
6057 if (!(sender instanceof PendingIntentRecord)) {
6058 return;
6059 }
6060 synchronized(this) {
6061 PendingIntentRecord rec = (PendingIntentRecord)sender;
6062 try {
6063 int uid = ActivityThread.getPackageManager()
6064 .getPackageUid(rec.key.packageName);
6065 if (uid != Binder.getCallingUid()) {
6066 String msg = "Permission Denial: cancelIntentSender() from pid="
6067 + Binder.getCallingPid()
6068 + ", uid=" + Binder.getCallingUid()
6069 + " is not allowed to cancel packges "
6070 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006071 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006072 throw new SecurityException(msg);
6073 }
6074 } catch (RemoteException e) {
6075 throw new SecurityException(e);
6076 }
6077 cancelIntentSenderLocked(rec, true);
6078 }
6079 }
6080
6081 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6082 rec.canceled = true;
6083 mIntentSenderRecords.remove(rec.key);
6084 if (cleanActivity && rec.key.activity != null) {
6085 rec.key.activity.pendingResults.remove(rec.ref);
6086 }
6087 }
6088
6089 public String getPackageForIntentSender(IIntentSender pendingResult) {
6090 if (!(pendingResult instanceof PendingIntentRecord)) {
6091 return null;
6092 }
6093 synchronized(this) {
6094 try {
6095 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6096 return res.key.packageName;
6097 } catch (ClassCastException e) {
6098 }
6099 }
6100 return null;
6101 }
6102
6103 public void setProcessLimit(int max) {
6104 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6105 "setProcessLimit()");
6106 mProcessLimit = max;
6107 }
6108
6109 public int getProcessLimit() {
6110 return mProcessLimit;
6111 }
6112
6113 void foregroundTokenDied(ForegroundToken token) {
6114 synchronized (ActivityManagerService.this) {
6115 synchronized (mPidsSelfLocked) {
6116 ForegroundToken cur
6117 = mForegroundProcesses.get(token.pid);
6118 if (cur != token) {
6119 return;
6120 }
6121 mForegroundProcesses.remove(token.pid);
6122 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6123 if (pr == null) {
6124 return;
6125 }
6126 pr.forcingToForeground = null;
6127 pr.foregroundServices = false;
6128 }
6129 updateOomAdjLocked();
6130 }
6131 }
6132
6133 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6134 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6135 "setProcessForeground()");
6136 synchronized(this) {
6137 boolean changed = false;
6138
6139 synchronized (mPidsSelfLocked) {
6140 ProcessRecord pr = mPidsSelfLocked.get(pid);
6141 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006142 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006143 return;
6144 }
6145 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6146 if (oldToken != null) {
6147 oldToken.token.unlinkToDeath(oldToken, 0);
6148 mForegroundProcesses.remove(pid);
6149 pr.forcingToForeground = null;
6150 changed = true;
6151 }
6152 if (isForeground && token != null) {
6153 ForegroundToken newToken = new ForegroundToken() {
6154 public void binderDied() {
6155 foregroundTokenDied(this);
6156 }
6157 };
6158 newToken.pid = pid;
6159 newToken.token = token;
6160 try {
6161 token.linkToDeath(newToken, 0);
6162 mForegroundProcesses.put(pid, newToken);
6163 pr.forcingToForeground = token;
6164 changed = true;
6165 } catch (RemoteException e) {
6166 // If the process died while doing this, we will later
6167 // do the cleanup with the process death link.
6168 }
6169 }
6170 }
6171
6172 if (changed) {
6173 updateOomAdjLocked();
6174 }
6175 }
6176 }
6177
6178 // =========================================================
6179 // PERMISSIONS
6180 // =========================================================
6181
6182 static class PermissionController extends IPermissionController.Stub {
6183 ActivityManagerService mActivityManagerService;
6184 PermissionController(ActivityManagerService activityManagerService) {
6185 mActivityManagerService = activityManagerService;
6186 }
6187
6188 public boolean checkPermission(String permission, int pid, int uid) {
6189 return mActivityManagerService.checkPermission(permission, pid,
6190 uid) == PackageManager.PERMISSION_GRANTED;
6191 }
6192 }
6193
6194 /**
6195 * This can be called with or without the global lock held.
6196 */
6197 int checkComponentPermission(String permission, int pid, int uid,
6198 int reqUid) {
6199 // We might be performing an operation on behalf of an indirect binder
6200 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6201 // client identity accordingly before proceeding.
6202 Identity tlsIdentity = sCallerIdentity.get();
6203 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006204 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006205 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6206 uid = tlsIdentity.uid;
6207 pid = tlsIdentity.pid;
6208 }
6209
6210 // Root, system server and our own process get to do everything.
6211 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6212 !Process.supportsProcesses()) {
6213 return PackageManager.PERMISSION_GRANTED;
6214 }
6215 // If the target requires a specific UID, always fail for others.
6216 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006217 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006218 return PackageManager.PERMISSION_DENIED;
6219 }
6220 if (permission == null) {
6221 return PackageManager.PERMISSION_GRANTED;
6222 }
6223 try {
6224 return ActivityThread.getPackageManager()
6225 .checkUidPermission(permission, uid);
6226 } catch (RemoteException e) {
6227 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006228 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006229 }
6230 return PackageManager.PERMISSION_DENIED;
6231 }
6232
6233 /**
6234 * As the only public entry point for permissions checking, this method
6235 * can enforce the semantic that requesting a check on a null global
6236 * permission is automatically denied. (Internally a null permission
6237 * string is used when calling {@link #checkComponentPermission} in cases
6238 * when only uid-based security is needed.)
6239 *
6240 * This can be called with or without the global lock held.
6241 */
6242 public int checkPermission(String permission, int pid, int uid) {
6243 if (permission == null) {
6244 return PackageManager.PERMISSION_DENIED;
6245 }
6246 return checkComponentPermission(permission, pid, uid, -1);
6247 }
6248
6249 /**
6250 * Binder IPC calls go through the public entry point.
6251 * This can be called with or without the global lock held.
6252 */
6253 int checkCallingPermission(String permission) {
6254 return checkPermission(permission,
6255 Binder.getCallingPid(),
6256 Binder.getCallingUid());
6257 }
6258
6259 /**
6260 * This can be called with or without the global lock held.
6261 */
6262 void enforceCallingPermission(String permission, String func) {
6263 if (checkCallingPermission(permission)
6264 == PackageManager.PERMISSION_GRANTED) {
6265 return;
6266 }
6267
6268 String msg = "Permission Denial: " + func + " from pid="
6269 + Binder.getCallingPid()
6270 + ", uid=" + Binder.getCallingUid()
6271 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006272 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006273 throw new SecurityException(msg);
6274 }
6275
6276 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6277 ProviderInfo pi, int uid, int modeFlags) {
6278 try {
6279 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6280 if ((pi.readPermission != null) &&
6281 (pm.checkUidPermission(pi.readPermission, uid)
6282 != PackageManager.PERMISSION_GRANTED)) {
6283 return false;
6284 }
6285 }
6286 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6287 if ((pi.writePermission != null) &&
6288 (pm.checkUidPermission(pi.writePermission, uid)
6289 != PackageManager.PERMISSION_GRANTED)) {
6290 return false;
6291 }
6292 }
6293 return true;
6294 } catch (RemoteException e) {
6295 return false;
6296 }
6297 }
6298
6299 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6300 int modeFlags) {
6301 // Root gets to do everything.
6302 if (uid == 0 || !Process.supportsProcesses()) {
6303 return true;
6304 }
6305 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6306 if (perms == null) return false;
6307 UriPermission perm = perms.get(uri);
6308 if (perm == null) return false;
6309 return (modeFlags&perm.modeFlags) == modeFlags;
6310 }
6311
6312 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6313 // Another redirected-binder-call permissions check as in
6314 // {@link checkComponentPermission}.
6315 Identity tlsIdentity = sCallerIdentity.get();
6316 if (tlsIdentity != null) {
6317 uid = tlsIdentity.uid;
6318 pid = tlsIdentity.pid;
6319 }
6320
6321 // Our own process gets to do everything.
6322 if (pid == MY_PID) {
6323 return PackageManager.PERMISSION_GRANTED;
6324 }
6325 synchronized(this) {
6326 return checkUriPermissionLocked(uri, uid, modeFlags)
6327 ? PackageManager.PERMISSION_GRANTED
6328 : PackageManager.PERMISSION_DENIED;
6329 }
6330 }
6331
6332 private void grantUriPermissionLocked(int callingUid,
6333 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6334 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6335 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6336 if (modeFlags == 0) {
6337 return;
6338 }
6339
Joe Onorato8a9b2202010-02-26 18:56:32 -08006340 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006341 "Requested grant " + targetPkg + " permission to " + uri);
6342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006343 final IPackageManager pm = ActivityThread.getPackageManager();
6344
6345 // If this is not a content: uri, we can't do anything with it.
6346 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006347 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006348 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006349 return;
6350 }
6351
6352 String name = uri.getAuthority();
6353 ProviderInfo pi = null;
6354 ContentProviderRecord cpr
6355 = (ContentProviderRecord)mProvidersByName.get(name);
6356 if (cpr != null) {
6357 pi = cpr.info;
6358 } else {
6359 try {
6360 pi = pm.resolveContentProvider(name,
6361 PackageManager.GET_URI_PERMISSION_PATTERNS);
6362 } catch (RemoteException ex) {
6363 }
6364 }
6365 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006366 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006367 return;
6368 }
6369
6370 int targetUid;
6371 try {
6372 targetUid = pm.getPackageUid(targetPkg);
6373 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006374 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006375 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006376 return;
6377 }
6378 } catch (RemoteException ex) {
6379 return;
6380 }
6381
6382 // First... does the target actually need this permission?
6383 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6384 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006385 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006386 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006387 return;
6388 }
6389
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006390 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006391 if (!pi.grantUriPermissions) {
6392 throw new SecurityException("Provider " + pi.packageName
6393 + "/" + pi.name
6394 + " does not allow granting of Uri permissions (uri "
6395 + uri + ")");
6396 }
6397 if (pi.uriPermissionPatterns != null) {
6398 final int N = pi.uriPermissionPatterns.length;
6399 boolean allowed = false;
6400 for (int i=0; i<N; i++) {
6401 if (pi.uriPermissionPatterns[i] != null
6402 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6403 allowed = true;
6404 break;
6405 }
6406 }
6407 if (!allowed) {
6408 throw new SecurityException("Provider " + pi.packageName
6409 + "/" + pi.name
6410 + " does not allow granting of permission to path of Uri "
6411 + uri);
6412 }
6413 }
6414
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006415 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 // this uri?
6417 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6418 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6419 throw new SecurityException("Uid " + callingUid
6420 + " does not have permission to uri " + uri);
6421 }
6422 }
6423
6424 // Okay! So here we are: the caller has the assumed permission
6425 // to the uri, and the target doesn't. Let's now give this to
6426 // the target.
6427
Joe Onorato8a9b2202010-02-26 18:56:32 -08006428 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006429 "Granting " + targetPkg + " permission to " + uri);
6430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006431 HashMap<Uri, UriPermission> targetUris
6432 = mGrantedUriPermissions.get(targetUid);
6433 if (targetUris == null) {
6434 targetUris = new HashMap<Uri, UriPermission>();
6435 mGrantedUriPermissions.put(targetUid, targetUris);
6436 }
6437
6438 UriPermission perm = targetUris.get(uri);
6439 if (perm == null) {
6440 perm = new UriPermission(targetUid, uri);
6441 targetUris.put(uri, perm);
6442
6443 }
6444 perm.modeFlags |= modeFlags;
6445 if (activity == null) {
6446 perm.globalModeFlags |= modeFlags;
6447 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6448 perm.readActivities.add(activity);
6449 if (activity.readUriPermissions == null) {
6450 activity.readUriPermissions = new HashSet<UriPermission>();
6451 }
6452 activity.readUriPermissions.add(perm);
6453 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6454 perm.writeActivities.add(activity);
6455 if (activity.writeUriPermissions == null) {
6456 activity.writeUriPermissions = new HashSet<UriPermission>();
6457 }
6458 activity.writeUriPermissions.add(perm);
6459 }
6460 }
6461
6462 private void grantUriPermissionFromIntentLocked(int callingUid,
6463 String targetPkg, Intent intent, HistoryRecord activity) {
6464 if (intent == null) {
6465 return;
6466 }
6467 Uri data = intent.getData();
6468 if (data == null) {
6469 return;
6470 }
6471 grantUriPermissionLocked(callingUid, targetPkg, data,
6472 intent.getFlags(), activity);
6473 }
6474
6475 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6476 Uri uri, int modeFlags) {
6477 synchronized(this) {
6478 final ProcessRecord r = getRecordForAppLocked(caller);
6479 if (r == null) {
6480 throw new SecurityException("Unable to find app for caller "
6481 + caller
6482 + " when granting permission to uri " + uri);
6483 }
6484 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006485 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 return;
6487 }
6488 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006489 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006490 return;
6491 }
6492
6493 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6494 null);
6495 }
6496 }
6497
6498 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6499 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6500 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6501 HashMap<Uri, UriPermission> perms
6502 = mGrantedUriPermissions.get(perm.uid);
6503 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006504 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006505 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006506 perms.remove(perm.uri);
6507 if (perms.size() == 0) {
6508 mGrantedUriPermissions.remove(perm.uid);
6509 }
6510 }
6511 }
6512 }
6513
6514 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6515 if (activity.readUriPermissions != null) {
6516 for (UriPermission perm : activity.readUriPermissions) {
6517 perm.readActivities.remove(activity);
6518 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6519 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6520 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6521 removeUriPermissionIfNeededLocked(perm);
6522 }
6523 }
6524 }
6525 if (activity.writeUriPermissions != null) {
6526 for (UriPermission perm : activity.writeUriPermissions) {
6527 perm.writeActivities.remove(activity);
6528 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6529 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6530 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6531 removeUriPermissionIfNeededLocked(perm);
6532 }
6533 }
6534 }
6535 }
6536
6537 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6538 int modeFlags) {
6539 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6540 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6541 if (modeFlags == 0) {
6542 return;
6543 }
6544
Joe Onorato8a9b2202010-02-26 18:56:32 -08006545 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006546 "Revoking all granted permissions to " + uri);
6547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006548 final IPackageManager pm = ActivityThread.getPackageManager();
6549
6550 final String authority = uri.getAuthority();
6551 ProviderInfo pi = null;
6552 ContentProviderRecord cpr
6553 = (ContentProviderRecord)mProvidersByName.get(authority);
6554 if (cpr != null) {
6555 pi = cpr.info;
6556 } else {
6557 try {
6558 pi = pm.resolveContentProvider(authority,
6559 PackageManager.GET_URI_PERMISSION_PATTERNS);
6560 } catch (RemoteException ex) {
6561 }
6562 }
6563 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006564 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006565 return;
6566 }
6567
6568 // Does the caller have this permission on the URI?
6569 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6570 // Right now, if you are not the original owner of the permission,
6571 // you are not allowed to revoke it.
6572 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6573 throw new SecurityException("Uid " + callingUid
6574 + " does not have permission to uri " + uri);
6575 //}
6576 }
6577
6578 // Go through all of the permissions and remove any that match.
6579 final List<String> SEGMENTS = uri.getPathSegments();
6580 if (SEGMENTS != null) {
6581 final int NS = SEGMENTS.size();
6582 int N = mGrantedUriPermissions.size();
6583 for (int i=0; i<N; i++) {
6584 HashMap<Uri, UriPermission> perms
6585 = mGrantedUriPermissions.valueAt(i);
6586 Iterator<UriPermission> it = perms.values().iterator();
6587 toploop:
6588 while (it.hasNext()) {
6589 UriPermission perm = it.next();
6590 Uri targetUri = perm.uri;
6591 if (!authority.equals(targetUri.getAuthority())) {
6592 continue;
6593 }
6594 List<String> targetSegments = targetUri.getPathSegments();
6595 if (targetSegments == null) {
6596 continue;
6597 }
6598 if (targetSegments.size() < NS) {
6599 continue;
6600 }
6601 for (int j=0; j<NS; j++) {
6602 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6603 continue toploop;
6604 }
6605 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006606 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006607 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006608 perm.clearModes(modeFlags);
6609 if (perm.modeFlags == 0) {
6610 it.remove();
6611 }
6612 }
6613 if (perms.size() == 0) {
6614 mGrantedUriPermissions.remove(
6615 mGrantedUriPermissions.keyAt(i));
6616 N--;
6617 i--;
6618 }
6619 }
6620 }
6621 }
6622
6623 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6624 int modeFlags) {
6625 synchronized(this) {
6626 final ProcessRecord r = getRecordForAppLocked(caller);
6627 if (r == null) {
6628 throw new SecurityException("Unable to find app for caller "
6629 + caller
6630 + " when revoking permission to uri " + uri);
6631 }
6632 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006633 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006634 return;
6635 }
6636
6637 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6638 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6639 if (modeFlags == 0) {
6640 return;
6641 }
6642
6643 final IPackageManager pm = ActivityThread.getPackageManager();
6644
6645 final String authority = uri.getAuthority();
6646 ProviderInfo pi = null;
6647 ContentProviderRecord cpr
6648 = (ContentProviderRecord)mProvidersByName.get(authority);
6649 if (cpr != null) {
6650 pi = cpr.info;
6651 } else {
6652 try {
6653 pi = pm.resolveContentProvider(authority,
6654 PackageManager.GET_URI_PERMISSION_PATTERNS);
6655 } catch (RemoteException ex) {
6656 }
6657 }
6658 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006659 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006660 return;
6661 }
6662
6663 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6664 }
6665 }
6666
6667 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6668 synchronized (this) {
6669 ProcessRecord app =
6670 who != null ? getRecordForAppLocked(who) : null;
6671 if (app == null) return;
6672
6673 Message msg = Message.obtain();
6674 msg.what = WAIT_FOR_DEBUGGER_MSG;
6675 msg.obj = app;
6676 msg.arg1 = waiting ? 1 : 0;
6677 mHandler.sendMessage(msg);
6678 }
6679 }
6680
6681 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6682 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006683 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006684 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006685 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006686 }
6687
6688 // =========================================================
6689 // TASK MANAGEMENT
6690 // =========================================================
6691
6692 public List getTasks(int maxNum, int flags,
6693 IThumbnailReceiver receiver) {
6694 ArrayList list = new ArrayList();
6695
6696 PendingThumbnailsRecord pending = null;
6697 IApplicationThread topThumbnail = null;
6698 HistoryRecord topRecord = null;
6699
6700 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006701 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006702 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6703 + ", receiver=" + receiver);
6704
6705 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6706 != PackageManager.PERMISSION_GRANTED) {
6707 if (receiver != null) {
6708 // If the caller wants to wait for pending thumbnails,
6709 // it ain't gonna get them.
6710 try {
6711 receiver.finished();
6712 } catch (RemoteException ex) {
6713 }
6714 }
6715 String msg = "Permission Denial: getTasks() from pid="
6716 + Binder.getCallingPid()
6717 + ", uid=" + Binder.getCallingUid()
6718 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006719 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006720 throw new SecurityException(msg);
6721 }
6722
6723 int pos = mHistory.size()-1;
6724 HistoryRecord next =
6725 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6726 HistoryRecord top = null;
6727 CharSequence topDescription = null;
6728 TaskRecord curTask = null;
6729 int numActivities = 0;
6730 int numRunning = 0;
6731 while (pos >= 0 && maxNum > 0) {
6732 final HistoryRecord r = next;
6733 pos--;
6734 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6735
6736 // Initialize state for next task if needed.
6737 if (top == null ||
6738 (top.state == ActivityState.INITIALIZING
6739 && top.task == r.task)) {
6740 top = r;
6741 topDescription = r.description;
6742 curTask = r.task;
6743 numActivities = numRunning = 0;
6744 }
6745
6746 // Add 'r' into the current task.
6747 numActivities++;
6748 if (r.app != null && r.app.thread != null) {
6749 numRunning++;
6750 }
6751 if (topDescription == null) {
6752 topDescription = r.description;
6753 }
6754
Joe Onorato8a9b2202010-02-26 18:56:32 -08006755 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006756 TAG, r.intent.getComponent().flattenToShortString()
6757 + ": task=" + r.task);
6758
6759 // If the next one is a different task, generate a new
6760 // TaskInfo entry for what we have.
6761 if (next == null || next.task != curTask) {
6762 ActivityManager.RunningTaskInfo ci
6763 = new ActivityManager.RunningTaskInfo();
6764 ci.id = curTask.taskId;
6765 ci.baseActivity = r.intent.getComponent();
6766 ci.topActivity = top.intent.getComponent();
6767 ci.thumbnail = top.thumbnail;
6768 ci.description = topDescription;
6769 ci.numActivities = numActivities;
6770 ci.numRunning = numRunning;
6771 //System.out.println(
6772 // "#" + maxNum + ": " + " descr=" + ci.description);
6773 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006774 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006775 TAG, "State=" + top.state + "Idle=" + top.idle
6776 + " app=" + top.app
6777 + " thr=" + (top.app != null ? top.app.thread : null));
6778 if (top.state == ActivityState.RESUMED
6779 || top.state == ActivityState.PAUSING) {
6780 if (top.idle && top.app != null
6781 && top.app.thread != null) {
6782 topRecord = top;
6783 topThumbnail = top.app.thread;
6784 } else {
6785 top.thumbnailNeeded = true;
6786 }
6787 }
6788 if (pending == null) {
6789 pending = new PendingThumbnailsRecord(receiver);
6790 }
6791 pending.pendingRecords.add(top);
6792 }
6793 list.add(ci);
6794 maxNum--;
6795 top = null;
6796 }
6797 }
6798
6799 if (pending != null) {
6800 mPendingThumbnails.add(pending);
6801 }
6802 }
6803
Joe Onorato8a9b2202010-02-26 18:56:32 -08006804 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006805
6806 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006807 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006808 try {
6809 topThumbnail.requestThumbnail(topRecord);
6810 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006811 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006812 sendPendingThumbnail(null, topRecord, null, null, true);
6813 }
6814 }
6815
6816 if (pending == null && receiver != null) {
6817 // In this case all thumbnails were available and the client
6818 // is being asked to be told when the remaining ones come in...
6819 // which is unusually, since the top-most currently running
6820 // activity should never have a canned thumbnail! Oh well.
6821 try {
6822 receiver.finished();
6823 } catch (RemoteException ex) {
6824 }
6825 }
6826
6827 return list;
6828 }
6829
6830 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6831 int flags) {
6832 synchronized (this) {
6833 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6834 "getRecentTasks()");
6835
6836 final int N = mRecentTasks.size();
6837 ArrayList<ActivityManager.RecentTaskInfo> res
6838 = new ArrayList<ActivityManager.RecentTaskInfo>(
6839 maxNum < N ? maxNum : N);
6840 for (int i=0; i<N && maxNum > 0; i++) {
6841 TaskRecord tr = mRecentTasks.get(i);
6842 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6843 || (tr.intent == null)
6844 || ((tr.intent.getFlags()
6845 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6846 ActivityManager.RecentTaskInfo rti
6847 = new ActivityManager.RecentTaskInfo();
6848 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6849 rti.baseIntent = new Intent(
6850 tr.intent != null ? tr.intent : tr.affinityIntent);
6851 rti.origActivity = tr.origActivity;
6852 res.add(rti);
6853 maxNum--;
6854 }
6855 }
6856 return res;
6857 }
6858 }
6859
6860 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6861 int j;
6862 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6863 TaskRecord jt = startTask;
6864
6865 // First look backwards
6866 for (j=startIndex-1; j>=0; j--) {
6867 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6868 if (r.task != jt) {
6869 jt = r.task;
6870 if (affinity.equals(jt.affinity)) {
6871 return j;
6872 }
6873 }
6874 }
6875
6876 // Now look forwards
6877 final int N = mHistory.size();
6878 jt = startTask;
6879 for (j=startIndex+1; j<N; j++) {
6880 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6881 if (r.task != jt) {
6882 if (affinity.equals(jt.affinity)) {
6883 return j;
6884 }
6885 jt = r.task;
6886 }
6887 }
6888
6889 // Might it be at the top?
6890 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6891 return N-1;
6892 }
6893
6894 return -1;
6895 }
6896
6897 /**
6898 * Perform a reset of the given task, if needed as part of launching it.
6899 * Returns the new HistoryRecord at the top of the task.
6900 */
6901 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6902 HistoryRecord newActivity) {
6903 boolean forceReset = (newActivity.info.flags
6904 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6905 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6906 if ((newActivity.info.flags
6907 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6908 forceReset = true;
6909 }
6910 }
6911
6912 final TaskRecord task = taskTop.task;
6913
6914 // We are going to move through the history list so that we can look
6915 // at each activity 'target' with 'below' either the interesting
6916 // activity immediately below it in the stack or null.
6917 HistoryRecord target = null;
6918 int targetI = 0;
6919 int taskTopI = -1;
6920 int replyChainEnd = -1;
6921 int lastReparentPos = -1;
6922 for (int i=mHistory.size()-1; i>=-1; i--) {
6923 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6924
6925 if (below != null && below.finishing) {
6926 continue;
6927 }
6928 if (target == null) {
6929 target = below;
6930 targetI = i;
6931 // If we were in the middle of a reply chain before this
6932 // task, it doesn't appear like the root of the chain wants
6933 // anything interesting, so drop it.
6934 replyChainEnd = -1;
6935 continue;
6936 }
6937
6938 final int flags = target.info.flags;
6939
6940 final boolean finishOnTaskLaunch =
6941 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6942 final boolean allowTaskReparenting =
6943 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6944
6945 if (target.task == task) {
6946 // We are inside of the task being reset... we'll either
6947 // finish this activity, push it out for another task,
6948 // or leave it as-is. We only do this
6949 // for activities that are not the root of the task (since
6950 // if we finish the root, we may no longer have the task!).
6951 if (taskTopI < 0) {
6952 taskTopI = targetI;
6953 }
6954 if (below != null && below.task == task) {
6955 final boolean clearWhenTaskReset =
6956 (target.intent.getFlags()
6957 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006958 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006959 // If this activity is sending a reply to a previous
6960 // activity, we can't do anything with it now until
6961 // we reach the start of the reply chain.
6962 // XXX note that we are assuming the result is always
6963 // to the previous activity, which is almost always
6964 // the case but we really shouldn't count on.
6965 if (replyChainEnd < 0) {
6966 replyChainEnd = targetI;
6967 }
Ed Heyl73798232009-03-24 21:32:21 -07006968 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006969 && target.taskAffinity != null
6970 && !target.taskAffinity.equals(task.affinity)) {
6971 // If this activity has an affinity for another
6972 // task, then we need to move it out of here. We will
6973 // move it as far out of the way as possible, to the
6974 // bottom of the activity stack. This also keeps it
6975 // correctly ordered with any activities we previously
6976 // moved.
6977 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6978 if (target.taskAffinity != null
6979 && target.taskAffinity.equals(p.task.affinity)) {
6980 // If the activity currently at the bottom has the
6981 // same task affinity as the one we are moving,
6982 // then merge it into the same task.
6983 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006984 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006985 + " out to bottom task " + p.task);
6986 } else {
6987 mCurTask++;
6988 if (mCurTask <= 0) {
6989 mCurTask = 1;
6990 }
6991 target.task = new TaskRecord(mCurTask, target.info, null,
6992 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6993 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006994 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006995 + " out to new task " + target.task);
6996 }
6997 mWindowManager.setAppGroupId(target, task.taskId);
6998 if (replyChainEnd < 0) {
6999 replyChainEnd = targetI;
7000 }
7001 int dstPos = 0;
7002 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7003 p = (HistoryRecord)mHistory.get(srcPos);
7004 if (p.finishing) {
7005 continue;
7006 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007007 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007008 + " out to target's task " + target.task);
7009 task.numActivities--;
7010 p.task = target.task;
7011 target.task.numActivities++;
7012 mHistory.remove(srcPos);
7013 mHistory.add(dstPos, p);
7014 mWindowManager.moveAppToken(dstPos, p);
7015 mWindowManager.setAppGroupId(p, p.task.taskId);
7016 dstPos++;
7017 if (VALIDATE_TOKENS) {
7018 mWindowManager.validateAppTokens(mHistory);
7019 }
7020 i++;
7021 }
7022 if (taskTop == p) {
7023 taskTop = below;
7024 }
7025 if (taskTopI == replyChainEnd) {
7026 taskTopI = -1;
7027 }
7028 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007029 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007030 } else if (forceReset || finishOnTaskLaunch
7031 || clearWhenTaskReset) {
7032 // If the activity should just be removed -- either
7033 // because it asks for it, or the task should be
7034 // cleared -- then finish it and anything that is
7035 // part of its reply chain.
7036 if (clearWhenTaskReset) {
7037 // In this case, we want to finish this activity
7038 // and everything above it, so be sneaky and pretend
7039 // like these are all in the reply chain.
7040 replyChainEnd = targetI+1;
7041 while (replyChainEnd < mHistory.size() &&
7042 ((HistoryRecord)mHistory.get(
7043 replyChainEnd)).task == task) {
7044 replyChainEnd++;
7045 }
7046 replyChainEnd--;
7047 } else if (replyChainEnd < 0) {
7048 replyChainEnd = targetI;
7049 }
7050 HistoryRecord p = null;
7051 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7052 p = (HistoryRecord)mHistory.get(srcPos);
7053 if (p.finishing) {
7054 continue;
7055 }
7056 if (finishActivityLocked(p, srcPos,
7057 Activity.RESULT_CANCELED, null, "reset")) {
7058 replyChainEnd--;
7059 srcPos--;
7060 }
7061 }
7062 if (taskTop == p) {
7063 taskTop = below;
7064 }
7065 if (taskTopI == replyChainEnd) {
7066 taskTopI = -1;
7067 }
7068 replyChainEnd = -1;
7069 } else {
7070 // If we were in the middle of a chain, well the
7071 // activity that started it all doesn't want anything
7072 // special, so leave it all as-is.
7073 replyChainEnd = -1;
7074 }
7075 } else {
7076 // Reached the bottom of the task -- any reply chain
7077 // should be left as-is.
7078 replyChainEnd = -1;
7079 }
7080
7081 } else if (target.resultTo != null) {
7082 // If this activity is sending a reply to a previous
7083 // activity, we can't do anything with it now until
7084 // we reach the start of the reply chain.
7085 // XXX note that we are assuming the result is always
7086 // to the previous activity, which is almost always
7087 // the case but we really shouldn't count on.
7088 if (replyChainEnd < 0) {
7089 replyChainEnd = targetI;
7090 }
7091
7092 } else if (taskTopI >= 0 && allowTaskReparenting
7093 && task.affinity != null
7094 && task.affinity.equals(target.taskAffinity)) {
7095 // We are inside of another task... if this activity has
7096 // an affinity for our task, then either remove it if we are
7097 // clearing or move it over to our task. Note that
7098 // we currently punt on the case where we are resetting a
7099 // task that is not at the top but who has activities above
7100 // with an affinity to it... this is really not a normal
7101 // case, and we will need to later pull that task to the front
7102 // and usually at that point we will do the reset and pick
7103 // up those remaining activities. (This only happens if
7104 // someone starts an activity in a new task from an activity
7105 // in a task that is not currently on top.)
7106 if (forceReset || finishOnTaskLaunch) {
7107 if (replyChainEnd < 0) {
7108 replyChainEnd = targetI;
7109 }
7110 HistoryRecord p = null;
7111 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7112 p = (HistoryRecord)mHistory.get(srcPos);
7113 if (p.finishing) {
7114 continue;
7115 }
7116 if (finishActivityLocked(p, srcPos,
7117 Activity.RESULT_CANCELED, null, "reset")) {
7118 taskTopI--;
7119 lastReparentPos--;
7120 replyChainEnd--;
7121 srcPos--;
7122 }
7123 }
7124 replyChainEnd = -1;
7125 } else {
7126 if (replyChainEnd < 0) {
7127 replyChainEnd = targetI;
7128 }
7129 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7130 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7131 if (p.finishing) {
7132 continue;
7133 }
7134 if (lastReparentPos < 0) {
7135 lastReparentPos = taskTopI;
7136 taskTop = p;
7137 } else {
7138 lastReparentPos--;
7139 }
7140 mHistory.remove(srcPos);
7141 p.task.numActivities--;
7142 p.task = task;
7143 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007144 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007145 + " in to resetting task " + task);
7146 task.numActivities++;
7147 mWindowManager.moveAppToken(lastReparentPos, p);
7148 mWindowManager.setAppGroupId(p, p.task.taskId);
7149 if (VALIDATE_TOKENS) {
7150 mWindowManager.validateAppTokens(mHistory);
7151 }
7152 }
7153 replyChainEnd = -1;
7154
7155 // Now we've moved it in to place... but what if this is
7156 // a singleTop activity and we have put it on top of another
7157 // instance of the same activity? Then we drop the instance
7158 // below so it remains singleTop.
7159 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7160 for (int j=lastReparentPos-1; j>=0; j--) {
7161 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7162 if (p.finishing) {
7163 continue;
7164 }
7165 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7166 if (finishActivityLocked(p, j,
7167 Activity.RESULT_CANCELED, null, "replace")) {
7168 taskTopI--;
7169 lastReparentPos--;
7170 }
7171 }
7172 }
7173 }
7174 }
7175 }
7176
7177 target = below;
7178 targetI = i;
7179 }
7180
7181 return taskTop;
7182 }
7183
7184 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007185 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007186 */
7187 public void moveTaskToFront(int task) {
7188 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7189 "moveTaskToFront()");
7190
7191 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007192 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7193 Binder.getCallingUid(), "Task to front")) {
7194 return;
7195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007196 final long origId = Binder.clearCallingIdentity();
7197 try {
7198 int N = mRecentTasks.size();
7199 for (int i=0; i<N; i++) {
7200 TaskRecord tr = mRecentTasks.get(i);
7201 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007202 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007203 return;
7204 }
7205 }
7206 for (int i=mHistory.size()-1; i>=0; i--) {
7207 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7208 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007209 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007210 return;
7211 }
7212 }
7213 } finally {
7214 Binder.restoreCallingIdentity(origId);
7215 }
7216 }
7217 }
7218
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007219 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007220 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007221
7222 final int task = tr.taskId;
7223 int top = mHistory.size()-1;
7224
7225 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7226 // nothing to do!
7227 return;
7228 }
7229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007230 ArrayList moved = new ArrayList();
7231
7232 // Applying the affinities may have removed entries from the history,
7233 // so get the size again.
7234 top = mHistory.size()-1;
7235 int pos = top;
7236
7237 // Shift all activities with this task up to the top
7238 // of the stack, keeping them in the same internal order.
7239 while (pos >= 0) {
7240 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007241 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007242 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7243 boolean first = true;
7244 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007245 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007246 mHistory.remove(pos);
7247 mHistory.add(top, r);
7248 moved.add(0, r);
7249 top--;
7250 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007251 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 first = false;
7253 }
7254 }
7255 pos--;
7256 }
7257
Joe Onorato8a9b2202010-02-26 18:56:32 -08007258 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007259 "Prepare to front transition: task=" + tr);
7260 if (reason != null &&
7261 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7262 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7263 HistoryRecord r = topRunningActivityLocked(null);
7264 if (r != null) {
7265 mNoAnimActivities.add(r);
7266 }
7267 } else {
7268 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7269 }
7270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271 mWindowManager.moveAppTokensToTop(moved);
7272 if (VALIDATE_TOKENS) {
7273 mWindowManager.validateAppTokens(mHistory);
7274 }
7275
Josh Bartel7f208742010-02-25 11:01:44 -06007276 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007277 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007278 }
7279
Josh Bartel7f208742010-02-25 11:01:44 -06007280 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007281 resumeTopActivityLocked(null);
7282 }
7283
7284 public void moveTaskToBack(int task) {
7285 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7286 "moveTaskToBack()");
7287
7288 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007289 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7290 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7291 Binder.getCallingUid(), "Task to back")) {
7292 return;
7293 }
7294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007296 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007297 Binder.restoreCallingIdentity(origId);
7298 }
7299 }
7300
7301 /**
7302 * Moves an activity, and all of the other activities within the same task, to the bottom
7303 * of the history stack. The activity's order within the task is unchanged.
7304 *
7305 * @param token A reference to the activity we wish to move
7306 * @param nonRoot If false then this only works if the activity is the root
7307 * of a task; if true it will work for any activity in a task.
7308 * @return Returns true if the move completed, false if not.
7309 */
7310 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7311 synchronized(this) {
7312 final long origId = Binder.clearCallingIdentity();
7313 int taskId = getTaskForActivityLocked(token, !nonRoot);
7314 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007315 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 }
7317 Binder.restoreCallingIdentity(origId);
7318 }
7319 return false;
7320 }
7321
7322 /**
7323 * Worker method for rearranging history stack. Implements the function of moving all
7324 * activities for a specific task (gathering them if disjoint) into a single group at the
7325 * bottom of the stack.
7326 *
7327 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7328 * to premeptively cancel the move.
7329 *
7330 * @param task The taskId to collect and move to the bottom.
7331 * @return Returns true if the move completed, false if not.
7332 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007333 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007334 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007335
7336 // If we have a watcher, preflight the move before committing to it. First check
7337 // for *other* available tasks, but if none are available, then try again allowing the
7338 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007339 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007340 HistoryRecord next = topRunningActivityLocked(null, task);
7341 if (next == null) {
7342 next = topRunningActivityLocked(null, 0);
7343 }
7344 if (next != null) {
7345 // ask watcher if this is allowed
7346 boolean moveOK = true;
7347 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007348 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007349 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007350 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007351 }
7352 if (!moveOK) {
7353 return false;
7354 }
7355 }
7356 }
7357
7358 ArrayList moved = new ArrayList();
7359
Joe Onorato8a9b2202010-02-26 18:56:32 -08007360 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007361 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007362
7363 final int N = mHistory.size();
7364 int bottom = 0;
7365 int pos = 0;
7366
7367 // Shift all activities with this task down to the bottom
7368 // of the stack, keeping them in the same internal order.
7369 while (pos < N) {
7370 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007371 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7373 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007374 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007375 mHistory.remove(pos);
7376 mHistory.add(bottom, r);
7377 moved.add(r);
7378 bottom++;
7379 }
7380 pos++;
7381 }
7382
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007383 if (reason != null &&
7384 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7385 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7386 HistoryRecord r = topRunningActivityLocked(null);
7387 if (r != null) {
7388 mNoAnimActivities.add(r);
7389 }
7390 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007391 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007393 mWindowManager.moveAppTokensToBottom(moved);
7394 if (VALIDATE_TOKENS) {
7395 mWindowManager.validateAppTokens(mHistory);
7396 }
7397
Josh Bartel7f208742010-02-25 11:01:44 -06007398 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007399 return true;
7400 }
7401
7402 public void moveTaskBackwards(int task) {
7403 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7404 "moveTaskBackwards()");
7405
7406 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007407 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7408 Binder.getCallingUid(), "Task backwards")) {
7409 return;
7410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 final long origId = Binder.clearCallingIdentity();
7412 moveTaskBackwardsLocked(task);
7413 Binder.restoreCallingIdentity(origId);
7414 }
7415 }
7416
7417 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007418 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 }
7420
7421 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7422 synchronized(this) {
7423 return getTaskForActivityLocked(token, onlyRoot);
7424 }
7425 }
7426
7427 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7428 final int N = mHistory.size();
7429 TaskRecord lastTask = null;
7430 for (int i=0; i<N; i++) {
7431 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7432 if (r == token) {
7433 if (!onlyRoot || lastTask != r.task) {
7434 return r.task.taskId;
7435 }
7436 return -1;
7437 }
7438 lastTask = r.task;
7439 }
7440
7441 return -1;
7442 }
7443
7444 /**
7445 * Returns the top activity in any existing task matching the given
7446 * Intent. Returns null if no such task is found.
7447 */
7448 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7449 ComponentName cls = intent.getComponent();
7450 if (info.targetActivity != null) {
7451 cls = new ComponentName(info.packageName, info.targetActivity);
7452 }
7453
7454 TaskRecord cp = null;
7455
7456 final int N = mHistory.size();
7457 for (int i=(N-1); i>=0; i--) {
7458 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7459 if (!r.finishing && r.task != cp
7460 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7461 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007462 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007463 // + "/aff=" + r.task.affinity + " to new cls="
7464 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7465 if (r.task.affinity != null) {
7466 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007467 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 return r;
7469 }
7470 } else if (r.task.intent != null
7471 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007472 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007473 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007474 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475 return r;
7476 } else if (r.task.affinityIntent != null
7477 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007478 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007479 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007480 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 return r;
7482 }
7483 }
7484 }
7485
7486 return null;
7487 }
7488
7489 /**
7490 * Returns the first activity (starting from the top of the stack) that
7491 * is the same as the given activity. Returns null if no such activity
7492 * is found.
7493 */
7494 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7495 ComponentName cls = intent.getComponent();
7496 if (info.targetActivity != null) {
7497 cls = new ComponentName(info.packageName, info.targetActivity);
7498 }
7499
7500 final int N = mHistory.size();
7501 for (int i=(N-1); i>=0; i--) {
7502 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7503 if (!r.finishing) {
7504 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007505 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007506 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007507 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007508 return r;
7509 }
7510 }
7511 }
7512
7513 return null;
7514 }
7515
7516 public void finishOtherInstances(IBinder token, ComponentName className) {
7517 synchronized(this) {
7518 final long origId = Binder.clearCallingIdentity();
7519
7520 int N = mHistory.size();
7521 TaskRecord lastTask = null;
7522 for (int i=0; i<N; i++) {
7523 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7524 if (r.realActivity.equals(className)
7525 && r != token && lastTask != r.task) {
7526 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7527 null, "others")) {
7528 i--;
7529 N--;
7530 }
7531 }
7532 lastTask = r.task;
7533 }
7534
7535 Binder.restoreCallingIdentity(origId);
7536 }
7537 }
7538
7539 // =========================================================
7540 // THUMBNAILS
7541 // =========================================================
7542
7543 public void reportThumbnail(IBinder token,
7544 Bitmap thumbnail, CharSequence description) {
7545 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7546 final long origId = Binder.clearCallingIdentity();
7547 sendPendingThumbnail(null, token, thumbnail, description, true);
7548 Binder.restoreCallingIdentity(origId);
7549 }
7550
7551 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7552 Bitmap thumbnail, CharSequence description, boolean always) {
7553 TaskRecord task = null;
7554 ArrayList receivers = null;
7555
7556 //System.out.println("Send pending thumbnail: " + r);
7557
7558 synchronized(this) {
7559 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007560 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007561 if (index < 0) {
7562 return;
7563 }
7564 r = (HistoryRecord)mHistory.get(index);
7565 }
7566 if (thumbnail == null) {
7567 thumbnail = r.thumbnail;
7568 description = r.description;
7569 }
7570 if (thumbnail == null && !always) {
7571 // If there is no thumbnail, and this entry is not actually
7572 // going away, then abort for now and pick up the next
7573 // thumbnail we get.
7574 return;
7575 }
7576 task = r.task;
7577
7578 int N = mPendingThumbnails.size();
7579 int i=0;
7580 while (i<N) {
7581 PendingThumbnailsRecord pr =
7582 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7583 //System.out.println("Looking in " + pr.pendingRecords);
7584 if (pr.pendingRecords.remove(r)) {
7585 if (receivers == null) {
7586 receivers = new ArrayList();
7587 }
7588 receivers.add(pr);
7589 if (pr.pendingRecords.size() == 0) {
7590 pr.finished = true;
7591 mPendingThumbnails.remove(i);
7592 N--;
7593 continue;
7594 }
7595 }
7596 i++;
7597 }
7598 }
7599
7600 if (receivers != null) {
7601 final int N = receivers.size();
7602 for (int i=0; i<N; i++) {
7603 try {
7604 PendingThumbnailsRecord pr =
7605 (PendingThumbnailsRecord)receivers.get(i);
7606 pr.receiver.newThumbnail(
7607 task != null ? task.taskId : -1, thumbnail, description);
7608 if (pr.finished) {
7609 pr.receiver.finished();
7610 }
7611 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007612 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 }
7614 }
7615 }
7616 }
7617
7618 // =========================================================
7619 // CONTENT PROVIDERS
7620 // =========================================================
7621
7622 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7623 List providers = null;
7624 try {
7625 providers = ActivityThread.getPackageManager().
7626 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007627 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007628 } catch (RemoteException ex) {
7629 }
7630 if (providers != null) {
7631 final int N = providers.size();
7632 for (int i=0; i<N; i++) {
7633 ProviderInfo cpi =
7634 (ProviderInfo)providers.get(i);
7635 ContentProviderRecord cpr =
7636 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7637 if (cpr == null) {
7638 cpr = new ContentProviderRecord(cpi, app.info);
7639 mProvidersByClass.put(cpi.name, cpr);
7640 }
7641 app.pubProviders.put(cpi.name, cpr);
7642 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007643 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007644 }
7645 }
7646 return providers;
7647 }
7648
7649 private final String checkContentProviderPermissionLocked(
7650 ProviderInfo cpi, ProcessRecord r, int mode) {
7651 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7652 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7653 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7654 cpi.exported ? -1 : cpi.applicationInfo.uid)
7655 == PackageManager.PERMISSION_GRANTED
7656 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7657 return null;
7658 }
7659 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7660 cpi.exported ? -1 : cpi.applicationInfo.uid)
7661 == PackageManager.PERMISSION_GRANTED) {
7662 return null;
7663 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007664
7665 PathPermission[] pps = cpi.pathPermissions;
7666 if (pps != null) {
7667 int i = pps.length;
7668 while (i > 0) {
7669 i--;
7670 PathPermission pp = pps[i];
7671 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7672 cpi.exported ? -1 : cpi.applicationInfo.uid)
7673 == PackageManager.PERMISSION_GRANTED
7674 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7675 return null;
7676 }
7677 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7678 cpi.exported ? -1 : cpi.applicationInfo.uid)
7679 == PackageManager.PERMISSION_GRANTED) {
7680 return null;
7681 }
7682 }
7683 }
7684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007685 String msg = "Permission Denial: opening provider " + cpi.name
7686 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7687 + ", uid=" + callingUid + ") requires "
7688 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007689 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690 return msg;
7691 }
7692
7693 private final ContentProviderHolder getContentProviderImpl(
7694 IApplicationThread caller, String name) {
7695 ContentProviderRecord cpr;
7696 ProviderInfo cpi = null;
7697
7698 synchronized(this) {
7699 ProcessRecord r = null;
7700 if (caller != null) {
7701 r = getRecordForAppLocked(caller);
7702 if (r == null) {
7703 throw new SecurityException(
7704 "Unable to find app for caller " + caller
7705 + " (pid=" + Binder.getCallingPid()
7706 + ") when getting content provider " + name);
7707 }
7708 }
7709
7710 // First check if this content provider has been published...
7711 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7712 if (cpr != null) {
7713 cpi = cpr.info;
7714 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7715 return new ContentProviderHolder(cpi,
7716 cpi.readPermission != null
7717 ? cpi.readPermission : cpi.writePermission);
7718 }
7719
7720 if (r != null && cpr.canRunHere(r)) {
7721 // This provider has been published or is in the process
7722 // of being published... but it is also allowed to run
7723 // in the caller's process, so don't make a connection
7724 // and just let the caller instantiate its own instance.
7725 if (cpr.provider != null) {
7726 // don't give caller the provider object, it needs
7727 // to make its own.
7728 cpr = new ContentProviderRecord(cpr);
7729 }
7730 return cpr;
7731 }
7732
7733 final long origId = Binder.clearCallingIdentity();
7734
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007735 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007736 // return it right away.
7737 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007738 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007739 "Adding provider requested by "
7740 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007741 + cpr.info.processName);
7742 Integer cnt = r.conProviders.get(cpr);
7743 if (cnt == null) {
7744 r.conProviders.put(cpr, new Integer(1));
7745 } else {
7746 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007748 cpr.clients.add(r);
7749 } else {
7750 cpr.externals++;
7751 }
7752
7753 if (cpr.app != null) {
7754 updateOomAdjLocked(cpr.app);
7755 }
7756
7757 Binder.restoreCallingIdentity(origId);
7758
7759 } else {
7760 try {
7761 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007762 resolveContentProvider(name,
7763 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007764 } catch (RemoteException ex) {
7765 }
7766 if (cpi == null) {
7767 return null;
7768 }
7769
7770 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7771 return new ContentProviderHolder(cpi,
7772 cpi.readPermission != null
7773 ? cpi.readPermission : cpi.writePermission);
7774 }
7775
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007776 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7777 && !cpi.processName.equals("system")) {
7778 // If this content provider does not run in the system
7779 // process, and the system is not yet ready to run other
7780 // processes, then fail fast instead of hanging.
7781 throw new IllegalArgumentException(
7782 "Attempt to launch content provider before system ready");
7783 }
7784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7786 final boolean firstClass = cpr == null;
7787 if (firstClass) {
7788 try {
7789 ApplicationInfo ai =
7790 ActivityThread.getPackageManager().
7791 getApplicationInfo(
7792 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007793 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007795 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007796 + cpi.name);
7797 return null;
7798 }
7799 cpr = new ContentProviderRecord(cpi, ai);
7800 } catch (RemoteException ex) {
7801 // pm is in same process, this will never happen.
7802 }
7803 }
7804
7805 if (r != null && cpr.canRunHere(r)) {
7806 // If this is a multiprocess provider, then just return its
7807 // info and allow the caller to instantiate it. Only do
7808 // this if the provider is the same user as the caller's
7809 // process, or can run as root (so can be in any process).
7810 return cpr;
7811 }
7812
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007813 if (DEBUG_PROVIDER) {
7814 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007815 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007816 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007817 }
7818
7819 // This is single process, and our app is now connecting to it.
7820 // See if we are already in the process of launching this
7821 // provider.
7822 final int N = mLaunchingProviders.size();
7823 int i;
7824 for (i=0; i<N; i++) {
7825 if (mLaunchingProviders.get(i) == cpr) {
7826 break;
7827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007828 }
7829
7830 // If the provider is not already being launched, then get it
7831 // started.
7832 if (i >= N) {
7833 final long origId = Binder.clearCallingIdentity();
7834 ProcessRecord proc = startProcessLocked(cpi.processName,
7835 cpr.appInfo, false, 0, "content provider",
7836 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007837 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007839 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 + cpi.applicationInfo.packageName + "/"
7841 + cpi.applicationInfo.uid + " for provider "
7842 + name + ": process is bad");
7843 return null;
7844 }
7845 cpr.launchingApp = proc;
7846 mLaunchingProviders.add(cpr);
7847 Binder.restoreCallingIdentity(origId);
7848 }
7849
7850 // Make sure the provider is published (the same provider class
7851 // may be published under multiple names).
7852 if (firstClass) {
7853 mProvidersByClass.put(cpi.name, cpr);
7854 }
7855 mProvidersByName.put(name, cpr);
7856
7857 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007858 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007859 "Adding provider requested by "
7860 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007861 + cpr.info.processName);
7862 Integer cnt = r.conProviders.get(cpr);
7863 if (cnt == null) {
7864 r.conProviders.put(cpr, new Integer(1));
7865 } else {
7866 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007868 cpr.clients.add(r);
7869 } else {
7870 cpr.externals++;
7871 }
7872 }
7873 }
7874
7875 // Wait for the provider to be published...
7876 synchronized (cpr) {
7877 while (cpr.provider == null) {
7878 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007879 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 + cpi.applicationInfo.packageName + "/"
7881 + cpi.applicationInfo.uid + " for provider "
7882 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007883 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007884 cpi.applicationInfo.packageName,
7885 cpi.applicationInfo.uid, name);
7886 return null;
7887 }
7888 try {
7889 cpr.wait();
7890 } catch (InterruptedException ex) {
7891 }
7892 }
7893 }
7894 return cpr;
7895 }
7896
7897 public final ContentProviderHolder getContentProvider(
7898 IApplicationThread caller, String name) {
7899 if (caller == null) {
7900 String msg = "null IApplicationThread when getting content provider "
7901 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007902 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007903 throw new SecurityException(msg);
7904 }
7905
7906 return getContentProviderImpl(caller, name);
7907 }
7908
7909 private ContentProviderHolder getContentProviderExternal(String name) {
7910 return getContentProviderImpl(null, name);
7911 }
7912
7913 /**
7914 * Drop a content provider from a ProcessRecord's bookkeeping
7915 * @param cpr
7916 */
7917 public void removeContentProvider(IApplicationThread caller, String name) {
7918 synchronized (this) {
7919 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7920 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007921 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007922 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007923 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007924 return;
7925 }
7926 final ProcessRecord r = getRecordForAppLocked(caller);
7927 if (r == null) {
7928 throw new SecurityException(
7929 "Unable to find app for caller " + caller +
7930 " when removing content provider " + name);
7931 }
7932 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007933 ContentProviderRecord localCpr = (ContentProviderRecord)
7934 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007935 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007936 + r.info.processName + " from process "
7937 + localCpr.appInfo.processName);
7938 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007939 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007940 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007941 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007942 return;
7943 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007944 Integer cnt = r.conProviders.get(localCpr);
7945 if (cnt == null || cnt.intValue() <= 1) {
7946 localCpr.clients.remove(r);
7947 r.conProviders.remove(localCpr);
7948 } else {
7949 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007951 }
7952 updateOomAdjLocked();
7953 }
7954 }
7955
7956 private void removeContentProviderExternal(String name) {
7957 synchronized (this) {
7958 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7959 if(cpr == null) {
7960 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007961 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 return;
7963 }
7964
7965 //update content provider record entry info
7966 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7967 localCpr.externals--;
7968 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007969 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007970 }
7971 updateOomAdjLocked();
7972 }
7973 }
7974
7975 public final void publishContentProviders(IApplicationThread caller,
7976 List<ContentProviderHolder> providers) {
7977 if (providers == null) {
7978 return;
7979 }
7980
7981 synchronized(this) {
7982 final ProcessRecord r = getRecordForAppLocked(caller);
7983 if (r == null) {
7984 throw new SecurityException(
7985 "Unable to find app for caller " + caller
7986 + " (pid=" + Binder.getCallingPid()
7987 + ") when publishing content providers");
7988 }
7989
7990 final long origId = Binder.clearCallingIdentity();
7991
7992 final int N = providers.size();
7993 for (int i=0; i<N; i++) {
7994 ContentProviderHolder src = providers.get(i);
7995 if (src == null || src.info == null || src.provider == null) {
7996 continue;
7997 }
7998 ContentProviderRecord dst =
7999 (ContentProviderRecord)r.pubProviders.get(src.info.name);
8000 if (dst != null) {
8001 mProvidersByClass.put(dst.info.name, dst);
8002 String names[] = dst.info.authority.split(";");
8003 for (int j = 0; j < names.length; j++) {
8004 mProvidersByName.put(names[j], dst);
8005 }
8006
8007 int NL = mLaunchingProviders.size();
8008 int j;
8009 for (j=0; j<NL; j++) {
8010 if (mLaunchingProviders.get(j) == dst) {
8011 mLaunchingProviders.remove(j);
8012 j--;
8013 NL--;
8014 }
8015 }
8016 synchronized (dst) {
8017 dst.provider = src.provider;
8018 dst.app = r;
8019 dst.notifyAll();
8020 }
8021 updateOomAdjLocked(r);
8022 }
8023 }
8024
8025 Binder.restoreCallingIdentity(origId);
8026 }
8027 }
8028
8029 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008030 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008031 synchronized (mSelf) {
8032 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8033 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008034 if (providers != null) {
8035 for (int i=providers.size()-1; i>=0; i--) {
8036 ProviderInfo pi = (ProviderInfo)providers.get(i);
8037 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8038 Slog.w(TAG, "Not installing system proc provider " + pi.name
8039 + ": not system .apk");
8040 providers.remove(i);
8041 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008042 }
8043 }
8044 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008045 if (providers != null) {
8046 mSystemThread.installSystemProviders(providers);
8047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 }
8049
8050 // =========================================================
8051 // GLOBAL MANAGEMENT
8052 // =========================================================
8053
8054 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8055 ApplicationInfo info, String customProcess) {
8056 String proc = customProcess != null ? customProcess : info.processName;
8057 BatteryStatsImpl.Uid.Proc ps = null;
8058 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8059 synchronized (stats) {
8060 ps = stats.getProcessStatsLocked(info.uid, proc);
8061 }
8062 return new ProcessRecord(ps, thread, info, proc);
8063 }
8064
8065 final ProcessRecord addAppLocked(ApplicationInfo info) {
8066 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8067
8068 if (app == null) {
8069 app = newProcessRecordLocked(null, info, null);
8070 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008071 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 }
8073
8074 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8075 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8076 app.persistent = true;
8077 app.maxAdj = CORE_SERVER_ADJ;
8078 }
8079 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8080 mPersistentStartingProcesses.add(app);
8081 startProcessLocked(app, "added application", app.processName);
8082 }
8083
8084 return app;
8085 }
8086
8087 public void unhandledBack() {
8088 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8089 "unhandledBack()");
8090
8091 synchronized(this) {
8092 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008093 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008094 TAG, "Performing unhandledBack(): stack size = " + count);
8095 if (count > 1) {
8096 final long origId = Binder.clearCallingIdentity();
8097 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8098 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8099 Binder.restoreCallingIdentity(origId);
8100 }
8101 }
8102 }
8103
8104 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8105 String name = uri.getAuthority();
8106 ContentProviderHolder cph = getContentProviderExternal(name);
8107 ParcelFileDescriptor pfd = null;
8108 if (cph != null) {
8109 // We record the binder invoker's uid in thread-local storage before
8110 // going to the content provider to open the file. Later, in the code
8111 // that handles all permissions checks, we look for this uid and use
8112 // that rather than the Activity Manager's own uid. The effect is that
8113 // we do the check against the caller's permissions even though it looks
8114 // to the content provider like the Activity Manager itself is making
8115 // the request.
8116 sCallerIdentity.set(new Identity(
8117 Binder.getCallingPid(), Binder.getCallingUid()));
8118 try {
8119 pfd = cph.provider.openFile(uri, "r");
8120 } catch (FileNotFoundException e) {
8121 // do nothing; pfd will be returned null
8122 } finally {
8123 // Ensure that whatever happens, we clean up the identity state
8124 sCallerIdentity.remove();
8125 }
8126
8127 // We've got the fd now, so we're done with the provider.
8128 removeContentProviderExternal(name);
8129 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008130 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008131 }
8132 return pfd;
8133 }
8134
8135 public void goingToSleep() {
8136 synchronized(this) {
8137 mSleeping = true;
8138 mWindowManager.setEventDispatching(false);
8139
8140 if (mResumedActivity != null) {
8141 pauseIfSleepingLocked();
8142 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008143 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008144 }
8145 }
8146 }
8147
Dianne Hackborn55280a92009-05-07 15:53:46 -07008148 public boolean shutdown(int timeout) {
8149 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8150 != PackageManager.PERMISSION_GRANTED) {
8151 throw new SecurityException("Requires permission "
8152 + android.Manifest.permission.SHUTDOWN);
8153 }
8154
8155 boolean timedout = false;
8156
8157 synchronized(this) {
8158 mShuttingDown = true;
8159 mWindowManager.setEventDispatching(false);
8160
8161 if (mResumedActivity != null) {
8162 pauseIfSleepingLocked();
8163 final long endTime = System.currentTimeMillis() + timeout;
8164 while (mResumedActivity != null || mPausingActivity != null) {
8165 long delay = endTime - System.currentTimeMillis();
8166 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008167 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008168 timedout = true;
8169 break;
8170 }
8171 try {
8172 this.wait();
8173 } catch (InterruptedException e) {
8174 }
8175 }
8176 }
8177 }
8178
8179 mUsageStatsService.shutdown();
8180 mBatteryStatsService.shutdown();
8181
8182 return timedout;
8183 }
8184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008186 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008187 if (!mGoingToSleep.isHeld()) {
8188 mGoingToSleep.acquire();
8189 if (mLaunchingActivity.isHeld()) {
8190 mLaunchingActivity.release();
8191 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8192 }
8193 }
8194
8195 // If we are not currently pausing an activity, get the current
8196 // one to pause. If we are pausing one, we will just let that stuff
8197 // run and release the wake lock when all done.
8198 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008199 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8200 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008201 startPausingLocked(false, true);
8202 }
8203 }
8204 }
8205
8206 public void wakingUp() {
8207 synchronized(this) {
8208 if (mGoingToSleep.isHeld()) {
8209 mGoingToSleep.release();
8210 }
8211 mWindowManager.setEventDispatching(true);
8212 mSleeping = false;
8213 resumeTopActivityLocked(null);
8214 }
8215 }
8216
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008217 public void stopAppSwitches() {
8218 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8219 != PackageManager.PERMISSION_GRANTED) {
8220 throw new SecurityException("Requires permission "
8221 + android.Manifest.permission.STOP_APP_SWITCHES);
8222 }
8223
8224 synchronized(this) {
8225 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8226 + APP_SWITCH_DELAY_TIME;
8227 mDidAppSwitch = false;
8228 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8229 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8230 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8231 }
8232 }
8233
8234 public void resumeAppSwitches() {
8235 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8236 != PackageManager.PERMISSION_GRANTED) {
8237 throw new SecurityException("Requires permission "
8238 + android.Manifest.permission.STOP_APP_SWITCHES);
8239 }
8240
8241 synchronized(this) {
8242 // Note that we don't execute any pending app switches... we will
8243 // let those wait until either the timeout, or the next start
8244 // activity request.
8245 mAppSwitchesAllowedTime = 0;
8246 }
8247 }
8248
8249 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8250 String name) {
8251 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8252 return true;
8253 }
8254
8255 final int perm = checkComponentPermission(
8256 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8257 callingUid, -1);
8258 if (perm == PackageManager.PERMISSION_GRANTED) {
8259 return true;
8260 }
8261
Joe Onorato8a9b2202010-02-26 18:56:32 -08008262 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008263 return false;
8264 }
8265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 public void setDebugApp(String packageName, boolean waitForDebugger,
8267 boolean persistent) {
8268 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8269 "setDebugApp()");
8270
8271 // Note that this is not really thread safe if there are multiple
8272 // callers into it at the same time, but that's not a situation we
8273 // care about.
8274 if (persistent) {
8275 final ContentResolver resolver = mContext.getContentResolver();
8276 Settings.System.putString(
8277 resolver, Settings.System.DEBUG_APP,
8278 packageName);
8279 Settings.System.putInt(
8280 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8281 waitForDebugger ? 1 : 0);
8282 }
8283
8284 synchronized (this) {
8285 if (!persistent) {
8286 mOrigDebugApp = mDebugApp;
8287 mOrigWaitForDebugger = mWaitForDebugger;
8288 }
8289 mDebugApp = packageName;
8290 mWaitForDebugger = waitForDebugger;
8291 mDebugTransient = !persistent;
8292 if (packageName != null) {
8293 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008294 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008295 Binder.restoreCallingIdentity(origId);
8296 }
8297 }
8298 }
8299
8300 public void setAlwaysFinish(boolean enabled) {
8301 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8302 "setAlwaysFinish()");
8303
8304 Settings.System.putInt(
8305 mContext.getContentResolver(),
8306 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8307
8308 synchronized (this) {
8309 mAlwaysFinishActivities = enabled;
8310 }
8311 }
8312
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008313 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008314 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008315 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008316 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008317 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008318 }
8319 }
8320
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008321 public boolean isUserAMonkey() {
8322 // For now the fact that there is a controller implies
8323 // we have a monkey.
8324 synchronized (this) {
8325 return mController != null;
8326 }
8327 }
8328
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008329 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008330 synchronized (this) {
8331 mWatchers.register(watcher);
8332 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008333 }
8334
8335 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008336 synchronized (this) {
8337 mWatchers.unregister(watcher);
8338 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008339 }
8340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 public final void enterSafeMode() {
8342 synchronized(this) {
8343 // It only makes sense to do this before the system is ready
8344 // and started launching other packages.
8345 if (!mSystemReady) {
8346 try {
8347 ActivityThread.getPackageManager().enterSafeMode();
8348 } catch (RemoteException e) {
8349 }
8350
8351 View v = LayoutInflater.from(mContext).inflate(
8352 com.android.internal.R.layout.safe_mode, null);
8353 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8354 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8355 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8356 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8357 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8358 lp.format = v.getBackground().getOpacity();
8359 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8360 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8361 ((WindowManager)mContext.getSystemService(
8362 Context.WINDOW_SERVICE)).addView(v, lp);
8363 }
8364 }
8365 }
8366
8367 public void noteWakeupAlarm(IIntentSender sender) {
8368 if (!(sender instanceof PendingIntentRecord)) {
8369 return;
8370 }
8371 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8372 synchronized (stats) {
8373 if (mBatteryStatsService.isOnBattery()) {
8374 mBatteryStatsService.enforceCallingPermission();
8375 PendingIntentRecord rec = (PendingIntentRecord)sender;
8376 int MY_UID = Binder.getCallingUid();
8377 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8378 BatteryStatsImpl.Uid.Pkg pkg =
8379 stats.getPackageStatsLocked(uid, rec.key.packageName);
8380 pkg.incWakeupsLocked();
8381 }
8382 }
8383 }
8384
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008385 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008386 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008387 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008388 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008389 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008390 // XXX Note: don't acquire main activity lock here, because the window
8391 // manager calls in with its locks held.
8392
8393 boolean killed = false;
8394 synchronized (mPidsSelfLocked) {
8395 int[] types = new int[pids.length];
8396 int worstType = 0;
8397 for (int i=0; i<pids.length; i++) {
8398 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8399 if (proc != null) {
8400 int type = proc.setAdj;
8401 types[i] = type;
8402 if (type > worstType) {
8403 worstType = type;
8404 }
8405 }
8406 }
8407
8408 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8409 // then constrain it so we will kill all hidden procs.
8410 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8411 worstType = HIDDEN_APP_MIN_ADJ;
8412 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008413 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008414 for (int i=0; i<pids.length; i++) {
8415 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8416 if (proc == null) {
8417 continue;
8418 }
8419 int adj = proc.setAdj;
8420 if (adj >= worstType) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008421 Slog.w(TAG, "Killing " + reason + " : " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008422 + adj + ")");
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008423 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8424 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 killed = true;
8426 Process.killProcess(pids[i]);
8427 }
8428 }
8429 }
8430 return killed;
8431 }
8432
8433 public void reportPss(IApplicationThread caller, int pss) {
8434 Watchdog.PssRequestor req;
8435 String name;
8436 ProcessRecord callerApp;
8437 synchronized (this) {
8438 if (caller == null) {
8439 return;
8440 }
8441 callerApp = getRecordForAppLocked(caller);
8442 if (callerApp == null) {
8443 return;
8444 }
8445 callerApp.lastPss = pss;
8446 req = callerApp;
8447 name = callerApp.processName;
8448 }
8449 Watchdog.getInstance().reportPss(req, name, pss);
8450 if (!callerApp.persistent) {
8451 removeRequestedPss(callerApp);
8452 }
8453 }
8454
8455 public void requestPss(Runnable completeCallback) {
8456 ArrayList<ProcessRecord> procs;
8457 synchronized (this) {
8458 mRequestPssCallback = completeCallback;
8459 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008460 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8461 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008462 if (!proc.persistent) {
8463 mRequestPssList.add(proc);
8464 }
8465 }
8466 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8467 }
8468
8469 int oldPri = Process.getThreadPriority(Process.myTid());
8470 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8471 for (int i=procs.size()-1; i>=0; i--) {
8472 ProcessRecord proc = procs.get(i);
8473 proc.lastPss = 0;
8474 proc.requestPss();
8475 }
8476 Process.setThreadPriority(oldPri);
8477 }
8478
8479 void removeRequestedPss(ProcessRecord proc) {
8480 Runnable callback = null;
8481 synchronized (this) {
8482 if (mRequestPssList.remove(proc)) {
8483 if (mRequestPssList.size() == 0) {
8484 callback = mRequestPssCallback;
8485 mRequestPssCallback = null;
8486 }
8487 }
8488 }
8489
8490 if (callback != null) {
8491 callback.run();
8492 }
8493 }
8494
8495 public void collectPss(Watchdog.PssStats stats) {
8496 stats.mEmptyPss = 0;
8497 stats.mEmptyCount = 0;
8498 stats.mBackgroundPss = 0;
8499 stats.mBackgroundCount = 0;
8500 stats.mServicePss = 0;
8501 stats.mServiceCount = 0;
8502 stats.mVisiblePss = 0;
8503 stats.mVisibleCount = 0;
8504 stats.mForegroundPss = 0;
8505 stats.mForegroundCount = 0;
8506 stats.mNoPssCount = 0;
8507 synchronized (this) {
8508 int i;
8509 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8510 ? mProcDeaths.length : stats.mProcDeaths.length;
8511 int aggr = 0;
8512 for (i=0; i<NPD; i++) {
8513 aggr += mProcDeaths[i];
8514 stats.mProcDeaths[i] = aggr;
8515 }
8516 while (i<stats.mProcDeaths.length) {
8517 stats.mProcDeaths[i] = 0;
8518 i++;
8519 }
8520
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008521 for (i=mLruProcesses.size()-1; i>=0; i--) {
8522 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008523 if (proc.persistent) {
8524 continue;
8525 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008526 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008527 if (proc.lastPss == 0) {
8528 stats.mNoPssCount++;
8529 continue;
8530 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008531 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8532 if (proc.empty) {
8533 stats.mEmptyPss += proc.lastPss;
8534 stats.mEmptyCount++;
8535 } else {
8536 stats.mBackgroundPss += proc.lastPss;
8537 stats.mBackgroundCount++;
8538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008539 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8540 stats.mVisiblePss += proc.lastPss;
8541 stats.mVisibleCount++;
8542 } else {
8543 stats.mForegroundPss += proc.lastPss;
8544 stats.mForegroundCount++;
8545 }
8546 }
8547 }
8548 }
8549
8550 public final void startRunning(String pkg, String cls, String action,
8551 String data) {
8552 synchronized(this) {
8553 if (mStartRunning) {
8554 return;
8555 }
8556 mStartRunning = true;
8557 mTopComponent = pkg != null && cls != null
8558 ? new ComponentName(pkg, cls) : null;
8559 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8560 mTopData = data;
8561 if (!mSystemReady) {
8562 return;
8563 }
8564 }
8565
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008566 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008567 }
8568
8569 private void retrieveSettings() {
8570 final ContentResolver resolver = mContext.getContentResolver();
8571 String debugApp = Settings.System.getString(
8572 resolver, Settings.System.DEBUG_APP);
8573 boolean waitForDebugger = Settings.System.getInt(
8574 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8575 boolean alwaysFinishActivities = Settings.System.getInt(
8576 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8577
8578 Configuration configuration = new Configuration();
8579 Settings.System.getConfiguration(resolver, configuration);
8580
8581 synchronized (this) {
8582 mDebugApp = mOrigDebugApp = debugApp;
8583 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8584 mAlwaysFinishActivities = alwaysFinishActivities;
8585 // This happens before any activities are started, so we can
8586 // change mConfiguration in-place.
8587 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008588 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008589 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008590 }
8591 }
8592
8593 public boolean testIsSystemReady() {
8594 // no need to synchronize(this) just to read & return the value
8595 return mSystemReady;
8596 }
8597
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008598 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 // In the simulator, startRunning will never have been called, which
8600 // normally sets a few crucial variables. Do it here instead.
8601 if (!Process.supportsProcesses()) {
8602 mStartRunning = true;
8603 mTopAction = Intent.ACTION_MAIN;
8604 }
8605
8606 synchronized(this) {
8607 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008608 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008609 return;
8610 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008611
8612 // Check to see if there are any update receivers to run.
8613 if (!mDidUpdate) {
8614 if (mWaitingUpdate) {
8615 return;
8616 }
8617 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8618 List<ResolveInfo> ris = null;
8619 try {
8620 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8621 intent, null, 0);
8622 } catch (RemoteException e) {
8623 }
8624 if (ris != null) {
8625 for (int i=ris.size()-1; i>=0; i--) {
8626 if ((ris.get(i).activityInfo.applicationInfo.flags
8627 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8628 ris.remove(i);
8629 }
8630 }
8631 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8632 for (int i=0; i<ris.size(); i++) {
8633 ActivityInfo ai = ris.get(i).activityInfo;
8634 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8635 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008636 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008637 finisher = new IIntentReceiver.Stub() {
8638 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008639 String data, Bundle extras, boolean ordered,
8640 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008641 throws RemoteException {
8642 synchronized (ActivityManagerService.this) {
8643 mDidUpdate = true;
8644 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008645 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008646 }
8647 };
8648 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008649 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008650 broadcastIntentLocked(null, null, intent, null, finisher,
8651 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008652 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008653 mWaitingUpdate = true;
8654 }
8655 }
8656 }
8657 if (mWaitingUpdate) {
8658 return;
8659 }
8660 mDidUpdate = true;
8661 }
8662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008663 mSystemReady = true;
8664 if (!mStartRunning) {
8665 return;
8666 }
8667 }
8668
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008669 ArrayList<ProcessRecord> procsToKill = null;
8670 synchronized(mPidsSelfLocked) {
8671 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8672 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8673 if (!isAllowedWhileBooting(proc.info)){
8674 if (procsToKill == null) {
8675 procsToKill = new ArrayList<ProcessRecord>();
8676 }
8677 procsToKill.add(proc);
8678 }
8679 }
8680 }
8681
8682 if (procsToKill != null) {
8683 synchronized(this) {
8684 for (int i=procsToKill.size()-1; i>=0; i--) {
8685 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008686 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008687 removeProcessLocked(proc, true);
8688 }
8689 }
8690 }
8691
Joe Onorato8a9b2202010-02-26 18:56:32 -08008692 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008693 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008694 SystemClock.uptimeMillis());
8695
8696 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008697 // Make sure we have no pre-ready processes sitting around.
8698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008699 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8700 ResolveInfo ri = mContext.getPackageManager()
8701 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008702 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008703 CharSequence errorMsg = null;
8704 if (ri != null) {
8705 ActivityInfo ai = ri.activityInfo;
8706 ApplicationInfo app = ai.applicationInfo;
8707 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8708 mTopAction = Intent.ACTION_FACTORY_TEST;
8709 mTopData = null;
8710 mTopComponent = new ComponentName(app.packageName,
8711 ai.name);
8712 } else {
8713 errorMsg = mContext.getResources().getText(
8714 com.android.internal.R.string.factorytest_not_system);
8715 }
8716 } else {
8717 errorMsg = mContext.getResources().getText(
8718 com.android.internal.R.string.factorytest_no_action);
8719 }
8720 if (errorMsg != null) {
8721 mTopAction = null;
8722 mTopData = null;
8723 mTopComponent = null;
8724 Message msg = Message.obtain();
8725 msg.what = SHOW_FACTORY_ERROR_MSG;
8726 msg.getData().putCharSequence("msg", errorMsg);
8727 mHandler.sendMessage(msg);
8728 }
8729 }
8730 }
8731
8732 retrieveSettings();
8733
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008734 if (goingCallback != null) goingCallback.run();
8735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008736 synchronized (this) {
8737 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8738 try {
8739 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008740 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008741 if (apps != null) {
8742 int N = apps.size();
8743 int i;
8744 for (i=0; i<N; i++) {
8745 ApplicationInfo info
8746 = (ApplicationInfo)apps.get(i);
8747 if (info != null &&
8748 !info.packageName.equals("android")) {
8749 addAppLocked(info);
8750 }
8751 }
8752 }
8753 } catch (RemoteException ex) {
8754 // pm is in same process, this will never happen.
8755 }
8756 }
8757
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008758 // Start up initial activity.
8759 mBooting = true;
8760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008761 try {
8762 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8763 Message msg = Message.obtain();
8764 msg.what = SHOW_UID_ERROR_MSG;
8765 mHandler.sendMessage(msg);
8766 }
8767 } catch (RemoteException e) {
8768 }
8769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008770 resumeTopActivityLocked(null);
8771 }
8772 }
8773
Dan Egnorb7f03672009-12-09 16:22:32 -08008774 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008775 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008776 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008777 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008778 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008779 startAppProblemLocked(app);
8780 app.stopFreezingAllLocked();
8781 return handleAppCrashLocked(app);
8782 }
8783
Dan Egnorb7f03672009-12-09 16:22:32 -08008784 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008785 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008786 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008787 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008788 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8789 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008790 startAppProblemLocked(app);
8791 app.stopFreezingAllLocked();
8792 }
8793
8794 /**
8795 * Generate a process error record, suitable for attachment to a ProcessRecord.
8796 *
8797 * @param app The ProcessRecord in which the error occurred.
8798 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8799 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008800 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 * @param shortMsg Short message describing the crash.
8802 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008803 * @param stackTrace Full crash stack trace, may be null.
8804 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008805 * @return Returns a fully-formed AppErrorStateInfo record.
8806 */
8807 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008808 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008809 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008811 report.condition = condition;
8812 report.processName = app.processName;
8813 report.pid = app.pid;
8814 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008815 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 report.shortMsg = shortMsg;
8817 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008818 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819
8820 return report;
8821 }
8822
Dan Egnor42471dd2010-01-07 17:25:22 -08008823 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008824 synchronized (this) {
8825 app.crashing = false;
8826 app.crashingReport = null;
8827 app.notResponding = false;
8828 app.notRespondingReport = null;
8829 if (app.anrDialog == fromDialog) {
8830 app.anrDialog = null;
8831 }
8832 if (app.waitDialog == fromDialog) {
8833 app.waitDialog = null;
8834 }
8835 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008836 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008837 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 + app.processName
8839 + " (pid=" + app.pid + ") at user's request");
8840 Process.killProcess(app.pid);
8841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008842 }
8843 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008844
Dan Egnorb7f03672009-12-09 16:22:32 -08008845 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008846 long now = SystemClock.uptimeMillis();
8847
8848 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8849 app.info.uid);
8850 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8851 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008852 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008853 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008854 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008855 app.info.processName, app.info.uid);
8856 killServicesLocked(app, false);
8857 for (int i=mHistory.size()-1; i>=0; i--) {
8858 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8859 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008860 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008861 + r.intent.getComponent().flattenToShortString());
8862 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8863 }
8864 }
8865 if (!app.persistent) {
8866 // We don't want to start this process again until the user
8867 // explicitly does so... but for persistent process, we really
8868 // need to keep it running. If a persistent process is actually
8869 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008870 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008871 app.info.processName);
8872 mBadProcesses.put(app.info.processName, app.info.uid, now);
8873 app.bad = true;
8874 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8875 app.removed = true;
8876 removeProcessLocked(app, false);
8877 return false;
8878 }
8879 }
8880
8881 // Bump up the crash count of any services currently running in the proc.
8882 if (app.services.size() != 0) {
8883 // Any services running in the application need to be placed
8884 // back in the pending list.
8885 Iterator it = app.services.iterator();
8886 while (it.hasNext()) {
8887 ServiceRecord sr = (ServiceRecord)it.next();
8888 sr.crashCount++;
8889 }
8890 }
8891
8892 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8893 return true;
8894 }
8895
8896 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008897 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8898 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008899 skipCurrentReceiverLocked(app);
8900 }
8901
8902 void skipCurrentReceiverLocked(ProcessRecord app) {
8903 boolean reschedule = false;
8904 BroadcastRecord r = app.curReceiver;
8905 if (r != null) {
8906 // The current broadcast is waiting for this app's receiver
8907 // to be finished. Looks like that's not going to happen, so
8908 // let the broadcast continue.
8909 logBroadcastReceiverDiscard(r);
8910 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8911 r.resultExtras, r.resultAbort, true);
8912 reschedule = true;
8913 }
8914 r = mPendingBroadcast;
8915 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008916 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008917 "skip & discard pending app " + r);
8918 logBroadcastReceiverDiscard(r);
8919 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8920 r.resultExtras, r.resultAbort, true);
8921 reschedule = true;
8922 }
8923 if (reschedule) {
8924 scheduleBroadcastsLocked();
8925 }
8926 }
8927
Dan Egnor60d87622009-12-16 16:32:58 -08008928 /**
8929 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8930 * The application process will exit immediately after this call returns.
8931 * @param app object of the crashing app, null for the system server
8932 * @param crashInfo describing the exception
8933 */
8934 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8935 ProcessRecord r = findAppProcess(app);
8936
8937 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8938 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008939 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008940 crashInfo.exceptionClassName,
8941 crashInfo.exceptionMessage,
8942 crashInfo.throwFileName,
8943 crashInfo.throwLineNumber);
8944
Dan Egnor42471dd2010-01-07 17:25:22 -08008945 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008946
8947 crashApplication(r, crashInfo);
8948 }
8949
8950 /**
8951 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8952 * @param app object of the crashing app, null for the system server
8953 * @param tag reported by the caller
8954 * @param crashInfo describing the context of the error
8955 * @return true if the process should exit immediately (WTF is fatal)
8956 */
8957 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008958 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008959 ProcessRecord r = findAppProcess(app);
8960
8961 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8962 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008963 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008964 tag, crashInfo.exceptionMessage);
8965
Dan Egnor42471dd2010-01-07 17:25:22 -08008966 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008967
Doug Zongker43866e02010-01-07 12:09:54 -08008968 if (Settings.Secure.getInt(mContext.getContentResolver(),
8969 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008970 crashApplication(r, crashInfo);
8971 return true;
8972 } else {
8973 return false;
8974 }
8975 }
8976
8977 /**
8978 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8979 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8980 */
8981 private ProcessRecord findAppProcess(IBinder app) {
8982 if (app == null) {
8983 return null;
8984 }
8985
8986 synchronized (this) {
8987 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8988 final int NA = apps.size();
8989 for (int ia=0; ia<NA; ia++) {
8990 ProcessRecord p = apps.valueAt(ia);
8991 if (p.thread != null && p.thread.asBinder() == app) {
8992 return p;
8993 }
8994 }
8995 }
8996
Joe Onorato8a9b2202010-02-26 18:56:32 -08008997 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008998 return null;
8999 }
9000 }
9001
9002 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009003 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009004 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009005 * @param process which caused the error, null means the system server
9006 * @param activity which triggered the error, null if unknown
9007 * @param parent activity related to the error, null if unknown
9008 * @param subject line related to the error, null if absent
9009 * @param report in long form describing the error, null if absent
9010 * @param logFile to include in the report, null if none
9011 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009012 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009013 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009014 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9015 final String report, final File logFile,
9016 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009017 // NOTE -- this must never acquire the ActivityManagerService lock,
9018 // otherwise the watchdog may be prevented from resetting the system.
9019
Dan Egnora455d192010-03-12 08:52:28 -08009020 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009021 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009022 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009023 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009024 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009025 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009026 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009027 }
9028
Dan Egnora455d192010-03-12 08:52:28 -08009029 final String dropboxTag = prefix + eventType;
9030 final DropBoxManager dbox = (DropBoxManager)
9031 mContext.getSystemService(Context.DROPBOX_SERVICE);
9032
9033 // Exit early if the dropbox isn't configured to accept this report type.
9034 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9035
9036 final StringBuilder sb = new StringBuilder(1024);
9037 if (process == null || process.pid == MY_PID) {
9038 sb.append("Process: system_server\n");
9039 } else {
9040 sb.append("Process: ").append(process.processName).append("\n");
9041 }
9042 if (process != null) {
9043 int flags = process.info.flags;
9044 IPackageManager pm = ActivityThread.getPackageManager();
9045 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9046 for (String pkg : process.pkgList) {
9047 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009048 try {
Dan Egnora455d192010-03-12 08:52:28 -08009049 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9050 if (pi != null) {
9051 sb.append(" v").append(pi.versionCode);
9052 if (pi.versionName != null) {
9053 sb.append(" (").append(pi.versionName).append(")");
9054 }
9055 }
9056 } catch (RemoteException e) {
9057 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009058 }
Dan Egnora455d192010-03-12 08:52:28 -08009059 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009060 }
Dan Egnora455d192010-03-12 08:52:28 -08009061 }
9062 if (activity != null) {
9063 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9064 }
9065 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9066 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9067 }
9068 if (parent != null && parent != activity) {
9069 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9070 }
9071 if (subject != null) {
9072 sb.append("Subject: ").append(subject).append("\n");
9073 }
9074 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9075 sb.append("\n");
9076
9077 // Do the rest in a worker thread to avoid blocking the caller on I/O
9078 // (After this point, we shouldn't access AMS internal data structures.)
9079 Thread worker = new Thread("Error dump: " + dropboxTag) {
9080 @Override
9081 public void run() {
9082 if (report != null) {
9083 sb.append(report);
9084 }
9085 if (logFile != null) {
9086 try {
9087 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9088 } catch (IOException e) {
9089 Slog.e(TAG, "Error reading " + logFile, e);
9090 }
9091 }
9092 if (crashInfo != null && crashInfo.stackTrace != null) {
9093 sb.append(crashInfo.stackTrace);
9094 }
9095
9096 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9097 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9098 if (lines > 0) {
9099 sb.append("\n");
9100
9101 // Merge several logcat streams, and take the last N lines
9102 InputStreamReader input = null;
9103 try {
9104 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9105 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9106 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9107
9108 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9109 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9110 input = new InputStreamReader(logcat.getInputStream());
9111
9112 int num;
9113 char[] buf = new char[8192];
9114 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9115 } catch (IOException e) {
9116 Slog.e(TAG, "Error running logcat", e);
9117 } finally {
9118 if (input != null) try { input.close(); } catch (IOException e) {}
9119 }
9120 }
9121
9122 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009123 }
Dan Egnora455d192010-03-12 08:52:28 -08009124 };
9125
9126 if (process == null || process.pid == MY_PID) {
9127 worker.run(); // We may be about to die -- need to run this synchronously
9128 } else {
9129 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009130 }
9131 }
9132
9133 /**
9134 * Bring up the "unexpected error" dialog box for a crashing app.
9135 * Deal with edge cases (intercepts from instrumented applications,
9136 * ActivityController, error intent receivers, that sort of thing).
9137 * @param r the application crashing
9138 * @param crashInfo describing the failure
9139 */
9140 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009141 long timeMillis = System.currentTimeMillis();
9142 String shortMsg = crashInfo.exceptionClassName;
9143 String longMsg = crashInfo.exceptionMessage;
9144 String stackTrace = crashInfo.stackTrace;
9145 if (shortMsg != null && longMsg != null) {
9146 longMsg = shortMsg + ": " + longMsg;
9147 } else if (shortMsg != null) {
9148 longMsg = shortMsg;
9149 }
9150
Dan Egnor60d87622009-12-16 16:32:58 -08009151 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009152 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009153 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009154 try {
9155 String name = r != null ? r.processName : null;
9156 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009157 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009158 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009159 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009160 + " at watcher's request");
9161 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009162 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009163 }
9164 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009165 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009166 }
9167 }
9168
9169 final long origId = Binder.clearCallingIdentity();
9170
9171 // If this process is running instrumentation, finish it.
9172 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009173 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009174 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009175 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9176 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 Bundle info = new Bundle();
9178 info.putString("shortMsg", shortMsg);
9179 info.putString("longMsg", longMsg);
9180 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9181 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009182 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 }
9184
Dan Egnor60d87622009-12-16 16:32:58 -08009185 // If we can't identify the process or it's already exceeded its crash quota,
9186 // quit right away without showing a crash dialog.
9187 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009188 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009189 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009190 }
9191
9192 Message msg = Message.obtain();
9193 msg.what = SHOW_ERROR_MSG;
9194 HashMap data = new HashMap();
9195 data.put("result", result);
9196 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009197 msg.obj = data;
9198 mHandler.sendMessage(msg);
9199
9200 Binder.restoreCallingIdentity(origId);
9201 }
9202
9203 int res = result.get();
9204
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009205 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009206 synchronized (this) {
9207 if (r != null) {
9208 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9209 SystemClock.uptimeMillis());
9210 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009211 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009212 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009213 }
9214 }
9215
9216 if (appErrorIntent != null) {
9217 try {
9218 mContext.startActivity(appErrorIntent);
9219 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009220 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009223 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009224
9225 Intent createAppErrorIntentLocked(ProcessRecord r,
9226 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9227 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009228 if (report == null) {
9229 return null;
9230 }
9231 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9232 result.setComponent(r.errorReportReceiver);
9233 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9234 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9235 return result;
9236 }
9237
Dan Egnorb7f03672009-12-09 16:22:32 -08009238 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9239 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009240 if (r.errorReportReceiver == null) {
9241 return null;
9242 }
9243
9244 if (!r.crashing && !r.notResponding) {
9245 return null;
9246 }
9247
Dan Egnorb7f03672009-12-09 16:22:32 -08009248 ApplicationErrorReport report = new ApplicationErrorReport();
9249 report.packageName = r.info.packageName;
9250 report.installerPackageName = r.errorReportReceiver.getPackageName();
9251 report.processName = r.processName;
9252 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009253 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009254
Dan Egnorb7f03672009-12-09 16:22:32 -08009255 if (r.crashing) {
9256 report.type = ApplicationErrorReport.TYPE_CRASH;
9257 report.crashInfo = crashInfo;
9258 } else if (r.notResponding) {
9259 report.type = ApplicationErrorReport.TYPE_ANR;
9260 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009261
Dan Egnorb7f03672009-12-09 16:22:32 -08009262 report.anrInfo.activity = r.notRespondingReport.tag;
9263 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9264 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009265 }
9266
Dan Egnorb7f03672009-12-09 16:22:32 -08009267 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009268 }
9269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009270 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9271 // assume our apps are happy - lazy create the list
9272 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9273
9274 synchronized (this) {
9275
9276 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009277 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9278 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9280 // This one's in trouble, so we'll generate a report for it
9281 // crashes are higher priority (in case there's a crash *and* an anr)
9282 ActivityManager.ProcessErrorStateInfo report = null;
9283 if (app.crashing) {
9284 report = app.crashingReport;
9285 } else if (app.notResponding) {
9286 report = app.notRespondingReport;
9287 }
9288
9289 if (report != null) {
9290 if (errList == null) {
9291 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9292 }
9293 errList.add(report);
9294 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009295 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009296 " crashing = " + app.crashing +
9297 " notResponding = " + app.notResponding);
9298 }
9299 }
9300 }
9301 }
9302
9303 return errList;
9304 }
9305
9306 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9307 // Lazy instantiation of list
9308 List<ActivityManager.RunningAppProcessInfo> runList = null;
9309 synchronized (this) {
9310 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009311 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9312 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009313 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9314 // Generate process state info for running application
9315 ActivityManager.RunningAppProcessInfo currApp =
9316 new ActivityManager.RunningAppProcessInfo(app.processName,
9317 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009318 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009319 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009320 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009321 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9322 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9323 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009324 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9325 } else if (adj >= HOME_APP_ADJ) {
9326 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9327 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009328 } else if (adj >= SECONDARY_SERVER_ADJ) {
9329 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9330 } else if (adj >= VISIBLE_APP_ADJ) {
9331 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9332 } else {
9333 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9334 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009335 currApp.importanceReasonCode = app.adjTypeCode;
9336 if (app.adjSource instanceof ProcessRecord) {
9337 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9338 } else if (app.adjSource instanceof HistoryRecord) {
9339 HistoryRecord r = (HistoryRecord)app.adjSource;
9340 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9341 }
9342 if (app.adjTarget instanceof ComponentName) {
9343 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9344 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009345 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009346 // + " lru=" + currApp.lru);
9347 if (runList == null) {
9348 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9349 }
9350 runList.add(currApp);
9351 }
9352 }
9353 }
9354 return runList;
9355 }
9356
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009357 public List<ApplicationInfo> getRunningExternalApplications() {
9358 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9359 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9360 if (runningApps != null && runningApps.size() > 0) {
9361 Set<String> extList = new HashSet<String>();
9362 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9363 if (app.pkgList != null) {
9364 for (String pkg : app.pkgList) {
9365 extList.add(pkg);
9366 }
9367 }
9368 }
9369 IPackageManager pm = ActivityThread.getPackageManager();
9370 for (String pkg : extList) {
9371 try {
9372 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9373 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9374 retList.add(info);
9375 }
9376 } catch (RemoteException e) {
9377 }
9378 }
9379 }
9380 return retList;
9381 }
9382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009383 @Override
9384 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009385 if (checkCallingPermission(android.Manifest.permission.DUMP)
9386 != PackageManager.PERMISSION_GRANTED) {
9387 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9388 + Binder.getCallingPid()
9389 + ", uid=" + Binder.getCallingUid()
9390 + " without permission "
9391 + android.Manifest.permission.DUMP);
9392 return;
9393 }
9394
9395 boolean dumpAll = false;
9396
9397 int opti = 0;
9398 while (opti < args.length) {
9399 String opt = args[opti];
9400 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9401 break;
9402 }
9403 opti++;
9404 if ("-a".equals(opt)) {
9405 dumpAll = true;
9406 } else if ("-h".equals(opt)) {
9407 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009408 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009409 pw.println(" cmd may be one of:");
9410 pw.println(" activities: activity stack state");
9411 pw.println(" broadcasts: broadcast state");
9412 pw.println(" intents: pending intent state");
9413 pw.println(" processes: process state");
9414 pw.println(" providers: content provider state");
9415 pw.println(" services: service state");
9416 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009417 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009418 } else {
9419 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009421 }
9422
9423 // Is the caller requesting to dump a particular piece of data?
9424 if (opti < args.length) {
9425 String cmd = args[opti];
9426 opti++;
9427 if ("activities".equals(cmd) || "a".equals(cmd)) {
9428 synchronized (this) {
9429 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009430 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009431 return;
9432 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9433 synchronized (this) {
9434 dumpBroadcastsLocked(fd, pw, args, opti, true);
9435 }
9436 return;
9437 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9438 synchronized (this) {
9439 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9440 }
9441 return;
9442 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9443 synchronized (this) {
9444 dumpProcessesLocked(fd, pw, args, opti, true);
9445 }
9446 return;
9447 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9448 synchronized (this) {
9449 dumpProvidersLocked(fd, pw, args, opti, true);
9450 }
9451 return;
9452 } else if ("service".equals(cmd)) {
9453 dumpService(fd, pw, args, opti, true);
9454 return;
9455 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9456 synchronized (this) {
9457 dumpServicesLocked(fd, pw, args, opti, true);
9458 }
9459 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009460 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009461 }
9462
9463 // No piece of data specified, dump everything.
9464 synchronized (this) {
9465 boolean needSep;
9466 if (dumpAll) {
9467 pw.println("Providers in Current Activity Manager State:");
9468 }
9469 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9470 if (needSep) {
9471 pw.println(" ");
9472 }
9473 if (dumpAll) {
9474 pw.println("-------------------------------------------------------------------------------");
9475 pw.println("Broadcasts in Current Activity Manager State:");
9476 }
9477 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9478 if (needSep) {
9479 pw.println(" ");
9480 }
9481 if (dumpAll) {
9482 pw.println("-------------------------------------------------------------------------------");
9483 pw.println("Services in Current Activity Manager State:");
9484 }
9485 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9486 if (needSep) {
9487 pw.println(" ");
9488 }
9489 if (dumpAll) {
9490 pw.println("-------------------------------------------------------------------------------");
9491 pw.println("PendingIntents in Current Activity Manager State:");
9492 }
9493 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9494 if (needSep) {
9495 pw.println(" ");
9496 }
9497 if (dumpAll) {
9498 pw.println("-------------------------------------------------------------------------------");
9499 pw.println("Activities in Current Activity Manager State:");
9500 }
9501 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9502 if (needSep) {
9503 pw.println(" ");
9504 }
9505 if (dumpAll) {
9506 pw.println("-------------------------------------------------------------------------------");
9507 pw.println("Processes in Current Activity Manager State:");
9508 }
9509 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9510 }
9511 }
9512
9513 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9514 int opti, boolean dumpAll, boolean needHeader) {
9515 if (needHeader) {
9516 pw.println(" Activity stack:");
9517 }
9518 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9519 pw.println(" ");
9520 pw.println(" Running activities (most recent first):");
9521 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9522 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009523 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009524 pw.println(" Activities waiting for another to become visible:");
9525 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9526 }
9527 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009528 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009529 pw.println(" Activities waiting to stop:");
9530 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9531 }
9532 if (mFinishingActivities.size() > 0) {
9533 pw.println(" ");
9534 pw.println(" Activities waiting to finish:");
9535 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009537
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009538 pw.println(" ");
9539 pw.println(" mPausingActivity: " + mPausingActivity);
9540 pw.println(" mResumedActivity: " + mResumedActivity);
9541 pw.println(" mFocusedActivity: " + mFocusedActivity);
9542 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009543
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009544 if (dumpAll && mRecentTasks.size() > 0) {
9545 pw.println(" ");
9546 pw.println("Recent tasks in Current Activity Manager State:");
9547
9548 final int N = mRecentTasks.size();
9549 for (int i=0; i<N; i++) {
9550 TaskRecord tr = mRecentTasks.get(i);
9551 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9552 pw.println(tr);
9553 mRecentTasks.get(i).dump(pw, " ");
9554 }
9555 }
9556
9557 pw.println(" ");
9558 pw.println(" mCurTask: " + mCurTask);
9559
9560 return true;
9561 }
9562
9563 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9564 int opti, boolean dumpAll) {
9565 boolean needSep = false;
9566 int numPers = 0;
9567
9568 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009569 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9570 final int NA = procs.size();
9571 for (int ia=0; ia<NA; ia++) {
9572 if (!needSep) {
9573 pw.println(" All known processes:");
9574 needSep = true;
9575 }
9576 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009577 pw.print(r.persistent ? " *PERS*" : " *APP*");
9578 pw.print(" UID "); pw.print(procs.keyAt(ia));
9579 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009580 r.dump(pw, " ");
9581 if (r.persistent) {
9582 numPers++;
9583 }
9584 }
9585 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009586 }
9587
9588 if (mLruProcesses.size() > 0) {
9589 if (needSep) pw.println(" ");
9590 needSep = true;
9591 pw.println(" Running processes (most recent first):");
9592 dumpProcessList(pw, this, mLruProcesses, " ",
9593 "App ", "PERS", true);
9594 needSep = true;
9595 }
9596
9597 synchronized (mPidsSelfLocked) {
9598 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009599 if (needSep) pw.println(" ");
9600 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009601 pw.println(" PID mappings:");
9602 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9603 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9604 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009605 }
9606 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009607 }
9608
9609 if (mForegroundProcesses.size() > 0) {
9610 if (needSep) pw.println(" ");
9611 needSep = true;
9612 pw.println(" Foreground Processes:");
9613 for (int i=0; i<mForegroundProcesses.size(); i++) {
9614 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9615 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009616 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009617 }
9618
9619 if (mPersistentStartingProcesses.size() > 0) {
9620 if (needSep) pw.println(" ");
9621 needSep = true;
9622 pw.println(" Persisent processes that are starting:");
9623 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9624 "Starting Norm", "Restarting PERS", false);
9625 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009627 if (mStartingProcesses.size() > 0) {
9628 if (needSep) pw.println(" ");
9629 needSep = true;
9630 pw.println(" Processes that are starting:");
9631 dumpProcessList(pw, this, mStartingProcesses, " ",
9632 "Starting Norm", "Starting PERS", false);
9633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009634
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009635 if (mRemovedProcesses.size() > 0) {
9636 if (needSep) pw.println(" ");
9637 needSep = true;
9638 pw.println(" Processes that are being removed:");
9639 dumpProcessList(pw, this, mRemovedProcesses, " ",
9640 "Removed Norm", "Removed PERS", false);
9641 }
9642
9643 if (mProcessesOnHold.size() > 0) {
9644 if (needSep) pw.println(" ");
9645 needSep = true;
9646 pw.println(" Processes that are on old until the system is ready:");
9647 dumpProcessList(pw, this, mProcessesOnHold, " ",
9648 "OnHold Norm", "OnHold PERS", false);
9649 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009650
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009651 if (mProcessesToGc.size() > 0) {
9652 if (needSep) pw.println(" ");
9653 needSep = true;
9654 pw.println(" Processes that are waiting to GC:");
9655 long now = SystemClock.uptimeMillis();
9656 for (int i=0; i<mProcessesToGc.size(); i++) {
9657 ProcessRecord proc = mProcessesToGc.get(i);
9658 pw.print(" Process "); pw.println(proc);
9659 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9660 pw.print(", last gced=");
9661 pw.print(now-proc.lastRequestedGc);
9662 pw.print(" ms ago, last lowMem=");
9663 pw.print(now-proc.lastLowMemory);
9664 pw.println(" ms ago");
9665
9666 }
9667 }
9668
9669 if (mProcessCrashTimes.getMap().size() > 0) {
9670 if (needSep) pw.println(" ");
9671 needSep = true;
9672 pw.println(" Time since processes crashed:");
9673 long now = SystemClock.uptimeMillis();
9674 for (Map.Entry<String, SparseArray<Long>> procs
9675 : mProcessCrashTimes.getMap().entrySet()) {
9676 SparseArray<Long> uids = procs.getValue();
9677 final int N = uids.size();
9678 for (int i=0; i<N; i++) {
9679 pw.print(" Process "); pw.print(procs.getKey());
9680 pw.print(" uid "); pw.print(uids.keyAt(i));
9681 pw.print(": last crashed ");
9682 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009683 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009684 }
9685 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009687
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009688 if (mBadProcesses.getMap().size() > 0) {
9689 if (needSep) pw.println(" ");
9690 needSep = true;
9691 pw.println(" Bad processes:");
9692 for (Map.Entry<String, SparseArray<Long>> procs
9693 : mBadProcesses.getMap().entrySet()) {
9694 SparseArray<Long> uids = procs.getValue();
9695 final int N = uids.size();
9696 for (int i=0; i<N; i++) {
9697 pw.print(" Bad process "); pw.print(procs.getKey());
9698 pw.print(" uid "); pw.print(uids.keyAt(i));
9699 pw.print(": crashed at time ");
9700 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009701 }
9702 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009703 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009705 pw.println(" ");
9706 pw.println(" mHomeProcess: " + mHomeProcess);
9707 pw.println(" mConfiguration: " + mConfiguration);
9708 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9709 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9710 || mOrigWaitForDebugger) {
9711 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9712 + " mDebugTransient=" + mDebugTransient
9713 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9714 }
9715 if (mAlwaysFinishActivities || mController != null) {
9716 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9717 + " mController=" + mController);
9718 }
9719 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009720 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009721 pw.println(" mStartRunning=" + mStartRunning
9722 + " mSystemReady=" + mSystemReady
9723 + " mBooting=" + mBooting
9724 + " mBooted=" + mBooted
9725 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009726 pw.println(" mGoingToSleep=" + mGoingToSleep);
9727 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009728 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009729
9730 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009731 }
9732
9733 /**
9734 * There are three ways to call this:
9735 * - no service specified: dump all the services
9736 * - a flattened component name that matched an existing service was specified as the
9737 * first arg: dump that one service
9738 * - the first arg isn't the flattened component name of an existing service:
9739 * dump all services whose component contains the first arg as a substring
9740 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009741 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9742 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009743 String[] newArgs;
9744 String componentNameString;
9745 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009746 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009747 componentNameString = null;
9748 newArgs = EMPTY_STRING_ARRAY;
9749 r = null;
9750 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009751 componentNameString = args[opti];
9752 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009753 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9754 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009755 newArgs = new String[args.length - opti];
9756 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 }
9758
9759 if (r != null) {
9760 dumpService(fd, pw, r, newArgs);
9761 } else {
9762 for (ServiceRecord r1 : mServices.values()) {
9763 if (componentNameString == null
9764 || r1.name.flattenToString().contains(componentNameString)) {
9765 dumpService(fd, pw, r1, newArgs);
9766 }
9767 }
9768 }
9769 }
9770
9771 /**
9772 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9773 * there is a thread associated with the service.
9774 */
9775 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9776 pw.println(" Service " + r.name.flattenToString());
9777 if (r.app != null && r.app.thread != null) {
9778 try {
9779 // flush anything that is already in the PrintWriter since the thread is going
9780 // to write to the file descriptor directly
9781 pw.flush();
9782 r.app.thread.dumpService(fd, r, args);
9783 pw.print("\n");
9784 } catch (RemoteException e) {
9785 pw.println("got a RemoteException while dumping the service");
9786 }
9787 }
9788 }
9789
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009790 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9791 int opti, boolean dumpAll) {
9792 boolean needSep = false;
9793
9794 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009795 if (mRegisteredReceivers.size() > 0) {
9796 pw.println(" ");
9797 pw.println(" Registered Receivers:");
9798 Iterator it = mRegisteredReceivers.values().iterator();
9799 while (it.hasNext()) {
9800 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009801 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009802 r.dump(pw, " ");
9803 }
9804 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009806 pw.println(" ");
9807 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009808 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009809 needSep = true;
9810 }
9811
9812 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9813 || mPendingBroadcast != null) {
9814 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009815 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009816 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009817 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009818 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9819 pw.println(" Broadcast #" + i + ":");
9820 mParallelBroadcasts.get(i).dump(pw, " ");
9821 }
9822 if (mOrderedBroadcasts.size() > 0) {
9823 pw.println(" ");
9824 pw.println(" Active serialized broadcasts:");
9825 }
9826 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9827 pw.println(" Serialized Broadcast #" + i + ":");
9828 mOrderedBroadcasts.get(i).dump(pw, " ");
9829 }
9830 pw.println(" ");
9831 pw.println(" Pending broadcast:");
9832 if (mPendingBroadcast != null) {
9833 mPendingBroadcast.dump(pw, " ");
9834 } else {
9835 pw.println(" (null)");
9836 }
9837 needSep = true;
9838 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009840 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009841 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009842 pw.println(" Historical broadcasts:");
9843 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9844 BroadcastRecord r = mBroadcastHistory[i];
9845 if (r == null) {
9846 break;
9847 }
9848 pw.println(" Historical Broadcast #" + i + ":");
9849 r.dump(pw, " ");
9850 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009851 needSep = true;
9852 }
9853
9854 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009855 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009856 pw.println(" Sticky broadcasts:");
9857 StringBuilder sb = new StringBuilder(128);
9858 for (Map.Entry<String, ArrayList<Intent>> ent
9859 : mStickyBroadcasts.entrySet()) {
9860 pw.print(" * Sticky action "); pw.print(ent.getKey());
9861 pw.println(":");
9862 ArrayList<Intent> intents = ent.getValue();
9863 final int N = intents.size();
9864 for (int i=0; i<N; i++) {
9865 sb.setLength(0);
9866 sb.append(" Intent: ");
9867 intents.get(i).toShortString(sb, true, false);
9868 pw.println(sb.toString());
9869 Bundle bundle = intents.get(i).getExtras();
9870 if (bundle != null) {
9871 pw.print(" ");
9872 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009873 }
9874 }
9875 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009876 needSep = true;
9877 }
9878
9879 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009880 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009881 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009882 pw.println(" mHandler:");
9883 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009884 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009885 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009886
9887 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009888 }
9889
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009890 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9891 int opti, boolean dumpAll) {
9892 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009893
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009894 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009895 if (mServices.size() > 0) {
9896 pw.println(" Active services:");
9897 Iterator<ServiceRecord> it = mServices.values().iterator();
9898 while (it.hasNext()) {
9899 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009900 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901 r.dump(pw, " ");
9902 }
9903 needSep = true;
9904 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009906
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009907 if (mPendingServices.size() > 0) {
9908 if (needSep) pw.println(" ");
9909 pw.println(" Pending services:");
9910 for (int i=0; i<mPendingServices.size(); i++) {
9911 ServiceRecord r = mPendingServices.get(i);
9912 pw.print(" * Pending "); pw.println(r);
9913 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009914 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009915 needSep = true;
9916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009917
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009918 if (mRestartingServices.size() > 0) {
9919 if (needSep) pw.println(" ");
9920 pw.println(" Restarting services:");
9921 for (int i=0; i<mRestartingServices.size(); i++) {
9922 ServiceRecord r = mRestartingServices.get(i);
9923 pw.print(" * Restarting "); pw.println(r);
9924 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009925 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009926 needSep = true;
9927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009928
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009929 if (mStoppingServices.size() > 0) {
9930 if (needSep) pw.println(" ");
9931 pw.println(" Stopping services:");
9932 for (int i=0; i<mStoppingServices.size(); i++) {
9933 ServiceRecord r = mStoppingServices.get(i);
9934 pw.print(" * Stopping "); pw.println(r);
9935 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009936 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009937 needSep = true;
9938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009939
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009940 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009941 if (mServiceConnections.size() > 0) {
9942 if (needSep) pw.println(" ");
9943 pw.println(" Connection bindings to services:");
9944 Iterator<ConnectionRecord> it
9945 = mServiceConnections.values().iterator();
9946 while (it.hasNext()) {
9947 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009948 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009949 r.dump(pw, " ");
9950 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009951 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009952 }
9953 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009954
9955 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009956 }
9957
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009958 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9959 int opti, boolean dumpAll) {
9960 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009961
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009962 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009963 if (mProvidersByClass.size() > 0) {
9964 if (needSep) pw.println(" ");
9965 pw.println(" Published content providers (by class):");
9966 Iterator it = mProvidersByClass.entrySet().iterator();
9967 while (it.hasNext()) {
9968 Map.Entry e = (Map.Entry)it.next();
9969 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009970 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971 r.dump(pw, " ");
9972 }
9973 needSep = true;
9974 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009975
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009976 if (mProvidersByName.size() > 0) {
9977 pw.println(" ");
9978 pw.println(" Authority to provider mappings:");
9979 Iterator it = mProvidersByName.entrySet().iterator();
9980 while (it.hasNext()) {
9981 Map.Entry e = (Map.Entry)it.next();
9982 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9983 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9984 pw.println(r);
9985 }
9986 needSep = true;
9987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009988 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009989
9990 if (mLaunchingProviders.size() > 0) {
9991 if (needSep) pw.println(" ");
9992 pw.println(" Launching content providers:");
9993 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9994 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9995 pw.println(mLaunchingProviders.get(i));
9996 }
9997 needSep = true;
9998 }
9999
10000 if (mGrantedUriPermissions.size() > 0) {
10001 pw.println();
10002 pw.println("Granted Uri Permissions:");
10003 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10004 int uid = mGrantedUriPermissions.keyAt(i);
10005 HashMap<Uri, UriPermission> perms
10006 = mGrantedUriPermissions.valueAt(i);
10007 pw.print(" * UID "); pw.print(uid);
10008 pw.println(" holds:");
10009 for (UriPermission perm : perms.values()) {
10010 pw.print(" "); pw.println(perm);
10011 perm.dump(pw, " ");
10012 }
10013 }
10014 needSep = true;
10015 }
10016
10017 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010018 }
10019
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010020 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10021 int opti, boolean dumpAll) {
10022 boolean needSep = false;
10023
10024 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010025 if (this.mIntentSenderRecords.size() > 0) {
10026 Iterator<WeakReference<PendingIntentRecord>> it
10027 = mIntentSenderRecords.values().iterator();
10028 while (it.hasNext()) {
10029 WeakReference<PendingIntentRecord> ref = it.next();
10030 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010031 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010033 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010034 rec.dump(pw, " ");
10035 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010036 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010037 }
10038 }
10039 }
10040 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010041
10042 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010043 }
10044
10045 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010046 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010047 TaskRecord lastTask = null;
10048 for (int i=list.size()-1; i>=0; i--) {
10049 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010050 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010051 if (lastTask != r.task) {
10052 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010053 pw.print(prefix);
10054 pw.print(full ? "* " : " ");
10055 pw.println(lastTask);
10056 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010057 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010059 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010060 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10061 pw.print(" #"); pw.print(i); pw.print(": ");
10062 pw.println(r);
10063 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010064 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 }
10067 }
10068
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010069 private static String buildOomTag(String prefix, String space, int val, int base) {
10070 if (val == base) {
10071 if (space == null) return prefix;
10072 return prefix + " ";
10073 }
10074 return prefix + "+" + Integer.toString(val-base);
10075 }
10076
10077 private static final int dumpProcessList(PrintWriter pw,
10078 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010079 String prefix, String normalLabel, String persistentLabel,
10080 boolean inclOomAdj) {
10081 int numPers = 0;
10082 for (int i=list.size()-1; i>=0; i--) {
10083 ProcessRecord r = (ProcessRecord)list.get(i);
10084 if (false) {
10085 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10086 + " #" + i + ":");
10087 r.dump(pw, prefix + " ");
10088 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010089 String oomAdj;
10090 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010091 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010092 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010093 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10094 } else if (r.setAdj >= HOME_APP_ADJ) {
10095 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10096 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10097 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10098 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10099 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10100 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10101 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10102 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10103 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010104 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010105 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010106 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010107 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010108 } else {
10109 oomAdj = Integer.toString(r.setAdj);
10110 }
10111 String schedGroup;
10112 switch (r.setSchedGroup) {
10113 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10114 schedGroup = "B";
10115 break;
10116 case Process.THREAD_GROUP_DEFAULT:
10117 schedGroup = "F";
10118 break;
10119 default:
10120 schedGroup = Integer.toString(r.setSchedGroup);
10121 break;
10122 }
10123 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010124 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010125 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010126 if (r.adjSource != null || r.adjTarget != null) {
10127 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010128 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010130 } else {
10131 pw.println(String.format("%s%s #%2d: %s",
10132 prefix, (r.persistent ? persistentLabel : normalLabel),
10133 i, r.toString()));
10134 }
10135 if (r.persistent) {
10136 numPers++;
10137 }
10138 }
10139 return numPers;
10140 }
10141
10142 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
10143 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010144 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010145 long uptime = SystemClock.uptimeMillis();
10146 long realtime = SystemClock.elapsedRealtime();
10147
10148 if (isCheckinRequest) {
10149 // short checkin version
10150 pw.println(uptime + "," + realtime);
10151 pw.flush();
10152 } else {
10153 pw.println("Applications Memory Usage (kB):");
10154 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10155 }
10156 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10157 ProcessRecord r = (ProcessRecord)list.get(i);
10158 if (r.thread != null) {
10159 if (!isCheckinRequest) {
10160 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10161 pw.flush();
10162 }
10163 try {
10164 r.thread.asBinder().dump(fd, args);
10165 } catch (RemoteException e) {
10166 if (!isCheckinRequest) {
10167 pw.println("Got RemoteException!");
10168 pw.flush();
10169 }
10170 }
10171 }
10172 }
10173 }
10174
10175 /**
10176 * Searches array of arguments for the specified string
10177 * @param args array of argument strings
10178 * @param value value to search for
10179 * @return true if the value is contained in the array
10180 */
10181 private static boolean scanArgs(String[] args, String value) {
10182 if (args != null) {
10183 for (String arg : args) {
10184 if (value.equals(arg)) {
10185 return true;
10186 }
10187 }
10188 }
10189 return false;
10190 }
10191
Dianne Hackborn75b03852009-06-12 15:43:26 -070010192 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010193 int count = mHistory.size();
10194
10195 // convert the token to an entry in the history.
10196 HistoryRecord r = null;
10197 int index = -1;
10198 for (int i=count-1; i>=0; i--) {
10199 Object o = mHistory.get(i);
10200 if (o == token) {
10201 r = (HistoryRecord)o;
10202 index = i;
10203 break;
10204 }
10205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206
10207 return index;
10208 }
10209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010210 private final void killServicesLocked(ProcessRecord app,
10211 boolean allowRestart) {
10212 // Report disconnected services.
10213 if (false) {
10214 // XXX we are letting the client link to the service for
10215 // death notifications.
10216 if (app.services.size() > 0) {
10217 Iterator it = app.services.iterator();
10218 while (it.hasNext()) {
10219 ServiceRecord r = (ServiceRecord)it.next();
10220 if (r.connections.size() > 0) {
10221 Iterator<ConnectionRecord> jt
10222 = r.connections.values().iterator();
10223 while (jt.hasNext()) {
10224 ConnectionRecord c = jt.next();
10225 if (c.binding.client != app) {
10226 try {
10227 //c.conn.connected(r.className, null);
10228 } catch (Exception e) {
10229 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010230 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010231 + r.shortName
10232 + " from app " + app.processName, e);
10233 }
10234 }
10235 }
10236 }
10237 }
10238 }
10239 }
10240
10241 // Clean up any connections this application has to other services.
10242 if (app.connections.size() > 0) {
10243 Iterator<ConnectionRecord> it = app.connections.iterator();
10244 while (it.hasNext()) {
10245 ConnectionRecord r = it.next();
10246 removeConnectionLocked(r, app, null);
10247 }
10248 }
10249 app.connections.clear();
10250
10251 if (app.services.size() != 0) {
10252 // Any services running in the application need to be placed
10253 // back in the pending list.
10254 Iterator it = app.services.iterator();
10255 while (it.hasNext()) {
10256 ServiceRecord sr = (ServiceRecord)it.next();
10257 synchronized (sr.stats.getBatteryStats()) {
10258 sr.stats.stopLaunchedLocked();
10259 }
10260 sr.app = null;
10261 sr.executeNesting = 0;
10262 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010263
10264 boolean hasClients = sr.bindings.size() > 0;
10265 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 Iterator<IntentBindRecord> bindings
10267 = sr.bindings.values().iterator();
10268 while (bindings.hasNext()) {
10269 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010270 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010271 + ": shouldUnbind=" + b.hasBound);
10272 b.binder = null;
10273 b.requested = b.received = b.hasBound = false;
10274 }
10275 }
10276
10277 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010278 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010279 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010280 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010281 sr.crashCount, sr.shortName, app.pid);
10282 bringDownServiceLocked(sr, true);
10283 } else if (!allowRestart) {
10284 bringDownServiceLocked(sr, true);
10285 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010286 boolean canceled = scheduleServiceRestartLocked(sr, true);
10287
10288 // Should the service remain running? Note that in the
10289 // extreme case of so many attempts to deliver a command
10290 // that it failed, that we also will stop it here.
10291 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10292 if (sr.pendingStarts.size() == 0) {
10293 sr.startRequested = false;
10294 if (!hasClients) {
10295 // Whoops, no reason to restart!
10296 bringDownServiceLocked(sr, true);
10297 }
10298 }
10299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010300 }
10301 }
10302
10303 if (!allowRestart) {
10304 app.services.clear();
10305 }
10306 }
10307
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010308 // Make sure we have no more records on the stopping list.
10309 int i = mStoppingServices.size();
10310 while (i > 0) {
10311 i--;
10312 ServiceRecord sr = mStoppingServices.get(i);
10313 if (sr.app == app) {
10314 mStoppingServices.remove(i);
10315 }
10316 }
10317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010318 app.executingServices.clear();
10319 }
10320
10321 private final void removeDyingProviderLocked(ProcessRecord proc,
10322 ContentProviderRecord cpr) {
10323 synchronized (cpr) {
10324 cpr.launchingApp = null;
10325 cpr.notifyAll();
10326 }
10327
10328 mProvidersByClass.remove(cpr.info.name);
10329 String names[] = cpr.info.authority.split(";");
10330 for (int j = 0; j < names.length; j++) {
10331 mProvidersByName.remove(names[j]);
10332 }
10333
10334 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10335 while (cit.hasNext()) {
10336 ProcessRecord capp = cit.next();
10337 if (!capp.persistent && capp.thread != null
10338 && capp.pid != 0
10339 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010340 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010341 + " (pid " + capp.pid
10342 + ") because provider " + cpr.info.name
10343 + " is in dying process " + proc.processName);
10344 Process.killProcess(capp.pid);
10345 }
10346 }
10347
10348 mLaunchingProviders.remove(cpr);
10349 }
10350
10351 /**
10352 * Main code for cleaning up a process when it has gone away. This is
10353 * called both as a result of the process dying, or directly when stopping
10354 * a process when running in single process mode.
10355 */
10356 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10357 boolean restarting, int index) {
10358 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010359 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010360 }
10361
Dianne Hackborn36124872009-10-08 16:22:03 -070010362 mProcessesToGc.remove(app);
10363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010364 // Dismiss any open dialogs.
10365 if (app.crashDialog != null) {
10366 app.crashDialog.dismiss();
10367 app.crashDialog = null;
10368 }
10369 if (app.anrDialog != null) {
10370 app.anrDialog.dismiss();
10371 app.anrDialog = null;
10372 }
10373 if (app.waitDialog != null) {
10374 app.waitDialog.dismiss();
10375 app.waitDialog = null;
10376 }
10377
10378 app.crashing = false;
10379 app.notResponding = false;
10380
10381 app.resetPackageList();
10382 app.thread = null;
10383 app.forcingToForeground = null;
10384 app.foregroundServices = false;
10385
10386 killServicesLocked(app, true);
10387
10388 boolean restart = false;
10389
10390 int NL = mLaunchingProviders.size();
10391
10392 // Remove published content providers.
10393 if (!app.pubProviders.isEmpty()) {
10394 Iterator it = app.pubProviders.values().iterator();
10395 while (it.hasNext()) {
10396 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10397 cpr.provider = null;
10398 cpr.app = null;
10399
10400 // See if someone is waiting for this provider... in which
10401 // case we don't remove it, but just let it restart.
10402 int i = 0;
10403 if (!app.bad) {
10404 for (; i<NL; i++) {
10405 if (mLaunchingProviders.get(i) == cpr) {
10406 restart = true;
10407 break;
10408 }
10409 }
10410 } else {
10411 i = NL;
10412 }
10413
10414 if (i >= NL) {
10415 removeDyingProviderLocked(app, cpr);
10416 NL = mLaunchingProviders.size();
10417 }
10418 }
10419 app.pubProviders.clear();
10420 }
10421
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010422 // Take care of any launching providers waiting for this process.
10423 if (checkAppInLaunchingProvidersLocked(app, false)) {
10424 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 // Unregister from connected content providers.
10428 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010429 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 while (it.hasNext()) {
10431 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10432 cpr.clients.remove(app);
10433 }
10434 app.conProviders.clear();
10435 }
10436
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010437 // At this point there may be remaining entries in mLaunchingProviders
10438 // where we were the only one waiting, so they are no longer of use.
10439 // Look for these and clean up if found.
10440 // XXX Commented out for now. Trying to figure out a way to reproduce
10441 // the actual situation to identify what is actually going on.
10442 if (false) {
10443 for (int i=0; i<NL; i++) {
10444 ContentProviderRecord cpr = (ContentProviderRecord)
10445 mLaunchingProviders.get(i);
10446 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10447 synchronized (cpr) {
10448 cpr.launchingApp = null;
10449 cpr.notifyAll();
10450 }
10451 }
10452 }
10453 }
10454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010455 skipCurrentReceiverLocked(app);
10456
10457 // Unregister any receivers.
10458 if (app.receivers.size() > 0) {
10459 Iterator<ReceiverList> it = app.receivers.iterator();
10460 while (it.hasNext()) {
10461 removeReceiverLocked(it.next());
10462 }
10463 app.receivers.clear();
10464 }
10465
Christopher Tate181fafa2009-05-14 11:12:14 -070010466 // If the app is undergoing backup, tell the backup manager about it
10467 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010468 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010469 try {
10470 IBackupManager bm = IBackupManager.Stub.asInterface(
10471 ServiceManager.getService(Context.BACKUP_SERVICE));
10472 bm.agentDisconnected(app.info.packageName);
10473 } catch (RemoteException e) {
10474 // can't happen; backup manager is local
10475 }
10476 }
10477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010478 // If the caller is restarting this app, then leave it in its
10479 // current lists and let the caller take care of it.
10480 if (restarting) {
10481 return;
10482 }
10483
10484 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010485 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010486 "Removing non-persistent process during cleanup: " + app);
10487 mProcessNames.remove(app.processName, app.info.uid);
10488 } else if (!app.removed) {
10489 // This app is persistent, so we need to keep its record around.
10490 // If it is not already on the pending app list, add it there
10491 // and start a new process for it.
10492 app.thread = null;
10493 app.forcingToForeground = null;
10494 app.foregroundServices = false;
10495 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10496 mPersistentStartingProcesses.add(app);
10497 restart = true;
10498 }
10499 }
10500 mProcessesOnHold.remove(app);
10501
The Android Open Source Project4df24232009-03-05 14:34:35 -080010502 if (app == mHomeProcess) {
10503 mHomeProcess = null;
10504 }
10505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010506 if (restart) {
10507 // We have components that still need to be running in the
10508 // process, so re-launch it.
10509 mProcessNames.put(app.processName, app.info.uid, app);
10510 startProcessLocked(app, "restart", app.processName);
10511 } else if (app.pid > 0 && app.pid != MY_PID) {
10512 // Goodbye!
10513 synchronized (mPidsSelfLocked) {
10514 mPidsSelfLocked.remove(app.pid);
10515 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10516 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010517 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010518 }
10519 }
10520
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010521 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10522 // Look through the content providers we are waiting to have launched,
10523 // and if any run in this process then either schedule a restart of
10524 // the process or kill the client waiting for it if this process has
10525 // gone bad.
10526 int NL = mLaunchingProviders.size();
10527 boolean restart = false;
10528 for (int i=0; i<NL; i++) {
10529 ContentProviderRecord cpr = (ContentProviderRecord)
10530 mLaunchingProviders.get(i);
10531 if (cpr.launchingApp == app) {
10532 if (!alwaysBad && !app.bad) {
10533 restart = true;
10534 } else {
10535 removeDyingProviderLocked(app, cpr);
10536 NL = mLaunchingProviders.size();
10537 }
10538 }
10539 }
10540 return restart;
10541 }
10542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010543 // =========================================================
10544 // SERVICES
10545 // =========================================================
10546
10547 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10548 ActivityManager.RunningServiceInfo info =
10549 new ActivityManager.RunningServiceInfo();
10550 info.service = r.name;
10551 if (r.app != null) {
10552 info.pid = r.app.pid;
10553 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010554 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010555 info.process = r.processName;
10556 info.foreground = r.isForeground;
10557 info.activeSince = r.createTime;
10558 info.started = r.startRequested;
10559 info.clientCount = r.connections.size();
10560 info.crashCount = r.crashCount;
10561 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010562 if (r.isForeground) {
10563 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10564 }
10565 if (r.startRequested) {
10566 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10567 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010568 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010569 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10570 }
10571 if (r.app != null && r.app.persistent) {
10572 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10573 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010574 for (ConnectionRecord conn : r.connections.values()) {
10575 if (conn.clientLabel != 0) {
10576 info.clientPackage = conn.binding.client.info.packageName;
10577 info.clientLabel = conn.clientLabel;
10578 break;
10579 }
10580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 return info;
10582 }
10583
10584 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10585 int flags) {
10586 synchronized (this) {
10587 ArrayList<ActivityManager.RunningServiceInfo> res
10588 = new ArrayList<ActivityManager.RunningServiceInfo>();
10589
10590 if (mServices.size() > 0) {
10591 Iterator<ServiceRecord> it = mServices.values().iterator();
10592 while (it.hasNext() && res.size() < maxNum) {
10593 res.add(makeRunningServiceInfoLocked(it.next()));
10594 }
10595 }
10596
10597 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10598 ServiceRecord r = mRestartingServices.get(i);
10599 ActivityManager.RunningServiceInfo info =
10600 makeRunningServiceInfoLocked(r);
10601 info.restarting = r.nextRestartTime;
10602 res.add(info);
10603 }
10604
10605 return res;
10606 }
10607 }
10608
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010609 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10610 synchronized (this) {
10611 ServiceRecord r = mServices.get(name);
10612 if (r != null) {
10613 for (ConnectionRecord conn : r.connections.values()) {
10614 if (conn.clientIntent != null) {
10615 return conn.clientIntent;
10616 }
10617 }
10618 }
10619 }
10620 return null;
10621 }
10622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010623 private final ServiceRecord findServiceLocked(ComponentName name,
10624 IBinder token) {
10625 ServiceRecord r = mServices.get(name);
10626 return r == token ? r : null;
10627 }
10628
10629 private final class ServiceLookupResult {
10630 final ServiceRecord record;
10631 final String permission;
10632
10633 ServiceLookupResult(ServiceRecord _record, String _permission) {
10634 record = _record;
10635 permission = _permission;
10636 }
10637 };
10638
10639 private ServiceLookupResult findServiceLocked(Intent service,
10640 String resolvedType) {
10641 ServiceRecord r = null;
10642 if (service.getComponent() != null) {
10643 r = mServices.get(service.getComponent());
10644 }
10645 if (r == null) {
10646 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10647 r = mServicesByIntent.get(filter);
10648 }
10649
10650 if (r == null) {
10651 try {
10652 ResolveInfo rInfo =
10653 ActivityThread.getPackageManager().resolveService(
10654 service, resolvedType, 0);
10655 ServiceInfo sInfo =
10656 rInfo != null ? rInfo.serviceInfo : null;
10657 if (sInfo == null) {
10658 return null;
10659 }
10660
10661 ComponentName name = new ComponentName(
10662 sInfo.applicationInfo.packageName, sInfo.name);
10663 r = mServices.get(name);
10664 } catch (RemoteException ex) {
10665 // pm is in same process, this will never happen.
10666 }
10667 }
10668 if (r != null) {
10669 int callingPid = Binder.getCallingPid();
10670 int callingUid = Binder.getCallingUid();
10671 if (checkComponentPermission(r.permission,
10672 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10673 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010674 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010675 + " from pid=" + callingPid
10676 + ", uid=" + callingUid
10677 + " requires " + r.permission);
10678 return new ServiceLookupResult(null, r.permission);
10679 }
10680 return new ServiceLookupResult(r, null);
10681 }
10682 return null;
10683 }
10684
10685 private class ServiceRestarter implements Runnable {
10686 private ServiceRecord mService;
10687
10688 void setService(ServiceRecord service) {
10689 mService = service;
10690 }
10691
10692 public void run() {
10693 synchronized(ActivityManagerService.this) {
10694 performServiceRestartLocked(mService);
10695 }
10696 }
10697 }
10698
10699 private ServiceLookupResult retrieveServiceLocked(Intent service,
10700 String resolvedType, int callingPid, int callingUid) {
10701 ServiceRecord r = null;
10702 if (service.getComponent() != null) {
10703 r = mServices.get(service.getComponent());
10704 }
10705 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10706 r = mServicesByIntent.get(filter);
10707 if (r == null) {
10708 try {
10709 ResolveInfo rInfo =
10710 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010711 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010712 ServiceInfo sInfo =
10713 rInfo != null ? rInfo.serviceInfo : null;
10714 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010715 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010716 ": not found");
10717 return null;
10718 }
10719
10720 ComponentName name = new ComponentName(
10721 sInfo.applicationInfo.packageName, sInfo.name);
10722 r = mServices.get(name);
10723 if (r == null) {
10724 filter = new Intent.FilterComparison(service.cloneFilter());
10725 ServiceRestarter res = new ServiceRestarter();
10726 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10727 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10728 synchronized (stats) {
10729 ss = stats.getServiceStatsLocked(
10730 sInfo.applicationInfo.uid, sInfo.packageName,
10731 sInfo.name);
10732 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010733 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010734 res.setService(r);
10735 mServices.put(name, r);
10736 mServicesByIntent.put(filter, r);
10737
10738 // Make sure this component isn't in the pending list.
10739 int N = mPendingServices.size();
10740 for (int i=0; i<N; i++) {
10741 ServiceRecord pr = mPendingServices.get(i);
10742 if (pr.name.equals(name)) {
10743 mPendingServices.remove(i);
10744 i--;
10745 N--;
10746 }
10747 }
10748 }
10749 } catch (RemoteException ex) {
10750 // pm is in same process, this will never happen.
10751 }
10752 }
10753 if (r != null) {
10754 if (checkComponentPermission(r.permission,
10755 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10756 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010757 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010758 + " from pid=" + Binder.getCallingPid()
10759 + ", uid=" + Binder.getCallingUid()
10760 + " requires " + r.permission);
10761 return new ServiceLookupResult(null, r.permission);
10762 }
10763 return new ServiceLookupResult(r, null);
10764 }
10765 return null;
10766 }
10767
10768 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10769 long now = SystemClock.uptimeMillis();
10770 if (r.executeNesting == 0 && r.app != null) {
10771 if (r.app.executingServices.size() == 0) {
10772 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10773 msg.obj = r.app;
10774 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10775 }
10776 r.app.executingServices.add(r);
10777 }
10778 r.executeNesting++;
10779 r.executingStart = now;
10780 }
10781
10782 private final void sendServiceArgsLocked(ServiceRecord r,
10783 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010784 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785 if (N == 0) {
10786 return;
10787 }
10788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 int i = 0;
10790 while (i < N) {
10791 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010792 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010793 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010794 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010795 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010796 // If somehow we got a dummy start at the front, then
10797 // just drop it here.
10798 i++;
10799 continue;
10800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 bumpServiceExecutingLocked(r);
10802 if (!oomAdjusted) {
10803 oomAdjusted = true;
10804 updateOomAdjLocked(r.app);
10805 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010806 int flags = 0;
10807 if (si.deliveryCount > 0) {
10808 flags |= Service.START_FLAG_RETRY;
10809 }
10810 if (si.doneExecutingCount > 0) {
10811 flags |= Service.START_FLAG_REDELIVERY;
10812 }
10813 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10814 si.deliveredTime = SystemClock.uptimeMillis();
10815 r.deliveredStarts.add(si);
10816 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010818 } catch (RemoteException e) {
10819 // Remote process gone... we'll let the normal cleanup take
10820 // care of this.
10821 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010823 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010824 break;
10825 }
10826 }
10827 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010828 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 } else {
10830 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010831 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010832 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833 }
10834 }
10835 }
10836
10837 private final boolean requestServiceBindingLocked(ServiceRecord r,
10838 IntentBindRecord i, boolean rebind) {
10839 if (r.app == null || r.app.thread == null) {
10840 // If service is not currently running, can't yet bind.
10841 return false;
10842 }
10843 if ((!i.requested || rebind) && i.apps.size() > 0) {
10844 try {
10845 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010846 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010847 + ": shouldUnbind=" + i.hasBound);
10848 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10849 if (!rebind) {
10850 i.requested = true;
10851 }
10852 i.hasBound = true;
10853 i.doRebind = false;
10854 } catch (RemoteException e) {
10855 return false;
10856 }
10857 }
10858 return true;
10859 }
10860
10861 private final void requestServiceBindingsLocked(ServiceRecord r) {
10862 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10863 while (bindings.hasNext()) {
10864 IntentBindRecord i = bindings.next();
10865 if (!requestServiceBindingLocked(r, i, false)) {
10866 break;
10867 }
10868 }
10869 }
10870
10871 private final void realStartServiceLocked(ServiceRecord r,
10872 ProcessRecord app) throws RemoteException {
10873 if (app.thread == null) {
10874 throw new RemoteException();
10875 }
10876
10877 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010878 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010879
10880 app.services.add(r);
10881 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010882 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010883
10884 boolean created = false;
10885 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010886 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010887 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010888 mStringBuilder.setLength(0);
10889 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010890 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010892 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010893 synchronized (r.stats.getBatteryStats()) {
10894 r.stats.startLaunchedLocked();
10895 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010896 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010897 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010898 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010899 created = true;
10900 } finally {
10901 if (!created) {
10902 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010903 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010904 }
10905 }
10906
10907 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010908
10909 // If the service is in the started state, and there are no
10910 // pending arguments, then fake up one so its onStartCommand() will
10911 // be called.
10912 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10913 r.lastStartId++;
10914 if (r.lastStartId < 1) {
10915 r.lastStartId = 1;
10916 }
10917 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10918 }
10919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010920 sendServiceArgsLocked(r, true);
10921 }
10922
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010923 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10924 boolean allowCancel) {
10925 boolean canceled = false;
10926
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010927 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010928 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010929 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010930
10931 // Any delivered but not yet finished starts should be put back
10932 // on the pending list.
10933 final int N = r.deliveredStarts.size();
10934 if (N > 0) {
10935 for (int i=N-1; i>=0; i--) {
10936 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10937 if (si.intent == null) {
10938 // We'll generate this again if needed.
10939 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10940 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10941 r.pendingStarts.add(0, si);
10942 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10943 dur *= 2;
10944 if (minDuration < dur) minDuration = dur;
10945 if (resetTime < dur) resetTime = dur;
10946 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010947 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010948 + r.name);
10949 canceled = true;
10950 }
10951 }
10952 r.deliveredStarts.clear();
10953 }
10954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010955 r.totalRestartCount++;
10956 if (r.restartDelay == 0) {
10957 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010958 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959 } else {
10960 // If it has been a "reasonably long time" since the service
10961 // was started, then reset our restart duration back to
10962 // the beginning, so we don't infinitely increase the duration
10963 // on a service that just occasionally gets killed (which is
10964 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010965 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010967 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010968 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010969 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010970 if (r.restartDelay < minDuration) {
10971 r.restartDelay = minDuration;
10972 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 }
10974 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010975
10976 r.nextRestartTime = now + r.restartDelay;
10977
10978 // Make sure that we don't end up restarting a bunch of services
10979 // all at the same time.
10980 boolean repeat;
10981 do {
10982 repeat = false;
10983 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10984 ServiceRecord r2 = mRestartingServices.get(i);
10985 if (r2 != r && r.nextRestartTime
10986 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10987 && r.nextRestartTime
10988 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10989 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10990 r.restartDelay = r.nextRestartTime - now;
10991 repeat = true;
10992 break;
10993 }
10994 }
10995 } while (repeat);
10996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 if (!mRestartingServices.contains(r)) {
10998 mRestartingServices.add(r);
10999 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011000
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011001 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011003 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011004 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011005 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011006 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011008 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011009 r.shortName, r.restartDelay);
11010
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011011 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011012 }
11013
11014 final void performServiceRestartLocked(ServiceRecord r) {
11015 if (!mRestartingServices.contains(r)) {
11016 return;
11017 }
11018 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11019 }
11020
11021 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11022 if (r.restartDelay == 0) {
11023 return false;
11024 }
11025 r.resetRestartCounter();
11026 mRestartingServices.remove(r);
11027 mHandler.removeCallbacks(r.restarter);
11028 return true;
11029 }
11030
11031 private final boolean bringUpServiceLocked(ServiceRecord r,
11032 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011033 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011034 //r.dump(" ");
11035
Dianne Hackborn36124872009-10-08 16:22:03 -070011036 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011037 sendServiceArgsLocked(r, false);
11038 return true;
11039 }
11040
11041 if (!whileRestarting && r.restartDelay > 0) {
11042 // If waiting for a restart, then do nothing.
11043 return true;
11044 }
11045
Joe Onorato8a9b2202010-02-26 18:56:32 -080011046 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011047 + " " + r.intent);
11048
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011049 // We are now bringing the service up, so no longer in the
11050 // restarting state.
11051 mRestartingServices.remove(r);
11052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 final String appName = r.processName;
11054 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11055 if (app != null && app.thread != null) {
11056 try {
11057 realStartServiceLocked(r, app);
11058 return true;
11059 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011060 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011061 }
11062
11063 // If a dead object exception was thrown -- fall through to
11064 // restart the application.
11065 }
11066
Dianne Hackborn36124872009-10-08 16:22:03 -070011067 // Not running -- get it started, and enqueue this service record
11068 // to be executed when the app comes up.
11069 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11070 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011071 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011072 + r.appInfo.packageName + "/"
11073 + r.appInfo.uid + " for service "
11074 + r.intent.getIntent() + ": process is bad");
11075 bringDownServiceLocked(r, true);
11076 return false;
11077 }
11078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080 mPendingServices.add(r);
11081 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011083 return true;
11084 }
11085
11086 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011087 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011088 //r.dump(" ");
11089
11090 // Does it still need to run?
11091 if (!force && r.startRequested) {
11092 return;
11093 }
11094 if (r.connections.size() > 0) {
11095 if (!force) {
11096 // XXX should probably keep a count of the number of auto-create
11097 // connections directly in the service.
11098 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11099 while (it.hasNext()) {
11100 ConnectionRecord cr = it.next();
11101 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11102 return;
11103 }
11104 }
11105 }
11106
11107 // Report to all of the connections that the service is no longer
11108 // available.
11109 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11110 while (it.hasNext()) {
11111 ConnectionRecord c = it.next();
11112 try {
11113 // todo: shouldn't be a synchronous call!
11114 c.conn.connected(r.name, null);
11115 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011116 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 " to connection " + c.conn.asBinder() +
11118 " (in " + c.binding.client.processName + ")", e);
11119 }
11120 }
11121 }
11122
11123 // Tell the service that it has been unbound.
11124 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11125 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11126 while (it.hasNext()) {
11127 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011128 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129 + ": hasBound=" + ibr.hasBound);
11130 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11131 try {
11132 bumpServiceExecutingLocked(r);
11133 updateOomAdjLocked(r.app);
11134 ibr.hasBound = false;
11135 r.app.thread.scheduleUnbindService(r,
11136 ibr.intent.getIntent());
11137 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011138 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011139 + r.shortName, e);
11140 serviceDoneExecutingLocked(r, true);
11141 }
11142 }
11143 }
11144 }
11145
Joe Onorato8a9b2202010-02-26 18:56:32 -080011146 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011147 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011148 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 System.identityHashCode(r), r.shortName,
11150 (r.app != null) ? r.app.pid : -1);
11151
11152 mServices.remove(r.name);
11153 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011154 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011155 r.totalRestartCount = 0;
11156 unscheduleServiceRestartLocked(r);
11157
11158 // Also make sure it is not on the pending list.
11159 int N = mPendingServices.size();
11160 for (int i=0; i<N; i++) {
11161 if (mPendingServices.get(i) == r) {
11162 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011163 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 TAG, "Removed pending service: " + r.shortName);
11165 i--;
11166 N--;
11167 }
11168 }
11169
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011170 r.cancelNotification();
11171 r.isForeground = false;
11172 r.foregroundId = 0;
11173 r.foregroundNoti = null;
11174
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011175 // Clear start entries.
11176 r.deliveredStarts.clear();
11177 r.pendingStarts.clear();
11178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011179 if (r.app != null) {
11180 synchronized (r.stats.getBatteryStats()) {
11181 r.stats.stopLaunchedLocked();
11182 }
11183 r.app.services.remove(r);
11184 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011186 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011187 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011188 bumpServiceExecutingLocked(r);
11189 mStoppingServices.add(r);
11190 updateOomAdjLocked(r.app);
11191 r.app.thread.scheduleStopService(r);
11192 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011193 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 + r.shortName, e);
11195 serviceDoneExecutingLocked(r, true);
11196 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011197 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011199 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011200 TAG, "Removed service that has no process: " + r.shortName);
11201 }
11202 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011203 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 TAG, "Removed service that is not running: " + r.shortName);
11205 }
11206 }
11207
11208 ComponentName startServiceLocked(IApplicationThread caller,
11209 Intent service, String resolvedType,
11210 int callingPid, int callingUid) {
11211 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011212 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011213 + " type=" + resolvedType + " args=" + service.getExtras());
11214
11215 if (caller != null) {
11216 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11217 if (callerApp == null) {
11218 throw new SecurityException(
11219 "Unable to find app for caller " + caller
11220 + " (pid=" + Binder.getCallingPid()
11221 + ") when starting service " + service);
11222 }
11223 }
11224
11225 ServiceLookupResult res =
11226 retrieveServiceLocked(service, resolvedType,
11227 callingPid, callingUid);
11228 if (res == null) {
11229 return null;
11230 }
11231 if (res.record == null) {
11232 return new ComponentName("!", res.permission != null
11233 ? res.permission : "private to package");
11234 }
11235 ServiceRecord r = res.record;
11236 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011237 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011238 + r.shortName);
11239 }
11240 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011241 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011242 r.lastStartId++;
11243 if (r.lastStartId < 1) {
11244 r.lastStartId = 1;
11245 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011246 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011247 r.lastActivity = SystemClock.uptimeMillis();
11248 synchronized (r.stats.getBatteryStats()) {
11249 r.stats.startRunningLocked();
11250 }
11251 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11252 return new ComponentName("!", "Service process is bad");
11253 }
11254 return r.name;
11255 }
11256 }
11257
11258 public ComponentName startService(IApplicationThread caller, Intent service,
11259 String resolvedType) {
11260 // Refuse possible leaked file descriptors
11261 if (service != null && service.hasFileDescriptors() == true) {
11262 throw new IllegalArgumentException("File descriptors passed in Intent");
11263 }
11264
11265 synchronized(this) {
11266 final int callingPid = Binder.getCallingPid();
11267 final int callingUid = Binder.getCallingUid();
11268 final long origId = Binder.clearCallingIdentity();
11269 ComponentName res = startServiceLocked(caller, service,
11270 resolvedType, callingPid, callingUid);
11271 Binder.restoreCallingIdentity(origId);
11272 return res;
11273 }
11274 }
11275
11276 ComponentName startServiceInPackage(int uid,
11277 Intent service, String resolvedType) {
11278 synchronized(this) {
11279 final long origId = Binder.clearCallingIdentity();
11280 ComponentName res = startServiceLocked(null, service,
11281 resolvedType, -1, uid);
11282 Binder.restoreCallingIdentity(origId);
11283 return res;
11284 }
11285 }
11286
11287 public int stopService(IApplicationThread caller, Intent service,
11288 String resolvedType) {
11289 // Refuse possible leaked file descriptors
11290 if (service != null && service.hasFileDescriptors() == true) {
11291 throw new IllegalArgumentException("File descriptors passed in Intent");
11292 }
11293
11294 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011295 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011296 + " type=" + resolvedType);
11297
11298 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11299 if (caller != null && callerApp == null) {
11300 throw new SecurityException(
11301 "Unable to find app for caller " + caller
11302 + " (pid=" + Binder.getCallingPid()
11303 + ") when stopping service " + service);
11304 }
11305
11306 // If this service is active, make sure it is stopped.
11307 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11308 if (r != null) {
11309 if (r.record != null) {
11310 synchronized (r.record.stats.getBatteryStats()) {
11311 r.record.stats.stopRunningLocked();
11312 }
11313 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011314 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011315 final long origId = Binder.clearCallingIdentity();
11316 bringDownServiceLocked(r.record, false);
11317 Binder.restoreCallingIdentity(origId);
11318 return 1;
11319 }
11320 return -1;
11321 }
11322 }
11323
11324 return 0;
11325 }
11326
11327 public IBinder peekService(Intent service, String resolvedType) {
11328 // Refuse possible leaked file descriptors
11329 if (service != null && service.hasFileDescriptors() == true) {
11330 throw new IllegalArgumentException("File descriptors passed in Intent");
11331 }
11332
11333 IBinder ret = null;
11334
11335 synchronized(this) {
11336 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11337
11338 if (r != null) {
11339 // r.record is null if findServiceLocked() failed the caller permission check
11340 if (r.record == null) {
11341 throw new SecurityException(
11342 "Permission Denial: Accessing service " + r.record.name
11343 + " from pid=" + Binder.getCallingPid()
11344 + ", uid=" + Binder.getCallingUid()
11345 + " requires " + r.permission);
11346 }
11347 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11348 if (ib != null) {
11349 ret = ib.binder;
11350 }
11351 }
11352 }
11353
11354 return ret;
11355 }
11356
11357 public boolean stopServiceToken(ComponentName className, IBinder token,
11358 int startId) {
11359 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011360 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011361 + " " + token + " startId=" + startId);
11362 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011363 if (r != null) {
11364 if (startId >= 0) {
11365 // Asked to only stop if done with all work. Note that
11366 // to avoid leaks, we will take this as dropping all
11367 // start items up to and including this one.
11368 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11369 if (si != null) {
11370 while (r.deliveredStarts.size() > 0) {
11371 if (r.deliveredStarts.remove(0) == si) {
11372 break;
11373 }
11374 }
11375 }
11376
11377 if (r.lastStartId != startId) {
11378 return false;
11379 }
11380
11381 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011382 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011383 + " is last, but have " + r.deliveredStarts.size()
11384 + " remaining args");
11385 }
11386 }
11387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011388 synchronized (r.stats.getBatteryStats()) {
11389 r.stats.stopRunningLocked();
11390 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011391 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011392 }
11393 final long origId = Binder.clearCallingIdentity();
11394 bringDownServiceLocked(r, false);
11395 Binder.restoreCallingIdentity(origId);
11396 return true;
11397 }
11398 }
11399 return false;
11400 }
11401
11402 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011403 int id, Notification notification, boolean removeNotification) {
11404 final long origId = Binder.clearCallingIdentity();
11405 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011406 synchronized(this) {
11407 ServiceRecord r = findServiceLocked(className, token);
11408 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011409 if (id != 0) {
11410 if (notification == null) {
11411 throw new IllegalArgumentException("null notification");
11412 }
11413 if (r.foregroundId != id) {
11414 r.cancelNotification();
11415 r.foregroundId = id;
11416 }
11417 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11418 r.foregroundNoti = notification;
11419 r.isForeground = true;
11420 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011421 if (r.app != null) {
11422 updateServiceForegroundLocked(r.app, true);
11423 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011424 } else {
11425 if (r.isForeground) {
11426 r.isForeground = false;
11427 if (r.app != null) {
11428 updateServiceForegroundLocked(r.app, true);
11429 }
11430 }
11431 if (removeNotification) {
11432 r.cancelNotification();
11433 r.foregroundId = 0;
11434 r.foregroundNoti = null;
11435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 }
11437 }
11438 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011439 } finally {
11440 Binder.restoreCallingIdentity(origId);
11441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011442 }
11443
11444 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11445 boolean anyForeground = false;
11446 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11447 if (sr.isForeground) {
11448 anyForeground = true;
11449 break;
11450 }
11451 }
11452 if (anyForeground != proc.foregroundServices) {
11453 proc.foregroundServices = anyForeground;
11454 if (oomAdj) {
11455 updateOomAdjLocked();
11456 }
11457 }
11458 }
11459
11460 public int bindService(IApplicationThread caller, IBinder token,
11461 Intent service, String resolvedType,
11462 IServiceConnection connection, int flags) {
11463 // Refuse possible leaked file descriptors
11464 if (service != null && service.hasFileDescriptors() == true) {
11465 throw new IllegalArgumentException("File descriptors passed in Intent");
11466 }
11467
11468 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011469 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 + " type=" + resolvedType + " conn=" + connection.asBinder()
11471 + " flags=0x" + Integer.toHexString(flags));
11472 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11473 if (callerApp == null) {
11474 throw new SecurityException(
11475 "Unable to find app for caller " + caller
11476 + " (pid=" + Binder.getCallingPid()
11477 + ") when binding service " + service);
11478 }
11479
11480 HistoryRecord activity = null;
11481 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011482 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011483 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011484 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 return 0;
11486 }
11487 activity = (HistoryRecord)mHistory.get(aindex);
11488 }
11489
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011490 int clientLabel = 0;
11491 PendingIntent clientIntent = null;
11492
11493 if (callerApp.info.uid == Process.SYSTEM_UID) {
11494 // Hacky kind of thing -- allow system stuff to tell us
11495 // what they are, so we can report this elsewhere for
11496 // others to know why certain services are running.
11497 try {
11498 clientIntent = (PendingIntent)service.getParcelableExtra(
11499 Intent.EXTRA_CLIENT_INTENT);
11500 } catch (RuntimeException e) {
11501 }
11502 if (clientIntent != null) {
11503 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11504 if (clientLabel != 0) {
11505 // There are no useful extras in the intent, trash them.
11506 // System code calling with this stuff just needs to know
11507 // this will happen.
11508 service = service.cloneFilter();
11509 }
11510 }
11511 }
11512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 ServiceLookupResult res =
11514 retrieveServiceLocked(service, resolvedType,
11515 Binder.getCallingPid(), Binder.getCallingUid());
11516 if (res == null) {
11517 return 0;
11518 }
11519 if (res.record == null) {
11520 return -1;
11521 }
11522 ServiceRecord s = res.record;
11523
11524 final long origId = Binder.clearCallingIdentity();
11525
11526 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011527 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011528 + s.shortName);
11529 }
11530
11531 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11532 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011533 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534
11535 IBinder binder = connection.asBinder();
11536 s.connections.put(binder, c);
11537 b.connections.add(c);
11538 if (activity != null) {
11539 if (activity.connections == null) {
11540 activity.connections = new HashSet<ConnectionRecord>();
11541 }
11542 activity.connections.add(c);
11543 }
11544 b.client.connections.add(c);
11545 mServiceConnections.put(binder, c);
11546
11547 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11548 s.lastActivity = SystemClock.uptimeMillis();
11549 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11550 return 0;
11551 }
11552 }
11553
11554 if (s.app != null) {
11555 // This could have made the service more important.
11556 updateOomAdjLocked(s.app);
11557 }
11558
Joe Onorato8a9b2202010-02-26 18:56:32 -080011559 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011560 + ": received=" + b.intent.received
11561 + " apps=" + b.intent.apps.size()
11562 + " doRebind=" + b.intent.doRebind);
11563
11564 if (s.app != null && b.intent.received) {
11565 // Service is already running, so we can immediately
11566 // publish the connection.
11567 try {
11568 c.conn.connected(s.name, b.intent.binder);
11569 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011570 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571 + " to connection " + c.conn.asBinder()
11572 + " (in " + c.binding.client.processName + ")", e);
11573 }
11574
11575 // If this is the first app connected back to this binding,
11576 // and the service had previously asked to be told when
11577 // rebound, then do so.
11578 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11579 requestServiceBindingLocked(s, b.intent, true);
11580 }
11581 } else if (!b.intent.requested) {
11582 requestServiceBindingLocked(s, b.intent, false);
11583 }
11584
11585 Binder.restoreCallingIdentity(origId);
11586 }
11587
11588 return 1;
11589 }
11590
11591 private void removeConnectionLocked(
11592 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11593 IBinder binder = c.conn.asBinder();
11594 AppBindRecord b = c.binding;
11595 ServiceRecord s = b.service;
11596 s.connections.remove(binder);
11597 b.connections.remove(c);
11598 if (c.activity != null && c.activity != skipAct) {
11599 if (c.activity.connections != null) {
11600 c.activity.connections.remove(c);
11601 }
11602 }
11603 if (b.client != skipApp) {
11604 b.client.connections.remove(c);
11605 }
11606 mServiceConnections.remove(binder);
11607
11608 if (b.connections.size() == 0) {
11609 b.intent.apps.remove(b.client);
11610 }
11611
Joe Onorato8a9b2202010-02-26 18:56:32 -080011612 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 + ": shouldUnbind=" + b.intent.hasBound);
11614 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11615 && b.intent.hasBound) {
11616 try {
11617 bumpServiceExecutingLocked(s);
11618 updateOomAdjLocked(s.app);
11619 b.intent.hasBound = false;
11620 // Assume the client doesn't want to know about a rebind;
11621 // we will deal with that later if it asks for one.
11622 b.intent.doRebind = false;
11623 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11624 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011625 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011626 serviceDoneExecutingLocked(s, true);
11627 }
11628 }
11629
11630 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11631 bringDownServiceLocked(s, false);
11632 }
11633 }
11634
11635 public boolean unbindService(IServiceConnection connection) {
11636 synchronized (this) {
11637 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011638 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011639 ConnectionRecord r = mServiceConnections.get(binder);
11640 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011641 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011642 + connection.asBinder());
11643 return false;
11644 }
11645
11646 final long origId = Binder.clearCallingIdentity();
11647
11648 removeConnectionLocked(r, null, null);
11649
11650 if (r.binding.service.app != null) {
11651 // This could have made the service less important.
11652 updateOomAdjLocked(r.binding.service.app);
11653 }
11654
11655 Binder.restoreCallingIdentity(origId);
11656 }
11657
11658 return true;
11659 }
11660
11661 public void publishService(IBinder token, Intent intent, IBinder service) {
11662 // Refuse possible leaked file descriptors
11663 if (intent != null && intent.hasFileDescriptors() == true) {
11664 throw new IllegalArgumentException("File descriptors passed in Intent");
11665 }
11666
11667 synchronized(this) {
11668 if (!(token instanceof ServiceRecord)) {
11669 throw new IllegalArgumentException("Invalid service token");
11670 }
11671 ServiceRecord r = (ServiceRecord)token;
11672
11673 final long origId = Binder.clearCallingIdentity();
11674
Joe Onorato8a9b2202010-02-26 18:56:32 -080011675 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676 + " " + intent + ": " + service);
11677 if (r != null) {
11678 Intent.FilterComparison filter
11679 = new Intent.FilterComparison(intent);
11680 IntentBindRecord b = r.bindings.get(filter);
11681 if (b != null && !b.received) {
11682 b.binder = service;
11683 b.requested = true;
11684 b.received = true;
11685 if (r.connections.size() > 0) {
11686 Iterator<ConnectionRecord> it
11687 = r.connections.values().iterator();
11688 while (it.hasNext()) {
11689 ConnectionRecord c = it.next();
11690 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011691 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011692 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011693 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011694 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011695 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011696 TAG, "Published intent: " + intent);
11697 continue;
11698 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011699 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011700 try {
11701 c.conn.connected(r.name, service);
11702 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011703 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011704 " to connection " + c.conn.asBinder() +
11705 " (in " + c.binding.client.processName + ")", e);
11706 }
11707 }
11708 }
11709 }
11710
11711 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11712
11713 Binder.restoreCallingIdentity(origId);
11714 }
11715 }
11716 }
11717
11718 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11719 // Refuse possible leaked file descriptors
11720 if (intent != null && intent.hasFileDescriptors() == true) {
11721 throw new IllegalArgumentException("File descriptors passed in Intent");
11722 }
11723
11724 synchronized(this) {
11725 if (!(token instanceof ServiceRecord)) {
11726 throw new IllegalArgumentException("Invalid service token");
11727 }
11728 ServiceRecord r = (ServiceRecord)token;
11729
11730 final long origId = Binder.clearCallingIdentity();
11731
11732 if (r != null) {
11733 Intent.FilterComparison filter
11734 = new Intent.FilterComparison(intent);
11735 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011736 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011737 + " at " + b + ": apps="
11738 + (b != null ? b.apps.size() : 0));
11739 if (b != null) {
11740 if (b.apps.size() > 0) {
11741 // Applications have already bound since the last
11742 // unbind, so just rebind right here.
11743 requestServiceBindingLocked(r, b, true);
11744 } else {
11745 // Note to tell the service the next time there is
11746 // a new client.
11747 b.doRebind = true;
11748 }
11749 }
11750
11751 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11752
11753 Binder.restoreCallingIdentity(origId);
11754 }
11755 }
11756 }
11757
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011758 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011759 synchronized(this) {
11760 if (!(token instanceof ServiceRecord)) {
11761 throw new IllegalArgumentException("Invalid service token");
11762 }
11763 ServiceRecord r = (ServiceRecord)token;
11764 boolean inStopping = mStoppingServices.contains(token);
11765 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011766 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011767 + ": nesting=" + r.executeNesting
11768 + ", inStopping=" + inStopping);
11769 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011770 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 + " with incorrect token: given " + token
11772 + ", expected " + r);
11773 return;
11774 }
11775
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011776 if (type == 1) {
11777 // This is a call from a service start... take care of
11778 // book-keeping.
11779 r.callStart = true;
11780 switch (res) {
11781 case Service.START_STICKY_COMPATIBILITY:
11782 case Service.START_STICKY: {
11783 // We are done with the associated start arguments.
11784 r.findDeliveredStart(startId, true);
11785 // Don't stop if killed.
11786 r.stopIfKilled = false;
11787 break;
11788 }
11789 case Service.START_NOT_STICKY: {
11790 // We are done with the associated start arguments.
11791 r.findDeliveredStart(startId, true);
11792 if (r.lastStartId == startId) {
11793 // There is no more work, and this service
11794 // doesn't want to hang around if killed.
11795 r.stopIfKilled = true;
11796 }
11797 break;
11798 }
11799 case Service.START_REDELIVER_INTENT: {
11800 // We'll keep this item until they explicitly
11801 // call stop for it, but keep track of the fact
11802 // that it was delivered.
11803 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11804 if (si != null) {
11805 si.deliveryCount = 0;
11806 si.doneExecutingCount++;
11807 // Don't stop if killed.
11808 r.stopIfKilled = true;
11809 }
11810 break;
11811 }
11812 default:
11813 throw new IllegalArgumentException(
11814 "Unknown service start result: " + res);
11815 }
11816 if (res == Service.START_STICKY_COMPATIBILITY) {
11817 r.callStart = false;
11818 }
11819 }
11820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011821 final long origId = Binder.clearCallingIdentity();
11822 serviceDoneExecutingLocked(r, inStopping);
11823 Binder.restoreCallingIdentity(origId);
11824 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011825 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011826 + " with token " + token);
11827 }
11828 }
11829 }
11830
11831 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11832 r.executeNesting--;
11833 if (r.executeNesting <= 0 && r.app != null) {
11834 r.app.executingServices.remove(r);
11835 if (r.app.executingServices.size() == 0) {
11836 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11837 }
11838 if (inStopping) {
11839 mStoppingServices.remove(r);
11840 }
11841 updateOomAdjLocked(r.app);
11842 }
11843 }
11844
11845 void serviceTimeout(ProcessRecord proc) {
11846 synchronized(this) {
11847 if (proc.executingServices.size() == 0 || proc.thread == null) {
11848 return;
11849 }
11850 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11851 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11852 ServiceRecord timeout = null;
11853 long nextTime = 0;
11854 while (it.hasNext()) {
11855 ServiceRecord sr = it.next();
11856 if (sr.executingStart < maxTime) {
11857 timeout = sr;
11858 break;
11859 }
11860 if (sr.executingStart > nextTime) {
11861 nextTime = sr.executingStart;
11862 }
11863 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011864 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011865 Slog.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011866 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011867 } else {
11868 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11869 msg.obj = proc;
11870 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11871 }
11872 }
11873 }
11874
11875 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011876 // BACKUP AND RESTORE
11877 // =========================================================
11878
11879 // Cause the target app to be launched if necessary and its backup agent
11880 // instantiated. The backup agent will invoke backupAgentCreated() on the
11881 // activity manager to announce its creation.
11882 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011883 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011884 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11885
11886 synchronized(this) {
11887 // !!! TODO: currently no check here that we're already bound
11888 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11889 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11890 synchronized (stats) {
11891 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11892 }
11893
11894 BackupRecord r = new BackupRecord(ss, app, backupMode);
11895 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11896 // startProcessLocked() returns existing proc's record if it's already running
11897 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011898 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011899 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011900 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011901 return false;
11902 }
11903
11904 r.app = proc;
11905 mBackupTarget = r;
11906 mBackupAppName = app.packageName;
11907
Christopher Tate6fa95972009-06-05 18:43:55 -070011908 // Try not to kill the process during backup
11909 updateOomAdjLocked(proc);
11910
Christopher Tate181fafa2009-05-14 11:12:14 -070011911 // If the process is already attached, schedule the creation of the backup agent now.
11912 // If it is not yet live, this will be done when it attaches to the framework.
11913 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011914 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011915 try {
11916 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11917 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011918 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011919 }
11920 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011921 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011922 }
11923 // Invariants: at this point, the target app process exists and the application
11924 // is either already running or in the process of coming up. mBackupTarget and
11925 // mBackupAppName describe the app, so that when it binds back to the AM we
11926 // know that it's scheduled for a backup-agent operation.
11927 }
11928
11929 return true;
11930 }
11931
11932 // A backup agent has just come up
11933 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011934 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011935 + " = " + agent);
11936
11937 synchronized(this) {
11938 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011939 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011940 return;
11941 }
11942
Christopher Tate043dadc2009-06-02 16:11:00 -070011943 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011944 try {
11945 IBackupManager bm = IBackupManager.Stub.asInterface(
11946 ServiceManager.getService(Context.BACKUP_SERVICE));
11947 bm.agentConnected(agentPackageName, agent);
11948 } catch (RemoteException e) {
11949 // can't happen; the backup manager service is local
11950 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011951 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070011952 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011953 } finally {
11954 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011955 }
11956 }
11957 }
11958
11959 // done with this agent
11960 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011961 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011962 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011963 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011964 return;
11965 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011966
11967 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011968 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011969 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011970 return;
11971 }
11972
Christopher Tate181fafa2009-05-14 11:12:14 -070011973 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011974 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011975 return;
11976 }
11977
Christopher Tate6fa95972009-06-05 18:43:55 -070011978 ProcessRecord proc = mBackupTarget.app;
11979 mBackupTarget = null;
11980 mBackupAppName = null;
11981
11982 // Not backing this app up any more; reset its OOM adjustment
11983 updateOomAdjLocked(proc);
11984
Christopher Tatec7b31e32009-06-10 15:49:30 -070011985 // If the app crashed during backup, 'thread' will be null here
11986 if (proc.thread != null) {
11987 try {
11988 proc.thread.scheduleDestroyBackupAgent(appInfo);
11989 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011990 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070011991 e.printStackTrace();
11992 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011993 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011994 }
11995 }
11996 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011997 // BROADCASTS
11998 // =========================================================
11999
Josh Bartel7f208742010-02-25 11:01:44 -060012000 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012001 List cur) {
12002 final ContentResolver resolver = mContext.getContentResolver();
12003 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12004 if (list == null) {
12005 return cur;
12006 }
12007 int N = list.size();
12008 for (int i=0; i<N; i++) {
12009 Intent intent = list.get(i);
12010 if (filter.match(resolver, intent, true, TAG) >= 0) {
12011 if (cur == null) {
12012 cur = new ArrayList<Intent>();
12013 }
12014 cur.add(intent);
12015 }
12016 }
12017 return cur;
12018 }
12019
12020 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012021 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012022 + mBroadcastsScheduled);
12023
12024 if (mBroadcastsScheduled) {
12025 return;
12026 }
12027 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12028 mBroadcastsScheduled = true;
12029 }
12030
12031 public Intent registerReceiver(IApplicationThread caller,
12032 IIntentReceiver receiver, IntentFilter filter, String permission) {
12033 synchronized(this) {
12034 ProcessRecord callerApp = null;
12035 if (caller != null) {
12036 callerApp = getRecordForAppLocked(caller);
12037 if (callerApp == null) {
12038 throw new SecurityException(
12039 "Unable to find app for caller " + caller
12040 + " (pid=" + Binder.getCallingPid()
12041 + ") when registering receiver " + receiver);
12042 }
12043 }
12044
12045 List allSticky = null;
12046
12047 // Look for any matching sticky broadcasts...
12048 Iterator actions = filter.actionsIterator();
12049 if (actions != null) {
12050 while (actions.hasNext()) {
12051 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012052 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012053 }
12054 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012055 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012056 }
12057
12058 // The first sticky in the list is returned directly back to
12059 // the client.
12060 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12061
Joe Onorato8a9b2202010-02-26 18:56:32 -080012062 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012063 + ": " + sticky);
12064
12065 if (receiver == null) {
12066 return sticky;
12067 }
12068
12069 ReceiverList rl
12070 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12071 if (rl == null) {
12072 rl = new ReceiverList(this, callerApp,
12073 Binder.getCallingPid(),
12074 Binder.getCallingUid(), receiver);
12075 if (rl.app != null) {
12076 rl.app.receivers.add(rl);
12077 } else {
12078 try {
12079 receiver.asBinder().linkToDeath(rl, 0);
12080 } catch (RemoteException e) {
12081 return sticky;
12082 }
12083 rl.linkedToDeath = true;
12084 }
12085 mRegisteredReceivers.put(receiver.asBinder(), rl);
12086 }
12087 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12088 rl.add(bf);
12089 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012090 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012091 }
12092 mReceiverResolver.addFilter(bf);
12093
12094 // Enqueue broadcasts for all existing stickies that match
12095 // this filter.
12096 if (allSticky != null) {
12097 ArrayList receivers = new ArrayList();
12098 receivers.add(bf);
12099
12100 int N = allSticky.size();
12101 for (int i=0; i<N; i++) {
12102 Intent intent = (Intent)allSticky.get(i);
12103 BroadcastRecord r = new BroadcastRecord(intent, null,
12104 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012105 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012106 if (mParallelBroadcasts.size() == 0) {
12107 scheduleBroadcastsLocked();
12108 }
12109 mParallelBroadcasts.add(r);
12110 }
12111 }
12112
12113 return sticky;
12114 }
12115 }
12116
12117 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012118 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012119
12120 boolean doNext = false;
12121
12122 synchronized(this) {
12123 ReceiverList rl
12124 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12125 if (rl != null) {
12126 if (rl.curBroadcast != null) {
12127 BroadcastRecord r = rl.curBroadcast;
12128 doNext = finishReceiverLocked(
12129 receiver.asBinder(), r.resultCode, r.resultData,
12130 r.resultExtras, r.resultAbort, true);
12131 }
12132
12133 if (rl.app != null) {
12134 rl.app.receivers.remove(rl);
12135 }
12136 removeReceiverLocked(rl);
12137 if (rl.linkedToDeath) {
12138 rl.linkedToDeath = false;
12139 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12140 }
12141 }
12142 }
12143
12144 if (!doNext) {
12145 return;
12146 }
12147
12148 final long origId = Binder.clearCallingIdentity();
12149 processNextBroadcast(false);
12150 trimApplications();
12151 Binder.restoreCallingIdentity(origId);
12152 }
12153
12154 void removeReceiverLocked(ReceiverList rl) {
12155 mRegisteredReceivers.remove(rl.receiver.asBinder());
12156 int N = rl.size();
12157 for (int i=0; i<N; i++) {
12158 mReceiverResolver.removeFilter(rl.get(i));
12159 }
12160 }
12161
12162 private final int broadcastIntentLocked(ProcessRecord callerApp,
12163 String callerPackage, Intent intent, String resolvedType,
12164 IIntentReceiver resultTo, int resultCode, String resultData,
12165 Bundle map, String requiredPermission,
12166 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12167 intent = new Intent(intent);
12168
Joe Onorato8a9b2202010-02-26 18:56:32 -080012169 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012170 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12171 + " ordered=" + ordered);
12172 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012173 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012174 }
12175
12176 // Handle special intents: if this broadcast is from the package
12177 // manager about a package being removed, we need to remove all of
12178 // its activities from the history stack.
12179 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12180 intent.getAction());
12181 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12182 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012183 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012184 || uidRemoved) {
12185 if (checkComponentPermission(
12186 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12187 callingPid, callingUid, -1)
12188 == PackageManager.PERMISSION_GRANTED) {
12189 if (uidRemoved) {
12190 final Bundle intentExtras = intent.getExtras();
12191 final int uid = intentExtras != null
12192 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12193 if (uid >= 0) {
12194 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12195 synchronized (bs) {
12196 bs.removeUidStatsLocked(uid);
12197 }
12198 }
12199 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012200 // If resources are unvailble just force stop all
12201 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012202 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012203 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12204 if (list != null && (list.length > 0)) {
12205 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012206 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012207 }
12208 }
12209 } else {
12210 Uri data = intent.getData();
12211 String ssp;
12212 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12213 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12214 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012215 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012217 }
12218 }
12219 }
12220 } else {
12221 String msg = "Permission Denial: " + intent.getAction()
12222 + " broadcast from " + callerPackage + " (pid=" + callingPid
12223 + ", uid=" + callingUid + ")"
12224 + " requires "
12225 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012226 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012227 throw new SecurityException(msg);
12228 }
12229 }
12230
12231 /*
12232 * If this is the time zone changed action, queue up a message that will reset the timezone
12233 * of all currently running processes. This message will get queued up before the broadcast
12234 * happens.
12235 */
12236 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12237 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12238 }
12239
Dianne Hackborn854060af2009-07-09 18:14:31 -070012240 /*
12241 * Prevent non-system code (defined here to be non-persistent
12242 * processes) from sending protected broadcasts.
12243 */
12244 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12245 || callingUid == Process.SHELL_UID || callingUid == 0) {
12246 // Always okay.
12247 } else if (callerApp == null || !callerApp.persistent) {
12248 try {
12249 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12250 intent.getAction())) {
12251 String msg = "Permission Denial: not allowed to send broadcast "
12252 + intent.getAction() + " from pid="
12253 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012254 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012255 throw new SecurityException(msg);
12256 }
12257 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012258 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012259 return BROADCAST_SUCCESS;
12260 }
12261 }
12262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012263 // Add to the sticky list if requested.
12264 if (sticky) {
12265 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12266 callingPid, callingUid)
12267 != PackageManager.PERMISSION_GRANTED) {
12268 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12269 + callingPid + ", uid=" + callingUid
12270 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012271 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012272 throw new SecurityException(msg);
12273 }
12274 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012275 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012276 + " and enforce permission " + requiredPermission);
12277 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12278 }
12279 if (intent.getComponent() != null) {
12280 throw new SecurityException(
12281 "Sticky broadcasts can't target a specific component");
12282 }
12283 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12284 if (list == null) {
12285 list = new ArrayList<Intent>();
12286 mStickyBroadcasts.put(intent.getAction(), list);
12287 }
12288 int N = list.size();
12289 int i;
12290 for (i=0; i<N; i++) {
12291 if (intent.filterEquals(list.get(i))) {
12292 // This sticky already exists, replace it.
12293 list.set(i, new Intent(intent));
12294 break;
12295 }
12296 }
12297 if (i >= N) {
12298 list.add(new Intent(intent));
12299 }
12300 }
12301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012302 // Figure out who all will receive this broadcast.
12303 List receivers = null;
12304 List<BroadcastFilter> registeredReceivers = null;
12305 try {
12306 if (intent.getComponent() != null) {
12307 // Broadcast is going to one specific receiver class...
12308 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012309 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012310 if (ai != null) {
12311 receivers = new ArrayList();
12312 ResolveInfo ri = new ResolveInfo();
12313 ri.activityInfo = ai;
12314 receivers.add(ri);
12315 }
12316 } else {
12317 // Need to resolve the intent to interested receivers...
12318 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12319 == 0) {
12320 receivers =
12321 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012322 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012323 }
Mihai Preda074edef2009-05-18 17:13:31 +020012324 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012325 }
12326 } catch (RemoteException ex) {
12327 // pm is in same process, this will never happen.
12328 }
12329
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012330 final boolean replacePending =
12331 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12332
Joe Onorato8a9b2202010-02-26 18:56:32 -080012333 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012334 + " replacePending=" + replacePending);
12335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012336 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12337 if (!ordered && NR > 0) {
12338 // If we are not serializing this broadcast, then send the
12339 // registered receivers separately so they don't wait for the
12340 // components to be launched.
12341 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12342 callerPackage, callingPid, callingUid, requiredPermission,
12343 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012344 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012345 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012346 TAG, "Enqueueing parallel broadcast " + r
12347 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012348 boolean replaced = false;
12349 if (replacePending) {
12350 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12351 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012352 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012353 "***** DROPPING PARALLEL: " + intent);
12354 mParallelBroadcasts.set(i, r);
12355 replaced = true;
12356 break;
12357 }
12358 }
12359 }
12360 if (!replaced) {
12361 mParallelBroadcasts.add(r);
12362 scheduleBroadcastsLocked();
12363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012364 registeredReceivers = null;
12365 NR = 0;
12366 }
12367
12368 // Merge into one list.
12369 int ir = 0;
12370 if (receivers != null) {
12371 // A special case for PACKAGE_ADDED: do not allow the package
12372 // being added to see this broadcast. This prevents them from
12373 // using this as a back door to get run as soon as they are
12374 // installed. Maybe in the future we want to have a special install
12375 // broadcast or such for apps, but we'd like to deliberately make
12376 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012377 String skipPackages[] = null;
12378 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12379 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12380 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12381 Uri data = intent.getData();
12382 if (data != null) {
12383 String pkgName = data.getSchemeSpecificPart();
12384 if (pkgName != null) {
12385 skipPackages = new String[] { pkgName };
12386 }
12387 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012388 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012389 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012390 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012391 if (skipPackages != null && (skipPackages.length > 0)) {
12392 for (String skipPackage : skipPackages) {
12393 if (skipPackage != null) {
12394 int NT = receivers.size();
12395 for (int it=0; it<NT; it++) {
12396 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12397 if (curt.activityInfo.packageName.equals(skipPackage)) {
12398 receivers.remove(it);
12399 it--;
12400 NT--;
12401 }
12402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 }
12404 }
12405 }
12406
12407 int NT = receivers != null ? receivers.size() : 0;
12408 int it = 0;
12409 ResolveInfo curt = null;
12410 BroadcastFilter curr = null;
12411 while (it < NT && ir < NR) {
12412 if (curt == null) {
12413 curt = (ResolveInfo)receivers.get(it);
12414 }
12415 if (curr == null) {
12416 curr = registeredReceivers.get(ir);
12417 }
12418 if (curr.getPriority() >= curt.priority) {
12419 // Insert this broadcast record into the final list.
12420 receivers.add(it, curr);
12421 ir++;
12422 curr = null;
12423 it++;
12424 NT++;
12425 } else {
12426 // Skip to the next ResolveInfo in the final list.
12427 it++;
12428 curt = null;
12429 }
12430 }
12431 }
12432 while (ir < NR) {
12433 if (receivers == null) {
12434 receivers = new ArrayList();
12435 }
12436 receivers.add(registeredReceivers.get(ir));
12437 ir++;
12438 }
12439
12440 if ((receivers != null && receivers.size() > 0)
12441 || resultTo != null) {
12442 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12443 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012444 receivers, resultTo, resultCode, resultData, map, ordered,
12445 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012446 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012447 TAG, "Enqueueing ordered broadcast " + r
12448 + ": prev had " + mOrderedBroadcasts.size());
12449 if (DEBUG_BROADCAST) {
12450 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012451 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012452 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012453 boolean replaced = false;
12454 if (replacePending) {
12455 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12456 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012457 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012458 "***** DROPPING ORDERED: " + intent);
12459 mOrderedBroadcasts.set(i, r);
12460 replaced = true;
12461 break;
12462 }
12463 }
12464 }
12465 if (!replaced) {
12466 mOrderedBroadcasts.add(r);
12467 scheduleBroadcastsLocked();
12468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012469 }
12470
12471 return BROADCAST_SUCCESS;
12472 }
12473
12474 public final int broadcastIntent(IApplicationThread caller,
12475 Intent intent, String resolvedType, IIntentReceiver resultTo,
12476 int resultCode, String resultData, Bundle map,
12477 String requiredPermission, boolean serialized, boolean sticky) {
12478 // Refuse possible leaked file descriptors
12479 if (intent != null && intent.hasFileDescriptors() == true) {
12480 throw new IllegalArgumentException("File descriptors passed in Intent");
12481 }
12482
12483 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012484 int flags = intent.getFlags();
12485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012486 if (!mSystemReady) {
12487 // if the caller really truly claims to know what they're doing, go
12488 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012489 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12490 intent = new Intent(intent);
12491 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12492 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012493 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012494 + " before boot completion");
12495 throw new IllegalStateException("Cannot broadcast before boot completed");
12496 }
12497 }
12498
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012499 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12500 throw new IllegalArgumentException(
12501 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12502 }
12503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012504 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12505 final int callingPid = Binder.getCallingPid();
12506 final int callingUid = Binder.getCallingUid();
12507 final long origId = Binder.clearCallingIdentity();
12508 int res = broadcastIntentLocked(callerApp,
12509 callerApp != null ? callerApp.info.packageName : null,
12510 intent, resolvedType, resultTo,
12511 resultCode, resultData, map, requiredPermission, serialized,
12512 sticky, callingPid, callingUid);
12513 Binder.restoreCallingIdentity(origId);
12514 return res;
12515 }
12516 }
12517
12518 int broadcastIntentInPackage(String packageName, int uid,
12519 Intent intent, String resolvedType, IIntentReceiver resultTo,
12520 int resultCode, String resultData, Bundle map,
12521 String requiredPermission, boolean serialized, boolean sticky) {
12522 synchronized(this) {
12523 final long origId = Binder.clearCallingIdentity();
12524 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12525 resultTo, resultCode, resultData, map, requiredPermission,
12526 serialized, sticky, -1, uid);
12527 Binder.restoreCallingIdentity(origId);
12528 return res;
12529 }
12530 }
12531
12532 public final void unbroadcastIntent(IApplicationThread caller,
12533 Intent intent) {
12534 // Refuse possible leaked file descriptors
12535 if (intent != null && intent.hasFileDescriptors() == true) {
12536 throw new IllegalArgumentException("File descriptors passed in Intent");
12537 }
12538
12539 synchronized(this) {
12540 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12541 != PackageManager.PERMISSION_GRANTED) {
12542 String msg = "Permission Denial: unbroadcastIntent() from pid="
12543 + Binder.getCallingPid()
12544 + ", uid=" + Binder.getCallingUid()
12545 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012546 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012547 throw new SecurityException(msg);
12548 }
12549 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12550 if (list != null) {
12551 int N = list.size();
12552 int i;
12553 for (i=0; i<N; i++) {
12554 if (intent.filterEquals(list.get(i))) {
12555 list.remove(i);
12556 break;
12557 }
12558 }
12559 }
12560 }
12561 }
12562
12563 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12564 String resultData, Bundle resultExtras, boolean resultAbort,
12565 boolean explicit) {
12566 if (mOrderedBroadcasts.size() == 0) {
12567 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012568 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012569 }
12570 return false;
12571 }
12572 BroadcastRecord r = mOrderedBroadcasts.get(0);
12573 if (r.receiver == null) {
12574 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012575 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012576 }
12577 return false;
12578 }
12579 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012580 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012581 return false;
12582 }
12583 int state = r.state;
12584 r.state = r.IDLE;
12585 if (state == r.IDLE) {
12586 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012587 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012588 }
12589 }
12590 r.receiver = null;
12591 r.intent.setComponent(null);
12592 if (r.curApp != null) {
12593 r.curApp.curReceiver = null;
12594 }
12595 if (r.curFilter != null) {
12596 r.curFilter.receiverList.curBroadcast = null;
12597 }
12598 r.curFilter = null;
12599 r.curApp = null;
12600 r.curComponent = null;
12601 r.curReceiver = null;
12602 mPendingBroadcast = null;
12603
12604 r.resultCode = resultCode;
12605 r.resultData = resultData;
12606 r.resultExtras = resultExtras;
12607 r.resultAbort = resultAbort;
12608
12609 // We will process the next receiver right now if this is finishing
12610 // an app receiver (which is always asynchronous) or after we have
12611 // come back from calling a receiver.
12612 return state == BroadcastRecord.APP_RECEIVE
12613 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12614 }
12615
12616 public void finishReceiver(IBinder who, int resultCode, String resultData,
12617 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012618 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012619
12620 // Refuse possible leaked file descriptors
12621 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12622 throw new IllegalArgumentException("File descriptors passed in Bundle");
12623 }
12624
12625 boolean doNext;
12626
12627 final long origId = Binder.clearCallingIdentity();
12628
12629 synchronized(this) {
12630 doNext = finishReceiverLocked(
12631 who, resultCode, resultData, resultExtras, resultAbort, true);
12632 }
12633
12634 if (doNext) {
12635 processNextBroadcast(false);
12636 }
12637 trimApplications();
12638
12639 Binder.restoreCallingIdentity(origId);
12640 }
12641
12642 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12643 if (r.nextReceiver > 0) {
12644 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12645 if (curReceiver instanceof BroadcastFilter) {
12646 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012647 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012648 System.identityHashCode(r),
12649 r.intent.getAction(),
12650 r.nextReceiver - 1,
12651 System.identityHashCode(bf));
12652 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012653 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654 System.identityHashCode(r),
12655 r.intent.getAction(),
12656 r.nextReceiver - 1,
12657 ((ResolveInfo)curReceiver).toString());
12658 }
12659 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012660 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012661 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012662 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012663 System.identityHashCode(r),
12664 r.intent.getAction(),
12665 r.nextReceiver,
12666 "NONE");
12667 }
12668 }
12669
12670 private final void broadcastTimeout() {
12671 synchronized (this) {
12672 if (mOrderedBroadcasts.size() == 0) {
12673 return;
12674 }
12675 long now = SystemClock.uptimeMillis();
12676 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012677 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012678 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012679 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012680 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012681 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012682 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012683 return;
12684 }
12685
Joe Onorato8a9b2202010-02-26 18:56:32 -080012686 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012687 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012688 r.anrCount++;
12689
12690 // Current receiver has passed its expiration date.
12691 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012692 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012693 return;
12694 }
12695
12696 ProcessRecord app = null;
12697
12698 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012699 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012700 logBroadcastReceiverDiscard(r);
12701 if (curReceiver instanceof BroadcastFilter) {
12702 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12703 if (bf.receiverList.pid != 0
12704 && bf.receiverList.pid != MY_PID) {
12705 synchronized (this.mPidsSelfLocked) {
12706 app = this.mPidsSelfLocked.get(
12707 bf.receiverList.pid);
12708 }
12709 }
12710 } else {
12711 app = r.curApp;
12712 }
12713
12714 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012715 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012716 }
12717
12718 if (mPendingBroadcast == r) {
12719 mPendingBroadcast = null;
12720 }
12721
12722 // Move on to the next receiver.
12723 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12724 r.resultExtras, r.resultAbort, true);
12725 scheduleBroadcastsLocked();
12726 }
12727 }
12728
12729 private final void processCurBroadcastLocked(BroadcastRecord r,
12730 ProcessRecord app) throws RemoteException {
12731 if (app.thread == null) {
12732 throw new RemoteException();
12733 }
12734 r.receiver = app.thread.asBinder();
12735 r.curApp = app;
12736 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012737 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012738
12739 // Tell the application to launch this receiver.
12740 r.intent.setComponent(r.curComponent);
12741
12742 boolean started = false;
12743 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012744 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012745 "Delivering to component " + r.curComponent
12746 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012747 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012748 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12749 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12750 started = true;
12751 } finally {
12752 if (!started) {
12753 r.receiver = null;
12754 r.curApp = null;
12755 app.curReceiver = null;
12756 }
12757 }
12758
12759 }
12760
12761 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012762 Intent intent, int resultCode, String data, Bundle extras,
12763 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012764 if (app != null && app.thread != null) {
12765 // If we have an app thread, do the call through that so it is
12766 // correctly ordered with other one-way calls.
12767 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012768 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012769 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012770 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012771 }
12772 }
12773
12774 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12775 BroadcastFilter filter, boolean ordered) {
12776 boolean skip = false;
12777 if (filter.requiredPermission != null) {
12778 int perm = checkComponentPermission(filter.requiredPermission,
12779 r.callingPid, r.callingUid, -1);
12780 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012781 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012782 + r.intent.toString()
12783 + " from " + r.callerPackage + " (pid="
12784 + r.callingPid + ", uid=" + r.callingUid + ")"
12785 + " requires " + filter.requiredPermission
12786 + " due to registered receiver " + filter);
12787 skip = true;
12788 }
12789 }
12790 if (r.requiredPermission != null) {
12791 int perm = checkComponentPermission(r.requiredPermission,
12792 filter.receiverList.pid, filter.receiverList.uid, -1);
12793 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012794 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012795 + r.intent.toString()
12796 + " to " + filter.receiverList.app
12797 + " (pid=" + filter.receiverList.pid
12798 + ", uid=" + filter.receiverList.uid + ")"
12799 + " requires " + r.requiredPermission
12800 + " due to sender " + r.callerPackage
12801 + " (uid " + r.callingUid + ")");
12802 skip = true;
12803 }
12804 }
12805
12806 if (!skip) {
12807 // If this is not being sent as an ordered broadcast, then we
12808 // don't want to touch the fields that keep track of the current
12809 // state of ordered broadcasts.
12810 if (ordered) {
12811 r.receiver = filter.receiverList.receiver.asBinder();
12812 r.curFilter = filter;
12813 filter.receiverList.curBroadcast = r;
12814 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012815 if (filter.receiverList.app != null) {
12816 // Bump hosting application to no longer be in background
12817 // scheduling class. Note that we can't do that if there
12818 // isn't an app... but we can only be in that case for
12819 // things that directly call the IActivityManager API, which
12820 // are already core system stuff so don't matter for this.
12821 r.curApp = filter.receiverList.app;
12822 filter.receiverList.app.curReceiver = r;
12823 updateOomAdjLocked();
12824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012825 }
12826 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012827 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012828 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012829 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012830 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012831 }
12832 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12833 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012834 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012835 if (ordered) {
12836 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12837 }
12838 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012839 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012840 if (ordered) {
12841 r.receiver = null;
12842 r.curFilter = null;
12843 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012844 if (filter.receiverList.app != null) {
12845 filter.receiverList.app.curReceiver = null;
12846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012847 }
12848 }
12849 }
12850 }
12851
Dianne Hackborn12527f92009-11-11 17:39:50 -080012852 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12853 if (r.callingUid < 0) {
12854 // This was from a registerReceiver() call; ignore it.
12855 return;
12856 }
12857 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12858 MAX_BROADCAST_HISTORY-1);
12859 r.finishTime = SystemClock.uptimeMillis();
12860 mBroadcastHistory[0] = r;
12861 }
12862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012863 private final void processNextBroadcast(boolean fromMsg) {
12864 synchronized(this) {
12865 BroadcastRecord r;
12866
Joe Onorato8a9b2202010-02-26 18:56:32 -080012867 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012868 + mParallelBroadcasts.size() + " broadcasts, "
12869 + mOrderedBroadcasts.size() + " serialized broadcasts");
12870
12871 updateCpuStats();
12872
12873 if (fromMsg) {
12874 mBroadcastsScheduled = false;
12875 }
12876
12877 // First, deliver any non-serialized broadcasts right away.
12878 while (mParallelBroadcasts.size() > 0) {
12879 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012880 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012881 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012882 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012883 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012884 for (int i=0; i<N; i++) {
12885 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012886 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012887 "Delivering non-serialized to registered "
12888 + target + ": " + r);
12889 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12890 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012891 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012892 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012893 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012894 }
12895
12896 // Now take care of the next serialized one...
12897
12898 // If we are waiting for a process to come up to handle the next
12899 // broadcast, then do nothing at this point. Just in case, we
12900 // check that the process we're waiting for still exists.
12901 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012902 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012903 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012904 + mPendingBroadcast.curApp);
12905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012906
12907 boolean isDead;
12908 synchronized (mPidsSelfLocked) {
12909 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12910 }
12911 if (!isDead) {
12912 // It's still alive, so keep waiting
12913 return;
12914 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012915 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012916 + " died before responding to broadcast");
12917 mPendingBroadcast = null;
12918 }
12919 }
12920
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012921 boolean looped = false;
12922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012923 do {
12924 if (mOrderedBroadcasts.size() == 0) {
12925 // No more broadcasts pending, so all done!
12926 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012927 if (looped) {
12928 // If we had finished the last ordered broadcast, then
12929 // make sure all processes have correct oom and sched
12930 // adjustments.
12931 updateOomAdjLocked();
12932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012933 return;
12934 }
12935 r = mOrderedBroadcasts.get(0);
12936 boolean forceReceive = false;
12937
12938 // Ensure that even if something goes awry with the timeout
12939 // detection, we catch "hung" broadcasts here, discard them,
12940 // and continue to make progress.
12941 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12942 long now = SystemClock.uptimeMillis();
12943 if (r.dispatchTime > 0) {
12944 if ((numReceivers > 0) &&
12945 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012946 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012947 + " now=" + now
12948 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012949 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012950 + " intent=" + r.intent
12951 + " numReceivers=" + numReceivers
12952 + " nextReceiver=" + r.nextReceiver
12953 + " state=" + r.state);
12954 broadcastTimeout(); // forcibly finish this broadcast
12955 forceReceive = true;
12956 r.state = BroadcastRecord.IDLE;
12957 }
12958 }
12959
12960 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012961 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012962 "processNextBroadcast() called when not idle (state="
12963 + r.state + ")");
12964 return;
12965 }
12966
12967 if (r.receivers == null || r.nextReceiver >= numReceivers
12968 || r.resultAbort || forceReceive) {
12969 // No more receivers for this broadcast! Send the final
12970 // result if requested...
12971 if (r.resultTo != null) {
12972 try {
12973 if (DEBUG_BROADCAST) {
12974 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012975 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012976 + " seq=" + seq + " app=" + r.callerApp);
12977 }
12978 performReceive(r.callerApp, r.resultTo,
12979 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012980 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012981 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012982 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012983 }
12984 }
12985
Joe Onorato8a9b2202010-02-26 18:56:32 -080012986 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012987 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12988
Joe Onorato8a9b2202010-02-26 18:56:32 -080012989 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012990 + r);
12991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012992 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012993 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012994 mOrderedBroadcasts.remove(0);
12995 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012996 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012997 continue;
12998 }
12999 } while (r == null);
13000
13001 // Get the next receiver...
13002 int recIdx = r.nextReceiver++;
13003
13004 // Keep track of when this receiver started, and make sure there
13005 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013006 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013007 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013008 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013009
Joe Onorato8a9b2202010-02-26 18:56:32 -080013010 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013011 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013012 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013013 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013014 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013015 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013016 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013017 }
13018
13019 Object nextReceiver = r.receivers.get(recIdx);
13020 if (nextReceiver instanceof BroadcastFilter) {
13021 // Simple case: this is a registered receiver who gets
13022 // a direct call.
13023 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013024 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013025 "Delivering serialized to registered "
13026 + filter + ": " + r);
13027 deliverToRegisteredReceiver(r, filter, r.ordered);
13028 if (r.receiver == null || !r.ordered) {
13029 // The receiver has already finished, so schedule to
13030 // process the next one.
13031 r.state = BroadcastRecord.IDLE;
13032 scheduleBroadcastsLocked();
13033 }
13034 return;
13035 }
13036
13037 // Hard case: need to instantiate the receiver, possibly
13038 // starting its application process to host it.
13039
13040 ResolveInfo info =
13041 (ResolveInfo)nextReceiver;
13042
13043 boolean skip = false;
13044 int perm = checkComponentPermission(info.activityInfo.permission,
13045 r.callingPid, r.callingUid,
13046 info.activityInfo.exported
13047 ? -1 : info.activityInfo.applicationInfo.uid);
13048 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013049 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013050 + r.intent.toString()
13051 + " from " + r.callerPackage + " (pid=" + r.callingPid
13052 + ", uid=" + r.callingUid + ")"
13053 + " requires " + info.activityInfo.permission
13054 + " due to receiver " + info.activityInfo.packageName
13055 + "/" + info.activityInfo.name);
13056 skip = true;
13057 }
13058 if (r.callingUid != Process.SYSTEM_UID &&
13059 r.requiredPermission != null) {
13060 try {
13061 perm = ActivityThread.getPackageManager().
13062 checkPermission(r.requiredPermission,
13063 info.activityInfo.applicationInfo.packageName);
13064 } catch (RemoteException e) {
13065 perm = PackageManager.PERMISSION_DENIED;
13066 }
13067 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013068 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013069 + r.intent + " to "
13070 + info.activityInfo.applicationInfo.packageName
13071 + " requires " + r.requiredPermission
13072 + " due to sender " + r.callerPackage
13073 + " (uid " + r.callingUid + ")");
13074 skip = true;
13075 }
13076 }
13077 if (r.curApp != null && r.curApp.crashing) {
13078 // If the target process is crashing, just skip it.
13079 skip = true;
13080 }
13081
13082 if (skip) {
13083 r.receiver = null;
13084 r.curFilter = null;
13085 r.state = BroadcastRecord.IDLE;
13086 scheduleBroadcastsLocked();
13087 return;
13088 }
13089
13090 r.state = BroadcastRecord.APP_RECEIVE;
13091 String targetProcess = info.activityInfo.processName;
13092 r.curComponent = new ComponentName(
13093 info.activityInfo.applicationInfo.packageName,
13094 info.activityInfo.name);
13095 r.curReceiver = info.activityInfo;
13096
13097 // Is this receiver's application already running?
13098 ProcessRecord app = getProcessRecordLocked(targetProcess,
13099 info.activityInfo.applicationInfo.uid);
13100 if (app != null && app.thread != null) {
13101 try {
13102 processCurBroadcastLocked(r, app);
13103 return;
13104 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013105 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013106 + r.curComponent, e);
13107 }
13108
13109 // If a dead object exception was thrown -- fall through to
13110 // restart the application.
13111 }
13112
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013113 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013114 if ((r.curApp=startProcessLocked(targetProcess,
13115 info.activityInfo.applicationInfo, true,
13116 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013117 "broadcast", r.curComponent,
13118 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13119 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013120 // Ah, this recipient is unavailable. Finish it if necessary,
13121 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013122 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013123 + info.activityInfo.applicationInfo.packageName + "/"
13124 + info.activityInfo.applicationInfo.uid + " for broadcast "
13125 + r.intent + ": process is bad");
13126 logBroadcastReceiverDiscard(r);
13127 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13128 r.resultExtras, r.resultAbort, true);
13129 scheduleBroadcastsLocked();
13130 r.state = BroadcastRecord.IDLE;
13131 return;
13132 }
13133
13134 mPendingBroadcast = r;
13135 }
13136 }
13137
13138 // =========================================================
13139 // INSTRUMENTATION
13140 // =========================================================
13141
13142 public boolean startInstrumentation(ComponentName className,
13143 String profileFile, int flags, Bundle arguments,
13144 IInstrumentationWatcher watcher) {
13145 // Refuse possible leaked file descriptors
13146 if (arguments != null && arguments.hasFileDescriptors()) {
13147 throw new IllegalArgumentException("File descriptors passed in Bundle");
13148 }
13149
13150 synchronized(this) {
13151 InstrumentationInfo ii = null;
13152 ApplicationInfo ai = null;
13153 try {
13154 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013155 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013156 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013157 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013158 } catch (PackageManager.NameNotFoundException e) {
13159 }
13160 if (ii == null) {
13161 reportStartInstrumentationFailure(watcher, className,
13162 "Unable to find instrumentation info for: " + className);
13163 return false;
13164 }
13165 if (ai == null) {
13166 reportStartInstrumentationFailure(watcher, className,
13167 "Unable to find instrumentation target package: " + ii.targetPackage);
13168 return false;
13169 }
13170
13171 int match = mContext.getPackageManager().checkSignatures(
13172 ii.targetPackage, ii.packageName);
13173 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13174 String msg = "Permission Denial: starting instrumentation "
13175 + className + " from pid="
13176 + Binder.getCallingPid()
13177 + ", uid=" + Binder.getCallingPid()
13178 + " not allowed because package " + ii.packageName
13179 + " does not have a signature matching the target "
13180 + ii.targetPackage;
13181 reportStartInstrumentationFailure(watcher, className, msg);
13182 throw new SecurityException(msg);
13183 }
13184
13185 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013186 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013187 ProcessRecord app = addAppLocked(ai);
13188 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013189 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013190 app.instrumentationProfileFile = profileFile;
13191 app.instrumentationArguments = arguments;
13192 app.instrumentationWatcher = watcher;
13193 app.instrumentationResultClass = className;
13194 Binder.restoreCallingIdentity(origId);
13195 }
13196
13197 return true;
13198 }
13199
13200 /**
13201 * Report errors that occur while attempting to start Instrumentation. Always writes the
13202 * error to the logs, but if somebody is watching, send the report there too. This enables
13203 * the "am" command to report errors with more information.
13204 *
13205 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13206 * @param cn The component name of the instrumentation.
13207 * @param report The error report.
13208 */
13209 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13210 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013211 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013212 try {
13213 if (watcher != null) {
13214 Bundle results = new Bundle();
13215 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13216 results.putString("Error", report);
13217 watcher.instrumentationStatus(cn, -1, results);
13218 }
13219 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013220 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013221 }
13222 }
13223
13224 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13225 if (app.instrumentationWatcher != null) {
13226 try {
13227 // NOTE: IInstrumentationWatcher *must* be oneway here
13228 app.instrumentationWatcher.instrumentationFinished(
13229 app.instrumentationClass,
13230 resultCode,
13231 results);
13232 } catch (RemoteException e) {
13233 }
13234 }
13235 app.instrumentationWatcher = null;
13236 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013237 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013238 app.instrumentationProfileFile = null;
13239 app.instrumentationArguments = null;
13240
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013241 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013242 }
13243
13244 public void finishInstrumentation(IApplicationThread target,
13245 int resultCode, Bundle results) {
13246 // Refuse possible leaked file descriptors
13247 if (results != null && results.hasFileDescriptors()) {
13248 throw new IllegalArgumentException("File descriptors passed in Intent");
13249 }
13250
13251 synchronized(this) {
13252 ProcessRecord app = getRecordForAppLocked(target);
13253 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013254 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013255 return;
13256 }
13257 final long origId = Binder.clearCallingIdentity();
13258 finishInstrumentationLocked(app, resultCode, results);
13259 Binder.restoreCallingIdentity(origId);
13260 }
13261 }
13262
13263 // =========================================================
13264 // CONFIGURATION
13265 // =========================================================
13266
13267 public ConfigurationInfo getDeviceConfigurationInfo() {
13268 ConfigurationInfo config = new ConfigurationInfo();
13269 synchronized (this) {
13270 config.reqTouchScreen = mConfiguration.touchscreen;
13271 config.reqKeyboardType = mConfiguration.keyboard;
13272 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013273 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13274 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013275 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13276 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013277 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13278 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013279 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13280 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013281 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013282 }
13283 return config;
13284 }
13285
13286 public Configuration getConfiguration() {
13287 Configuration ci;
13288 synchronized(this) {
13289 ci = new Configuration(mConfiguration);
13290 }
13291 return ci;
13292 }
13293
13294 public void updateConfiguration(Configuration values) {
13295 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13296 "updateConfiguration()");
13297
13298 synchronized(this) {
13299 if (values == null && mWindowManager != null) {
13300 // sentinel: fetch the current configuration from the window manager
13301 values = mWindowManager.computeNewConfiguration();
13302 }
13303
13304 final long origId = Binder.clearCallingIdentity();
13305 updateConfigurationLocked(values, null);
13306 Binder.restoreCallingIdentity(origId);
13307 }
13308 }
13309
13310 /**
13311 * Do either or both things: (1) change the current configuration, and (2)
13312 * make sure the given activity is running with the (now) current
13313 * configuration. Returns true if the activity has been left running, or
13314 * false if <var>starting</var> is being destroyed to match the new
13315 * configuration.
13316 */
13317 public boolean updateConfigurationLocked(Configuration values,
13318 HistoryRecord starting) {
13319 int changes = 0;
13320
13321 boolean kept = true;
13322
13323 if (values != null) {
13324 Configuration newConfig = new Configuration(mConfiguration);
13325 changes = newConfig.updateFrom(values);
13326 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013327 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013328 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013329 }
13330
Doug Zongker2bec3d42009-12-04 12:52:44 -080013331 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013332
13333 if (values.locale != null) {
13334 saveLocaleLocked(values.locale,
13335 !values.locale.equals(mConfiguration.locale),
13336 values.userSetLocale);
13337 }
13338
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013339 mConfigurationSeq++;
13340 if (mConfigurationSeq <= 0) {
13341 mConfigurationSeq = 1;
13342 }
13343 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013344 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013345 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013346
13347 AttributeCache ac = AttributeCache.instance();
13348 if (ac != null) {
13349 ac.updateConfiguration(mConfiguration);
13350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013351
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013352 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13353 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13354 msg.obj = new Configuration(mConfiguration);
13355 mHandler.sendMessage(msg);
13356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013357
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013358 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13359 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013360 try {
13361 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013362 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013363 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013364 app.thread.scheduleConfigurationChanged(mConfiguration);
13365 }
13366 } catch (Exception e) {
13367 }
13368 }
13369 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013370 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13371 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013372 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13373 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013374 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13375 broadcastIntentLocked(null, null,
13376 new Intent(Intent.ACTION_LOCALE_CHANGED),
13377 null, null, 0, null, null,
13378 null, false, false, MY_PID, Process.SYSTEM_UID);
13379 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013380 }
13381 }
13382
13383 if (changes != 0 && starting == null) {
13384 // If the configuration changed, and the caller is not already
13385 // in the process of starting an activity, then find the top
13386 // activity to check if its configuration needs to change.
13387 starting = topRunningActivityLocked(null);
13388 }
13389
13390 if (starting != null) {
13391 kept = ensureActivityConfigurationLocked(starting, changes);
13392 if (kept) {
13393 // If this didn't result in the starting activity being
13394 // destroyed, then we need to make sure at this point that all
13395 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013396 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013397 + ", ensuring others are correct.");
13398 ensureActivitiesVisibleLocked(starting, changes);
13399 }
13400 }
13401
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013402 if (values != null && mWindowManager != null) {
13403 mWindowManager.setNewConfiguration(mConfiguration);
13404 }
13405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013406 return kept;
13407 }
13408
13409 private final boolean relaunchActivityLocked(HistoryRecord r,
13410 int changes, boolean andResume) {
13411 List<ResultInfo> results = null;
13412 List<Intent> newIntents = null;
13413 if (andResume) {
13414 results = r.results;
13415 newIntents = r.newIntents;
13416 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013417 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013418 + " with results=" + results + " newIntents=" + newIntents
13419 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013420 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13421 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013422 r.task.taskId, r.shortComponentName);
13423
13424 r.startFreezingScreenLocked(r.app, 0);
13425
13426 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013427 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013428 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013429 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013430 // Note: don't need to call pauseIfSleepingLocked() here, because
13431 // the caller will only pass in 'andResume' if this activity is
13432 // currently resumed, which implies we aren't sleeping.
13433 } catch (RemoteException e) {
13434 return false;
13435 }
13436
13437 if (andResume) {
13438 r.results = null;
13439 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013440 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013441 }
13442
13443 return true;
13444 }
13445
13446 /**
13447 * Make sure the given activity matches the current configuration. Returns
13448 * false if the activity had to be destroyed. Returns true if the
13449 * configuration is the same, or the activity will remain running as-is
13450 * for whatever reason. Ensures the HistoryRecord is updated with the
13451 * correct configuration and all other bookkeeping is handled.
13452 */
13453 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13454 int globalChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013455 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013456 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013457
13458 // Short circuit: if the two configurations are the exact same
13459 // object (the common case), then there is nothing to do.
13460 Configuration newConfig = mConfiguration;
13461 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013462 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013463 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013464 return true;
13465 }
13466
13467 // We don't worry about activities that are finishing.
13468 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013469 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013470 "Configuration doesn't matter in finishing " + r);
13471 r.stopFreezingScreenLocked(false);
13472 return true;
13473 }
13474
13475 // Okay we now are going to make this activity have the new config.
13476 // But then we need to figure out how it needs to deal with that.
13477 Configuration oldConfig = r.configuration;
13478 r.configuration = newConfig;
13479
13480 // If the activity isn't currently running, just leave the new
13481 // configuration and it will pick that up next time it starts.
13482 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013483 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013484 "Configuration doesn't matter not running " + r);
13485 r.stopFreezingScreenLocked(false);
13486 return true;
13487 }
13488
13489 // If the activity isn't persistent, there is a chance we will
13490 // need to restart it.
13491 if (!r.persistent) {
13492
13493 // Figure out what has changed between the two configurations.
13494 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013495 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013496 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013497 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013498 + Integer.toHexString(r.info.configChanges)
13499 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013500 }
13501 if ((changes&(~r.info.configChanges)) != 0) {
13502 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13503 r.configChangeFlags |= changes;
13504 r.startFreezingScreenLocked(r.app, globalChanges);
13505 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013506 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013507 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013508 destroyActivityLocked(r, true);
13509 } else if (r.state == ActivityState.PAUSING) {
13510 // A little annoying: we are waiting for this activity to
13511 // finish pausing. Let's not do anything now, but just
13512 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013513 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013514 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013515 r.configDestroy = true;
13516 return true;
13517 } else if (r.state == ActivityState.RESUMED) {
13518 // Try to optimize this case: the configuration is changing
13519 // and we need to restart the top, resumed activity.
13520 // Instead of doing the normal handshaking, just say
13521 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013522 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013523 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013524 relaunchActivityLocked(r, r.configChangeFlags, true);
13525 r.configChangeFlags = 0;
13526 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013527 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013528 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013529 relaunchActivityLocked(r, r.configChangeFlags, false);
13530 r.configChangeFlags = 0;
13531 }
13532
13533 // All done... tell the caller we weren't able to keep this
13534 // activity around.
13535 return false;
13536 }
13537 }
13538
13539 // Default case: the activity can handle this new configuration, so
13540 // hand it over. Note that we don't need to give it the new
13541 // configuration, since we always send configuration changes to all
13542 // process when they happen so it can just use whatever configuration
13543 // it last got.
13544 if (r.app != null && r.app.thread != null) {
13545 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013546 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013547 r.app.thread.scheduleActivityConfigurationChanged(r);
13548 } catch (RemoteException e) {
13549 // If process died, whatever.
13550 }
13551 }
13552 r.stopFreezingScreenLocked(false);
13553
13554 return true;
13555 }
13556
13557 /**
13558 * Save the locale. You must be inside a synchronized (this) block.
13559 */
13560 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13561 if(isDiff) {
13562 SystemProperties.set("user.language", l.getLanguage());
13563 SystemProperties.set("user.region", l.getCountry());
13564 }
13565
13566 if(isPersist) {
13567 SystemProperties.set("persist.sys.language", l.getLanguage());
13568 SystemProperties.set("persist.sys.country", l.getCountry());
13569 SystemProperties.set("persist.sys.localevar", l.getVariant());
13570 }
13571 }
13572
13573 // =========================================================
13574 // LIFETIME MANAGEMENT
13575 // =========================================================
13576
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013577 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13578 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013579 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013580 // This adjustment has already been computed. If we are calling
13581 // from the top, we may have already computed our adjustment with
13582 // an earlier hidden adjustment that isn't really for us... if
13583 // so, use the new hidden adjustment.
13584 if (!recursed && app.hidden) {
13585 app.curAdj = hiddenAdj;
13586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013587 return app.curAdj;
13588 }
13589
13590 if (app.thread == null) {
13591 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013592 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013593 return (app.curAdj=EMPTY_APP_ADJ);
13594 }
13595
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013596 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13597 // The max adjustment doesn't allow this app to be anything
13598 // below foreground, so it is not worth doing work for it.
13599 app.adjType = "fixed";
13600 app.adjSeq = mAdjSeq;
13601 app.curRawAdj = app.maxAdj;
13602 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13603 return (app.curAdj=app.maxAdj);
13604 }
13605
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013606 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013607 app.adjSource = null;
13608 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013609 app.empty = false;
13610 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013611
The Android Open Source Project4df24232009-03-05 14:34:35 -080013612 // Determine the importance of the process, starting with most
13613 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013614 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013615 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013616 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013617 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013618 // The last app on the list is the foreground app.
13619 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013620 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013621 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013622 } else if (app.instrumentationClass != null) {
13623 // Don't want to kill running instrumentation.
13624 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013625 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013626 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013627 } else if (app.persistentActivities > 0) {
13628 // Special persistent activities... shouldn't be used these days.
13629 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013630 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013631 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013632 } else if (app.curReceiver != null ||
13633 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13634 // An app that is currently receiving a broadcast also
13635 // counts as being in the foreground.
13636 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013637 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013638 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013639 } else if (app.executingServices.size() > 0) {
13640 // An app that is currently executing a service callback also
13641 // counts as being in the foreground.
13642 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013643 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013644 app.adjType = "exec-service";
13645 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013646 // The user is aware of this app, so make it visible.
13647 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013648 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013649 app.adjType = "foreground-service";
13650 } else if (app.forcingToForeground != null) {
13651 // The user is aware of this app, so make it visible.
13652 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013653 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013654 app.adjType = "force-foreground";
13655 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013656 } else if (app == mHomeProcess) {
13657 // This process is hosting what we currently consider to be the
13658 // home app, so we don't want to let it go into the background.
13659 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013660 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013661 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013662 } else if ((N=app.activities.size()) != 0) {
13663 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013664 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013665 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013666 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013667 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013668 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013669 for (int j=0; j<N; j++) {
13670 if (((HistoryRecord)app.activities.get(j)).visible) {
13671 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013672 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013673 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013674 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013675 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013676 break;
13677 }
13678 }
13679 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013680 // A very not-needed process. If this is lower in the lru list,
13681 // we will push it in to the empty bucket.
13682 app.hidden = true;
13683 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013684 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013685 adj = hiddenAdj;
13686 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013687 }
13688
Joe Onorato8a9b2202010-02-26 18:56:32 -080013689 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013690
The Android Open Source Project4df24232009-03-05 14:34:35 -080013691 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013692 // there are applications dependent on our services or providers, but
13693 // this gives us a baseline and makes sure we don't get into an
13694 // infinite recursion.
13695 app.adjSeq = mAdjSeq;
13696 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013697
Christopher Tate6fa95972009-06-05 18:43:55 -070013698 if (mBackupTarget != null && app == mBackupTarget.app) {
13699 // If possible we want to avoid killing apps while they're being backed up
13700 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013701 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013702 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013703 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013704 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013705 }
13706 }
13707
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013708 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13709 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013710 final long now = SystemClock.uptimeMillis();
13711 // This process is more important if the top activity is
13712 // bound to the service.
13713 Iterator jt = app.services.iterator();
13714 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13715 ServiceRecord s = (ServiceRecord)jt.next();
13716 if (s.startRequested) {
13717 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13718 // This service has seen some activity within
13719 // recent memory, so we will keep its process ahead
13720 // of the background processes.
13721 if (adj > SECONDARY_SERVER_ADJ) {
13722 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013723 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013724 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013725 }
13726 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013727 // If we have let the service slide into the background
13728 // state, still have some text describing what it is doing
13729 // even though the service no longer has an impact.
13730 if (adj > SECONDARY_SERVER_ADJ) {
13731 app.adjType = "started-bg-services";
13732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013733 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013734 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13735 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013736 Iterator<ConnectionRecord> kt
13737 = s.connections.values().iterator();
13738 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13739 // XXX should compute this based on the max of
13740 // all connected clients.
13741 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013742 if (cr.binding.client == app) {
13743 // Binding to ourself is not interesting.
13744 continue;
13745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013746 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13747 ProcessRecord client = cr.binding.client;
13748 int myHiddenAdj = hiddenAdj;
13749 if (myHiddenAdj > client.hiddenAdj) {
13750 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13751 myHiddenAdj = client.hiddenAdj;
13752 } else {
13753 myHiddenAdj = VISIBLE_APP_ADJ;
13754 }
13755 }
13756 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013757 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013758 if (adj > clientAdj) {
13759 adj = clientAdj > VISIBLE_APP_ADJ
13760 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013761 if (!client.hidden) {
13762 app.hidden = false;
13763 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013764 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013765 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13766 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013767 app.adjSource = cr.binding.client;
13768 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013769 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013770 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13771 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13772 schedGroup = Process.THREAD_GROUP_DEFAULT;
13773 }
13774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013775 }
13776 HistoryRecord a = cr.activity;
13777 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013778 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013779 //}
13780 if (a != null && adj > FOREGROUND_APP_ADJ &&
13781 (a.state == ActivityState.RESUMED
13782 || a.state == ActivityState.PAUSING)) {
13783 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013784 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013785 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013786 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013787 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13788 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013789 app.adjSource = a;
13790 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013791 }
13792 }
13793 }
13794 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013795
13796 // Finally, f this process has active services running in it, we
13797 // would like to avoid killing it unless it would prevent the current
13798 // application from running. By default we put the process in
13799 // with the rest of the background processes; as we scan through
13800 // its services we may bump it up from there.
13801 if (adj > hiddenAdj) {
13802 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013803 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013804 app.adjType = "bg-services";
13805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013806 }
13807
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013808 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13809 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013810 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013811 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13812 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013813 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13814 if (cpr.clients.size() != 0) {
13815 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13816 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13817 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013818 if (client == app) {
13819 // Being our own client is not interesting.
13820 continue;
13821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013822 int myHiddenAdj = hiddenAdj;
13823 if (myHiddenAdj > client.hiddenAdj) {
13824 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13825 myHiddenAdj = client.hiddenAdj;
13826 } else {
13827 myHiddenAdj = FOREGROUND_APP_ADJ;
13828 }
13829 }
13830 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013831 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013832 if (adj > clientAdj) {
13833 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013834 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013835 if (!client.hidden) {
13836 app.hidden = false;
13837 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013838 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013839 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13840 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013841 app.adjSource = client;
13842 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013843 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013844 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13845 schedGroup = Process.THREAD_GROUP_DEFAULT;
13846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013847 }
13848 }
13849 // If the provider has external (non-framework) process
13850 // dependencies, ensure that its adjustment is at least
13851 // FOREGROUND_APP_ADJ.
13852 if (cpr.externals != 0) {
13853 if (adj > FOREGROUND_APP_ADJ) {
13854 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013855 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013856 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013857 app.adjType = "provider";
13858 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013859 }
13860 }
13861 }
13862 }
13863
13864 app.curRawAdj = adj;
13865
Joe Onorato8a9b2202010-02-26 18:56:32 -080013866 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013867 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13868 if (adj > app.maxAdj) {
13869 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013870 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13871 schedGroup = Process.THREAD_GROUP_DEFAULT;
13872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013873 }
13874
13875 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013876 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013878 return adj;
13879 }
13880
13881 /**
13882 * Ask a given process to GC right now.
13883 */
13884 final void performAppGcLocked(ProcessRecord app) {
13885 try {
13886 app.lastRequestedGc = SystemClock.uptimeMillis();
13887 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013888 if (app.reportLowMemory) {
13889 app.reportLowMemory = false;
13890 app.thread.scheduleLowMemory();
13891 } else {
13892 app.thread.processInBackground();
13893 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013894 }
13895 } catch (Exception e) {
13896 // whatever.
13897 }
13898 }
13899
13900 /**
13901 * Returns true if things are idle enough to perform GCs.
13902 */
Josh Bartel7f208742010-02-25 11:01:44 -060013903 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013904 return mParallelBroadcasts.size() == 0
13905 && mOrderedBroadcasts.size() == 0
13906 && (mSleeping || (mResumedActivity != null &&
13907 mResumedActivity.idle));
13908 }
13909
13910 /**
13911 * Perform GCs on all processes that are waiting for it, but only
13912 * if things are idle.
13913 */
13914 final void performAppGcsLocked() {
13915 final int N = mProcessesToGc.size();
13916 if (N <= 0) {
13917 return;
13918 }
Josh Bartel7f208742010-02-25 11:01:44 -060013919 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013920 while (mProcessesToGc.size() > 0) {
13921 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013922 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13923 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13924 <= SystemClock.uptimeMillis()) {
13925 // To avoid spamming the system, we will GC processes one
13926 // at a time, waiting a few seconds between each.
13927 performAppGcLocked(proc);
13928 scheduleAppGcsLocked();
13929 return;
13930 } else {
13931 // It hasn't been long enough since we last GCed this
13932 // process... put it in the list to wait for its time.
13933 addProcessToGcListLocked(proc);
13934 break;
13935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013936 }
13937 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013938
13939 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013940 }
13941 }
13942
13943 /**
13944 * If all looks good, perform GCs on all processes waiting for them.
13945 */
13946 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060013947 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013948 performAppGcsLocked();
13949 return;
13950 }
13951 // Still not idle, wait some more.
13952 scheduleAppGcsLocked();
13953 }
13954
13955 /**
13956 * Schedule the execution of all pending app GCs.
13957 */
13958 final void scheduleAppGcsLocked() {
13959 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013960
13961 if (mProcessesToGc.size() > 0) {
13962 // Schedule a GC for the time to the next process.
13963 ProcessRecord proc = mProcessesToGc.get(0);
13964 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13965
13966 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13967 long now = SystemClock.uptimeMillis();
13968 if (when < (now+GC_TIMEOUT)) {
13969 when = now + GC_TIMEOUT;
13970 }
13971 mHandler.sendMessageAtTime(msg, when);
13972 }
13973 }
13974
13975 /**
13976 * Add a process to the array of processes waiting to be GCed. Keeps the
13977 * list in sorted order by the last GC time. The process can't already be
13978 * on the list.
13979 */
13980 final void addProcessToGcListLocked(ProcessRecord proc) {
13981 boolean added = false;
13982 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13983 if (mProcessesToGc.get(i).lastRequestedGc <
13984 proc.lastRequestedGc) {
13985 added = true;
13986 mProcessesToGc.add(i+1, proc);
13987 break;
13988 }
13989 }
13990 if (!added) {
13991 mProcessesToGc.add(0, proc);
13992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013993 }
13994
13995 /**
13996 * Set up to ask a process to GC itself. This will either do it
13997 * immediately, or put it on the list of processes to gc the next
13998 * time things are idle.
13999 */
14000 final void scheduleAppGcLocked(ProcessRecord app) {
14001 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014002 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014003 return;
14004 }
14005 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014006 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014007 scheduleAppGcsLocked();
14008 }
14009 }
14010
14011 private final boolean updateOomAdjLocked(
14012 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14013 app.hiddenAdj = hiddenAdj;
14014
14015 if (app.thread == null) {
14016 return true;
14017 }
14018
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014019 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014020
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014021 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014022 if (app.curRawAdj != app.setRawAdj) {
14023 if (app.curRawAdj > FOREGROUND_APP_ADJ
14024 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14025 // If this app is transitioning from foreground to
14026 // non-foreground, have it do a gc.
14027 scheduleAppGcLocked(app);
14028 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14029 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14030 // Likewise do a gc when an app is moving in to the
14031 // background (such as a service stopping).
14032 scheduleAppGcLocked(app);
14033 }
14034 app.setRawAdj = app.curRawAdj;
14035 }
14036 if (adj != app.setAdj) {
14037 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014038 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014039 TAG, "Set app " + app.processName +
14040 " oom adj to " + adj);
14041 app.setAdj = adj;
14042 } else {
14043 return false;
14044 }
14045 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014046 if (app.setSchedGroup != app.curSchedGroup) {
14047 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014048 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014049 "Setting process group of " + app.processName
14050 + " to " + app.curSchedGroup);
14051 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014052 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014053 try {
14054 Process.setProcessGroup(app.pid, app.curSchedGroup);
14055 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014056 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014057 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014058 e.printStackTrace();
14059 } finally {
14060 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014061 }
14062 }
14063 if (false) {
14064 if (app.thread != null) {
14065 try {
14066 app.thread.setSchedulingGroup(app.curSchedGroup);
14067 } catch (RemoteException e) {
14068 }
14069 }
14070 }
14071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014072 }
14073
14074 return true;
14075 }
14076
14077 private final HistoryRecord resumedAppLocked() {
14078 HistoryRecord resumedActivity = mResumedActivity;
14079 if (resumedActivity == null || resumedActivity.app == null) {
14080 resumedActivity = mPausingActivity;
14081 if (resumedActivity == null || resumedActivity.app == null) {
14082 resumedActivity = topRunningActivityLocked(null);
14083 }
14084 }
14085 return resumedActivity;
14086 }
14087
14088 private final boolean updateOomAdjLocked(ProcessRecord app) {
14089 final HistoryRecord TOP_ACT = resumedAppLocked();
14090 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14091 int curAdj = app.curAdj;
14092 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14093 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14094
14095 mAdjSeq++;
14096
14097 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14098 if (res) {
14099 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14100 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14101 if (nowHidden != wasHidden) {
14102 // Changed to/from hidden state, so apps after it in the LRU
14103 // list may also be changed.
14104 updateOomAdjLocked();
14105 }
14106 }
14107 return res;
14108 }
14109
14110 private final boolean updateOomAdjLocked() {
14111 boolean didOomAdj = true;
14112 final HistoryRecord TOP_ACT = resumedAppLocked();
14113 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14114
14115 if (false) {
14116 RuntimeException e = new RuntimeException();
14117 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014118 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014119 }
14120
14121 mAdjSeq++;
14122
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014123 // Let's determine how many processes we have running vs.
14124 // how many slots we have for background processes; we may want
14125 // to put multiple processes in a slot of there are enough of
14126 // them.
14127 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14128 int factor = (mLruProcesses.size()-4)/numSlots;
14129 if (factor < 1) factor = 1;
14130 int step = 0;
14131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014132 // First try updating the OOM adjustment for each of the
14133 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014134 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014135 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14136 while (i > 0) {
14137 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014138 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014139 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014140 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014141 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014142 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014143 step++;
14144 if (step >= factor) {
14145 step = 0;
14146 curHiddenAdj++;
14147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014148 }
14149 } else {
14150 didOomAdj = false;
14151 }
14152 }
14153
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014154 // If we return false, we will fall back on killing processes to
14155 // have a fixed limit. Do this if a limit has been requested; else
14156 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014157 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14158 }
14159
14160 private final void trimApplications() {
14161 synchronized (this) {
14162 int i;
14163
14164 // First remove any unused application processes whose package
14165 // has been removed.
14166 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14167 final ProcessRecord app = mRemovedProcesses.get(i);
14168 if (app.activities.size() == 0
14169 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014170 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014171 TAG, "Exiting empty application process "
14172 + app.processName + " ("
14173 + (app.thread != null ? app.thread.asBinder() : null)
14174 + ")\n");
14175 if (app.pid > 0 && app.pid != MY_PID) {
14176 Process.killProcess(app.pid);
14177 } else {
14178 try {
14179 app.thread.scheduleExit();
14180 } catch (Exception e) {
14181 // Ignore exceptions.
14182 }
14183 }
14184 cleanUpApplicationRecordLocked(app, false, -1);
14185 mRemovedProcesses.remove(i);
14186
14187 if (app.persistent) {
14188 if (app.persistent) {
14189 addAppLocked(app.info);
14190 }
14191 }
14192 }
14193 }
14194
14195 // Now try updating the OOM adjustment for each of the
14196 // application processes based on their current state.
14197 // If the setOomAdj() API is not supported, then go with our
14198 // back-up plan...
14199 if (!updateOomAdjLocked()) {
14200
14201 // Count how many processes are running services.
14202 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014203 for (i=mLruProcesses.size()-1; i>=0; i--) {
14204 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014205
14206 if (app.persistent || app.services.size() != 0
14207 || app.curReceiver != null
14208 || app.persistentActivities > 0) {
14209 // Don't count processes holding services against our
14210 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014211 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014212 TAG, "Not trimming app " + app + " with services: "
14213 + app.services);
14214 numServiceProcs++;
14215 }
14216 }
14217
14218 int curMaxProcs = mProcessLimit;
14219 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14220 if (mAlwaysFinishActivities) {
14221 curMaxProcs = 1;
14222 }
14223 curMaxProcs += numServiceProcs;
14224
14225 // Quit as many processes as we can to get down to the desired
14226 // process count. First remove any processes that no longer
14227 // have activites running in them.
14228 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014229 i<mLruProcesses.size()
14230 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014231 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014232 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014233 // Quit an application only if it is not currently
14234 // running any activities.
14235 if (!app.persistent && app.activities.size() == 0
14236 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014237 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014238 TAG, "Exiting empty application process "
14239 + app.processName + " ("
14240 + (app.thread != null ? app.thread.asBinder() : null)
14241 + ")\n");
14242 if (app.pid > 0 && app.pid != MY_PID) {
14243 Process.killProcess(app.pid);
14244 } else {
14245 try {
14246 app.thread.scheduleExit();
14247 } catch (Exception e) {
14248 // Ignore exceptions.
14249 }
14250 }
14251 // todo: For now we assume the application is not buggy
14252 // or evil, and will quit as a result of our request.
14253 // Eventually we need to drive this off of the death
14254 // notification, and kill the process if it takes too long.
14255 cleanUpApplicationRecordLocked(app, false, i);
14256 i--;
14257 }
14258 }
14259
14260 // If we still have too many processes, now from the least
14261 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014262 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014263 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014264 " of " + curMaxProcs + " processes");
14265 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014266 i<mLruProcesses.size()
14267 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014268 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014269 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014270 // Quit the application only if we have a state saved for
14271 // all of its activities.
14272 boolean canQuit = !app.persistent && app.curReceiver == null
14273 && app.services.size() == 0
14274 && app.persistentActivities == 0;
14275 int NUMA = app.activities.size();
14276 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014277 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014278 TAG, "Looking to quit " + app.processName);
14279 for (j=0; j<NUMA && canQuit; j++) {
14280 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014281 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014282 TAG, " " + r.intent.getComponent().flattenToShortString()
14283 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14284 canQuit = (r.haveState || !r.stateNotNeeded)
14285 && !r.visible && r.stopped;
14286 }
14287 if (canQuit) {
14288 // Finish all of the activities, and then the app itself.
14289 for (j=0; j<NUMA; j++) {
14290 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14291 if (!r.finishing) {
14292 destroyActivityLocked(r, false);
14293 }
14294 r.resultTo = null;
14295 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014296 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014297 + app.processName + " ("
14298 + (app.thread != null ? app.thread.asBinder() : null)
14299 + ")\n");
14300 if (app.pid > 0 && app.pid != MY_PID) {
14301 Process.killProcess(app.pid);
14302 } else {
14303 try {
14304 app.thread.scheduleExit();
14305 } catch (Exception e) {
14306 // Ignore exceptions.
14307 }
14308 }
14309 // todo: For now we assume the application is not buggy
14310 // or evil, and will quit as a result of our request.
14311 // Eventually we need to drive this off of the death
14312 // notification, and kill the process if it takes too long.
14313 cleanUpApplicationRecordLocked(app, false, i);
14314 i--;
14315 //dump();
14316 }
14317 }
14318
14319 }
14320
14321 int curMaxActivities = MAX_ACTIVITIES;
14322 if (mAlwaysFinishActivities) {
14323 curMaxActivities = 1;
14324 }
14325
14326 // Finally, if there are too many activities now running, try to
14327 // finish as many as we can to get back down to the limit.
14328 for ( i=0;
14329 i<mLRUActivities.size()
14330 && mLRUActivities.size() > curMaxActivities;
14331 i++) {
14332 final HistoryRecord r
14333 = (HistoryRecord)mLRUActivities.get(i);
14334
14335 // We can finish this one if we have its icicle saved and
14336 // it is not persistent.
14337 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14338 && r.stopped && !r.persistent && !r.finishing) {
14339 final int origSize = mLRUActivities.size();
14340 destroyActivityLocked(r, true);
14341
14342 // This will remove it from the LRU list, so keep
14343 // our index at the same value. Note that this check to
14344 // see if the size changes is just paranoia -- if
14345 // something unexpected happens, we don't want to end up
14346 // in an infinite loop.
14347 if (origSize > mLRUActivities.size()) {
14348 i--;
14349 }
14350 }
14351 }
14352 }
14353 }
14354
14355 /** This method sends the specified signal to each of the persistent apps */
14356 public void signalPersistentProcesses(int sig) throws RemoteException {
14357 if (sig != Process.SIGNAL_USR1) {
14358 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14359 }
14360
14361 synchronized (this) {
14362 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14363 != PackageManager.PERMISSION_GRANTED) {
14364 throw new SecurityException("Requires permission "
14365 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14366 }
14367
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014368 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14369 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014370 if (r.thread != null && r.persistent) {
14371 Process.sendSignal(r.pid, sig);
14372 }
14373 }
14374 }
14375 }
14376
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014377 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014378 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014379
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014380 try {
14381 synchronized (this) {
14382 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14383 // its own permission.
14384 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14385 != PackageManager.PERMISSION_GRANTED) {
14386 throw new SecurityException("Requires permission "
14387 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014388 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014389
14390 if (start && fd == null) {
14391 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014392 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014393
14394 ProcessRecord proc = null;
14395 try {
14396 int pid = Integer.parseInt(process);
14397 synchronized (mPidsSelfLocked) {
14398 proc = mPidsSelfLocked.get(pid);
14399 }
14400 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014401 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014402
14403 if (proc == null) {
14404 HashMap<String, SparseArray<ProcessRecord>> all
14405 = mProcessNames.getMap();
14406 SparseArray<ProcessRecord> procs = all.get(process);
14407 if (procs != null && procs.size() > 0) {
14408 proc = procs.valueAt(0);
14409 }
14410 }
14411
14412 if (proc == null || proc.thread == null) {
14413 throw new IllegalArgumentException("Unknown process: " + process);
14414 }
14415
14416 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14417 if (isSecure) {
14418 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14419 throw new SecurityException("Process not debuggable: " + proc);
14420 }
14421 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014422
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014423 proc.thread.profilerControl(start, path, fd);
14424 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014425 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014426 }
14427 } catch (RemoteException e) {
14428 throw new IllegalStateException("Process disappeared");
14429 } finally {
14430 if (fd != null) {
14431 try {
14432 fd.close();
14433 } catch (IOException e) {
14434 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014435 }
14436 }
14437 }
14438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014439 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14440 public void monitor() {
14441 synchronized (this) { }
14442 }
14443}