blob: 2c82d9c078d10d95a9b330d8eb9479037f0e5d22 [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 Tate181fafa2009-05-14 11:12:14 -070049import android.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020050import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080051import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.ComponentName;
53import android.content.ContentResolver;
54import android.content.Context;
55import android.content.Intent;
56import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070057import android.content.IIntentReceiver;
58import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070059import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.content.pm.ActivityInfo;
61import android.content.pm.ApplicationInfo;
62import android.content.pm.ConfigurationInfo;
63import android.content.pm.IPackageDataObserver;
64import android.content.pm.IPackageManager;
65import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080066import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070068import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.content.pm.ProviderInfo;
70import android.content.pm.ResolveInfo;
71import android.content.pm.ServiceInfo;
72import android.content.res.Configuration;
73import android.graphics.Bitmap;
74import android.net.Uri;
75import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080076import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080077import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070078import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080079import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.FileUtils;
83import android.os.Handler;
84import android.os.IBinder;
85import android.os.IPermissionController;
86import android.os.Looper;
87import android.os.Message;
88import android.os.Parcel;
89import android.os.ParcelFileDescriptor;
90import android.os.PowerManager;
91import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070092import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.os.RemoteException;
94import android.os.ServiceManager;
95import android.os.SystemClock;
96import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.util.Config;
99import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800100import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800101import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.PrintWriterPrinter;
103import android.util.SparseArray;
104import android.view.Gravity;
105import android.view.LayoutInflater;
106import android.view.View;
107import android.view.WindowManager;
108import android.view.WindowManagerPolicy;
109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import java.io.File;
111import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200113import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import java.io.PrintWriter;
115import java.lang.IllegalStateException;
116import java.lang.ref.WeakReference;
117import java.util.ArrayList;
118import java.util.HashMap;
119import java.util.HashSet;
120import java.util.Iterator;
121import java.util.List;
122import java.util.Locale;
123import java.util.Map;
124
125public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
126 static final String TAG = "ActivityManager";
127 static final boolean DEBUG = false;
128 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
129 static final boolean DEBUG_SWITCH = localLOGV || false;
130 static final boolean DEBUG_TASKS = localLOGV || false;
131 static final boolean DEBUG_PAUSE = localLOGV || false;
132 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
133 static final boolean DEBUG_TRANSITION = localLOGV || false;
134 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700135 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 static final boolean DEBUG_SERVICE = localLOGV || false;
137 static final boolean DEBUG_VISBILITY = localLOGV || false;
138 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700139 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800140 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700142 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700143 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700144 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean VALIDATE_TOKENS = false;
146 static final boolean SHOW_ACTIVITY_START_TIME = true;
147
148 // Control over CPU and battery monitoring.
149 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
150 static final boolean MONITOR_CPU_USAGE = true;
151 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
152 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
153 static final boolean MONITOR_THREAD_CPU_USAGE = false;
154
Dianne Hackborn1655be42009-05-08 14:29:01 -0700155 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700156 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 private static final String SYSTEM_SECURE = "ro.secure";
159
160 // This is the maximum number of application processes we would like
161 // to have running. Due to the asynchronous nature of things, we can
162 // temporarily go beyond this limit.
163 static final int MAX_PROCESSES = 2;
164
165 // Set to false to leave processes running indefinitely, relying on
166 // the kernel killing them as resources are required.
167 static final boolean ENFORCE_PROCESS_LIMIT = false;
168
169 // This is the maximum number of activities that we would like to have
170 // running at a given time.
171 static final int MAX_ACTIVITIES = 20;
172
173 // Maximum number of recent tasks that we can remember.
174 static final int MAX_RECENT_TASKS = 20;
175
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700176 // Amount of time after a call to stopAppSwitches() during which we will
177 // prevent further untrusted switches from happening.
178 static final long APP_SWITCH_DELAY_TIME = 5*1000;
179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 // How long until we reset a task when the user returns to it. Currently
181 // 30 minutes.
182 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
183
184 // Set to true to disable the icon that is shown while a new activity
185 // is being started.
186 static final boolean SHOW_APP_STARTING_ICON = true;
187
188 // How long we wait until giving up on the last activity to pause. This
189 // is short because it directly impacts the responsiveness of starting the
190 // next activity.
191 static final int PAUSE_TIMEOUT = 500;
192
193 /**
194 * How long we can hold the launch wake lock before giving up.
195 */
196 static final int LAUNCH_TIMEOUT = 10*1000;
197
198 // How long we wait for a launched process to attach to the activity manager
199 // before we decide it's never going to come up for real.
200 static final int PROC_START_TIMEOUT = 10*1000;
201
202 // How long we wait until giving up on the last activity telling us it
203 // is idle.
204 static final int IDLE_TIMEOUT = 10*1000;
205
206 // How long to wait after going idle before forcing apps to GC.
207 static final int GC_TIMEOUT = 5*1000;
208
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700209 // The minimum amount of time between successive GC requests for a process.
210 static final int GC_MIN_INTERVAL = 60*1000;
211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 // How long we wait until giving up on an activity telling us it has
213 // finished destroying itself.
214 static final int DESTROY_TIMEOUT = 10*1000;
215
216 // How long we allow a receiver to run before giving up on it.
217 static final int BROADCAST_TIMEOUT = 10*1000;
218
219 // How long we wait for a service to finish executing.
220 static final int SERVICE_TIMEOUT = 20*1000;
221
222 // How long a service needs to be running until restarting its process
223 // is no longer considered to be a relaunch of the service.
224 static final int SERVICE_RESTART_DURATION = 5*1000;
225
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700226 // How long a service needs to be running until it will start back at
227 // SERVICE_RESTART_DURATION after being killed.
228 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
229
230 // Multiplying factor to increase restart duration time by, for each time
231 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
232 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
233
234 // The minimum amount of time between restarting services that we allow.
235 // That is, when multiple services are restarting, we won't allow each
236 // to restart less than this amount of time from the last one.
237 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 // Maximum amount of time for there to be no activity on a service before
240 // we consider it non-essential and allow its process to go on the
241 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700242 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243
244 // How long we wait until we timeout on key dispatching.
245 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
246
247 // The minimum time we allow between crashes, for us to consider this
248 // application to be bad and stop and its services and reject broadcasts.
249 static final int MIN_CRASH_INTERVAL = 60*1000;
250
251 // How long we wait until we timeout on key dispatching during instrumentation.
252 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
253
254 // OOM adjustments for processes in various states:
255
256 // This is a process without anything currently running in it. Definitely
257 // the first to go! Value set in system/rootdir/init.rc on startup.
258 // This value is initalized in the constructor, careful when refering to
259 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800260 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261
262 // This is a process only hosting activities that are not visible,
263 // so it can be killed without any disruption. Value set in
264 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800265 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 static int HIDDEN_APP_MIN_ADJ;
267
The Android Open Source Project4df24232009-03-05 14:34:35 -0800268 // This is a process holding the home application -- we want to try
269 // avoiding killing it, even if it would normally be in the background,
270 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800271 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800272
Christopher Tate6fa95972009-06-05 18:43:55 -0700273 // This is a process currently hosting a backup operation. Killing it
274 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 // This is a process holding a secondary server -- killing it will not
278 // have much of an impact as far as the user is concerned. Value set in
279 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800280 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281
282 // This is a process only hosting activities that are visible to the
283 // user, so we'd prefer they don't disappear. Value set in
284 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800285 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286
287 // This is the process running the current foreground app. We'd really
288 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
291 // This is a process running a core server, such as telephony. Definitely
292 // don't want to kill it, but doing so is not completely fatal.
293 static final int CORE_SERVER_ADJ = -12;
294
295 // The system process runs at the default adjustment.
296 static final int SYSTEM_ADJ = -16;
297
298 // Memory pages are 4K.
299 static final int PAGE_SIZE = 4*1024;
300
301 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800302 static final int EMPTY_APP_MEM;
303 static final int HIDDEN_APP_MEM;
304 static final int HOME_APP_MEM;
305 static final int BACKUP_APP_MEM;
306 static final int SECONDARY_SERVER_MEM;
307 static final int VISIBLE_APP_MEM;
308 static final int FOREGROUND_APP_MEM;
309
310 // The minimum number of hidden apps we want to be able to keep around,
311 // without empty apps being able to push them out of memory.
312 static final int MIN_HIDDEN_APPS = 2;
313
314 // We put empty content processes after any hidden processes that have
315 // been idle for less than 30 seconds.
316 static final long CONTENT_APP_IDLE_OFFSET = 30*1000;
317
318 // We put empty content processes after any hidden processes that have
319 // been idle for less than 60 seconds.
320 static final long EMPTY_APP_IDLE_OFFSET = 60*1000;
321
322 static {
323 // These values are set in system/rootdir/init.rc on startup.
324 FOREGROUND_APP_ADJ =
325 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
326 VISIBLE_APP_ADJ =
327 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
328 SECONDARY_SERVER_ADJ =
329 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
330 BACKUP_APP_ADJ =
331 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
332 HOME_APP_ADJ =
333 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
334 HIDDEN_APP_MIN_ADJ =
335 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
336 EMPTY_APP_ADJ =
337 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
338 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
339 FOREGROUND_APP_MEM =
340 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
341 VISIBLE_APP_MEM =
342 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
343 SECONDARY_SERVER_MEM =
344 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
345 BACKUP_APP_MEM =
346 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
347 HOME_APP_MEM =
348 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
349 HIDDEN_APP_MEM =
350 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
351 EMPTY_APP_MEM =
352 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354
Dan Egnor42471dd2010-01-07 17:25:22 -0800355 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356
357 static final String[] EMPTY_STRING_ARRAY = new String[0];
358
359 enum ActivityState {
360 INITIALIZING,
361 RESUMED,
362 PAUSING,
363 PAUSED,
364 STOPPING,
365 STOPPED,
366 FINISHING,
367 DESTROYING,
368 DESTROYED
369 }
370
371 /**
372 * The back history of all previous (and possibly still
373 * running) activities. It contains HistoryRecord objects.
374 */
375 final ArrayList mHistory = new ArrayList();
376
377 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700378 * Description of a request to start a new activity, which has been held
379 * due to app switches being disabled.
380 */
381 class PendingActivityLaunch {
382 HistoryRecord r;
383 HistoryRecord sourceRecord;
384 Uri[] grantedUriPermissions;
385 int grantedMode;
386 boolean onlyIfNeeded;
387 }
388
389 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
390 = new ArrayList<PendingActivityLaunch>();
391
392 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800393 * List of people waiting to find out about the next launched activity.
394 */
395 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
396 = new ArrayList<IActivityManager.WaitResult>();
397
398 /**
399 * List of people waiting to find out about the next visible activity.
400 */
401 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
402 = new ArrayList<IActivityManager.WaitResult>();
403
404 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 * List of all active broadcasts that are to be executed immediately
406 * (without waiting for another broadcast to finish). Currently this only
407 * contains broadcasts to registered receivers, to avoid spinning up
408 * a bunch of processes to execute IntentReceiver components.
409 */
410 final ArrayList<BroadcastRecord> mParallelBroadcasts
411 = new ArrayList<BroadcastRecord>();
412
413 /**
414 * List of all active broadcasts that are to be executed one at a time.
415 * The object at the top of the list is the currently activity broadcasts;
416 * those after it are waiting for the top to finish..
417 */
418 final ArrayList<BroadcastRecord> mOrderedBroadcasts
419 = new ArrayList<BroadcastRecord>();
420
421 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800422 * Historical data of past broadcasts, for debugging.
423 */
424 static final int MAX_BROADCAST_HISTORY = 100;
425 final BroadcastRecord[] mBroadcastHistory
426 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
427
428 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 * Set when we current have a BROADCAST_INTENT_MSG in flight.
430 */
431 boolean mBroadcastsScheduled = false;
432
433 /**
434 * Set to indicate whether to issue an onUserLeaving callback when a
435 * newly launched activity is being brought in front of us.
436 */
437 boolean mUserLeaving = false;
438
439 /**
440 * When we are in the process of pausing an activity, before starting the
441 * next one, this variable holds the activity that is currently being paused.
442 */
443 HistoryRecord mPausingActivity = null;
444
445 /**
446 * Current activity that is resumed, or null if there is none.
447 */
448 HistoryRecord mResumedActivity = null;
449
450 /**
451 * Activity we have told the window manager to have key focus.
452 */
453 HistoryRecord mFocusedActivity = null;
454
455 /**
456 * This is the last activity that we put into the paused state. This is
457 * used to determine if we need to do an activity transition while sleeping,
458 * when we normally hold the top activity paused.
459 */
460 HistoryRecord mLastPausedActivity = null;
461
462 /**
463 * List of activities that are waiting for a new activity
464 * to become visible before completing whatever operation they are
465 * supposed to do.
466 */
467 final ArrayList mWaitingVisibleActivities = new ArrayList();
468
469 /**
470 * List of activities that are ready to be stopped, but waiting
471 * for the next activity to settle down before doing so. It contains
472 * HistoryRecord objects.
473 */
474 final ArrayList<HistoryRecord> mStoppingActivities
475 = new ArrayList<HistoryRecord>();
476
477 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700478 * Animations that for the current transition have requested not to
479 * be considered for the transition animation.
480 */
481 final ArrayList<HistoryRecord> mNoAnimActivities
482 = new ArrayList<HistoryRecord>();
483
484 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 * List of intents that were used to start the most recent tasks.
486 */
487 final ArrayList<TaskRecord> mRecentTasks
488 = new ArrayList<TaskRecord>();
489
490 /**
491 * List of activities that are ready to be finished, but waiting
492 * for the previous activity to settle down before doing so. It contains
493 * HistoryRecord objects.
494 */
495 final ArrayList mFinishingActivities = new ArrayList();
496
497 /**
498 * All of the applications we currently have running organized by name.
499 * The keys are strings of the application package name (as
500 * returned by the package manager), and the keys are ApplicationRecord
501 * objects.
502 */
503 final ProcessMap<ProcessRecord> mProcessNames
504 = new ProcessMap<ProcessRecord>();
505
506 /**
507 * The last time that various processes have crashed.
508 */
509 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
510
511 /**
512 * Set of applications that we consider to be bad, and will reject
513 * incoming broadcasts from (which the user has no control over).
514 * Processes are added to this set when they have crashed twice within
515 * a minimum amount of time; they are removed from it when they are
516 * later restarted (hopefully due to some user action). The value is the
517 * time it was added to the list.
518 */
519 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
520
521 /**
522 * All of the processes we currently have running organized by pid.
523 * The keys are the pid running the application.
524 *
525 * <p>NOTE: This object is protected by its own lock, NOT the global
526 * activity manager lock!
527 */
528 final SparseArray<ProcessRecord> mPidsSelfLocked
529 = new SparseArray<ProcessRecord>();
530
531 /**
532 * All of the processes that have been forced to be foreground. The key
533 * is the pid of the caller who requested it (we hold a death
534 * link on it).
535 */
536 abstract class ForegroundToken implements IBinder.DeathRecipient {
537 int pid;
538 IBinder token;
539 }
540 final SparseArray<ForegroundToken> mForegroundProcesses
541 = new SparseArray<ForegroundToken>();
542
543 /**
544 * List of records for processes that someone had tried to start before the
545 * system was ready. We don't start them at that point, but ensure they
546 * are started by the time booting is complete.
547 */
548 final ArrayList<ProcessRecord> mProcessesOnHold
549 = new ArrayList<ProcessRecord>();
550
551 /**
552 * List of records for processes that we have started and are waiting
553 * for them to call back. This is really only needed when running in
554 * single processes mode, in which case we do not have a unique pid for
555 * each process.
556 */
557 final ArrayList<ProcessRecord> mStartingProcesses
558 = new ArrayList<ProcessRecord>();
559
560 /**
561 * List of persistent applications that are in the process
562 * of being started.
563 */
564 final ArrayList<ProcessRecord> mPersistentStartingProcesses
565 = new ArrayList<ProcessRecord>();
566
567 /**
568 * Processes that are being forcibly torn down.
569 */
570 final ArrayList<ProcessRecord> mRemovedProcesses
571 = new ArrayList<ProcessRecord>();
572
573 /**
574 * List of running applications, sorted by recent usage.
575 * The first entry in the list is the least recently used.
576 * It contains ApplicationRecord objects. This list does NOT include
577 * any persistent application records (since we never want to exit them).
578 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800579 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 = new ArrayList<ProcessRecord>();
581
582 /**
583 * List of processes that should gc as soon as things are idle.
584 */
585 final ArrayList<ProcessRecord> mProcessesToGc
586 = new ArrayList<ProcessRecord>();
587
588 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800589 * This is the process holding what we currently consider to be
590 * the "home" activity.
591 */
592 private ProcessRecord mHomeProcess;
593
594 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 * List of running activities, sorted by recent usage.
596 * The first entry in the list is the least recently used.
597 * It contains HistoryRecord objects.
598 */
599 private final ArrayList mLRUActivities = new ArrayList();
600
601 /**
602 * Set of PendingResultRecord objects that are currently active.
603 */
604 final HashSet mPendingResultRecords = new HashSet();
605
606 /**
607 * Set of IntentSenderRecord objects that are currently active.
608 */
609 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
610 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
611
612 /**
613 * Intent broadcast that we have tried to start, but are
614 * waiting for its application's process to be created. We only
615 * need one (instead of a list) because we always process broadcasts
616 * one at a time, so no others can be started while waiting for this
617 * one.
618 */
619 BroadcastRecord mPendingBroadcast = null;
620
621 /**
622 * Keeps track of all IIntentReceivers that have been registered for
623 * broadcasts. Hash keys are the receiver IBinder, hash value is
624 * a ReceiverList.
625 */
626 final HashMap mRegisteredReceivers = new HashMap();
627
628 /**
629 * Resolver for broadcast intents to registered receivers.
630 * Holds BroadcastFilter (subclass of IntentFilter).
631 */
632 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
633 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
634 @Override
635 protected boolean allowFilterResult(
636 BroadcastFilter filter, List<BroadcastFilter> dest) {
637 IBinder target = filter.receiverList.receiver.asBinder();
638 for (int i=dest.size()-1; i>=0; i--) {
639 if (dest.get(i).receiverList.receiver.asBinder() == target) {
640 return false;
641 }
642 }
643 return true;
644 }
645 };
646
647 /**
648 * State of all active sticky broadcasts. Keys are the action of the
649 * sticky Intent, values are an ArrayList of all broadcasted intents with
650 * that action (which should usually be one).
651 */
652 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
653 new HashMap<String, ArrayList<Intent>>();
654
655 /**
656 * All currently running services.
657 */
658 final HashMap<ComponentName, ServiceRecord> mServices =
659 new HashMap<ComponentName, ServiceRecord>();
660
661 /**
662 * All currently running services indexed by the Intent used to start them.
663 */
664 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
665 new HashMap<Intent.FilterComparison, ServiceRecord>();
666
667 /**
668 * All currently bound service connections. Keys are the IBinder of
669 * the client's IServiceConnection.
670 */
671 final HashMap<IBinder, ConnectionRecord> mServiceConnections
672 = new HashMap<IBinder, ConnectionRecord>();
673
674 /**
675 * List of services that we have been asked to start,
676 * but haven't yet been able to. It is used to hold start requests
677 * while waiting for their corresponding application thread to get
678 * going.
679 */
680 final ArrayList<ServiceRecord> mPendingServices
681 = new ArrayList<ServiceRecord>();
682
683 /**
684 * List of services that are scheduled to restart following a crash.
685 */
686 final ArrayList<ServiceRecord> mRestartingServices
687 = new ArrayList<ServiceRecord>();
688
689 /**
690 * List of services that are in the process of being stopped.
691 */
692 final ArrayList<ServiceRecord> mStoppingServices
693 = new ArrayList<ServiceRecord>();
694
695 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700696 * Backup/restore process management
697 */
698 String mBackupAppName = null;
699 BackupRecord mBackupTarget = null;
700
701 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 * List of PendingThumbnailsRecord objects of clients who are still
703 * waiting to receive all of the thumbnails for a task.
704 */
705 final ArrayList mPendingThumbnails = new ArrayList();
706
707 /**
708 * List of HistoryRecord objects that have been finished and must
709 * still report back to a pending thumbnail receiver.
710 */
711 final ArrayList mCancelledThumbnails = new ArrayList();
712
713 /**
714 * All of the currently running global content providers. Keys are a
715 * string containing the provider name and values are a
716 * ContentProviderRecord object containing the data about it. Note
717 * that a single provider may be published under multiple names, so
718 * there may be multiple entries here for a single one in mProvidersByClass.
719 */
720 final HashMap mProvidersByName = new HashMap();
721
722 /**
723 * All of the currently running global content providers. Keys are a
724 * string containing the provider's implementation class and values are a
725 * ContentProviderRecord object containing the data about it.
726 */
727 final HashMap mProvidersByClass = new HashMap();
728
729 /**
730 * List of content providers who have clients waiting for them. The
731 * application is currently being launched and the provider will be
732 * removed from this list once it is published.
733 */
734 final ArrayList mLaunchingProviders = new ArrayList();
735
736 /**
737 * Global set of specific Uri permissions that have been granted.
738 */
739 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
740 = new SparseArray<HashMap<Uri, UriPermission>>();
741
742 /**
743 * Thread-local storage used to carry caller permissions over through
744 * indirect content-provider access.
745 * @see #ActivityManagerService.openContentUri()
746 */
747 private class Identity {
748 public int pid;
749 public int uid;
750
751 Identity(int _pid, int _uid) {
752 pid = _pid;
753 uid = _uid;
754 }
755 }
756 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
757
758 /**
759 * All information we have collected about the runtime performance of
760 * any user id that can impact battery performance.
761 */
762 final BatteryStatsService mBatteryStatsService;
763
764 /**
765 * information about component usage
766 */
767 final UsageStatsService mUsageStatsService;
768
769 /**
770 * Current configuration information. HistoryRecord objects are given
771 * a reference to this object to indicate which configuration they are
772 * currently running in, so this object must be kept immutable.
773 */
774 Configuration mConfiguration = new Configuration();
775
776 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800777 * Current sequencing integer of the configuration, for skipping old
778 * configurations.
779 */
780 int mConfigurationSeq = 0;
781
782 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700783 * Hardware-reported OpenGLES version.
784 */
785 final int GL_ES_VERSION;
786
787 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 * List of initialization arguments to pass to all processes when binding applications to them.
789 * For example, references to the commonly used services.
790 */
791 HashMap<String, IBinder> mAppBindArgs;
792
793 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700794 * Temporary to avoid allocations. Protected by main lock.
795 */
796 final StringBuilder mStringBuilder = new StringBuilder(256);
797
798 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 * Used to control how we initialize the service.
800 */
801 boolean mStartRunning = false;
802 ComponentName mTopComponent;
803 String mTopAction;
804 String mTopData;
805 boolean mSystemReady = false;
806 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700807 boolean mWaitingUpdate = false;
808 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809
810 Context mContext;
811
812 int mFactoryTest;
813
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700814 boolean mCheckedForSetup;
815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700817 * The time at which we will allow normal application switches again,
818 * after a call to {@link #stopAppSwitches()}.
819 */
820 long mAppSwitchesAllowedTime;
821
822 /**
823 * This is set to true after the first switch after mAppSwitchesAllowedTime
824 * is set; any switches after that will clear the time.
825 */
826 boolean mDidAppSwitch;
827
828 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 * Set while we are wanting to sleep, to prevent any
830 * activities from being started/resumed.
831 */
832 boolean mSleeping = false;
833
834 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700835 * Set if we are shutting down the system, similar to sleeping.
836 */
837 boolean mShuttingDown = false;
838
839 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 * Set when the system is going to sleep, until we have
841 * successfully paused the current activity and released our wake lock.
842 * At that point the system is allowed to actually sleep.
843 */
844 PowerManager.WakeLock mGoingToSleep;
845
846 /**
847 * We don't want to allow the device to go to sleep while in the process
848 * of launching an activity. This is primarily to allow alarm intent
849 * receivers to launch an activity and get that to run before the device
850 * goes back to sleep.
851 */
852 PowerManager.WakeLock mLaunchingActivity;
853
854 /**
855 * Task identifier that activities are currently being started
856 * in. Incremented each time a new task is created.
857 * todo: Replace this with a TokenSpace class that generates non-repeating
858 * integers that won't wrap.
859 */
860 int mCurTask = 1;
861
862 /**
863 * Current sequence id for oom_adj computation traversal.
864 */
865 int mAdjSeq = 0;
866
867 /**
868 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
869 * is set, indicating the user wants processes started in such a way
870 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
871 * running in each process (thus no pre-initialized process, etc).
872 */
873 boolean mSimpleProcessManagement = false;
874
875 /**
876 * System monitoring: number of processes that died since the last
877 * N procs were started.
878 */
879 int[] mProcDeaths = new int[20];
880
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700881 /**
882 * This is set if we had to do a delayed dexopt of an app before launching
883 * it, to increasing the ANR timeouts in that case.
884 */
885 boolean mDidDexOpt;
886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 String mDebugApp = null;
888 boolean mWaitForDebugger = false;
889 boolean mDebugTransient = false;
890 String mOrigDebugApp = null;
891 boolean mOrigWaitForDebugger = false;
892 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700893 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700895 final RemoteCallbackList<IActivityWatcher> mWatchers
896 = new RemoteCallbackList<IActivityWatcher>();
897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 /**
899 * Callback of last caller to {@link #requestPss}.
900 */
901 Runnable mRequestPssCallback;
902
903 /**
904 * Remaining processes for which we are waiting results from the last
905 * call to {@link #requestPss}.
906 */
907 final ArrayList<ProcessRecord> mRequestPssList
908 = new ArrayList<ProcessRecord>();
909
910 /**
911 * Runtime statistics collection thread. This object's lock is used to
912 * protect all related state.
913 */
914 final Thread mProcessStatsThread;
915
916 /**
917 * Used to collect process stats when showing not responding dialog.
918 * Protected by mProcessStatsThread.
919 */
920 final ProcessStats mProcessStats = new ProcessStats(
921 MONITOR_THREAD_CPU_USAGE);
922 long mLastCpuTime = 0;
923 long mLastWriteTime = 0;
924
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700925 long mInitialStartTime = 0;
926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 /**
928 * Set to true after the system has finished booting.
929 */
930 boolean mBooted = false;
931
932 int mProcessLimit = 0;
933
934 WindowManagerService mWindowManager;
935
936 static ActivityManagerService mSelf;
937 static ActivityThread mSystemThread;
938
939 private final class AppDeathRecipient implements IBinder.DeathRecipient {
940 final ProcessRecord mApp;
941 final int mPid;
942 final IApplicationThread mAppThread;
943
944 AppDeathRecipient(ProcessRecord app, int pid,
945 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800946 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 TAG, "New death recipient " + this
948 + " for thread " + thread.asBinder());
949 mApp = app;
950 mPid = pid;
951 mAppThread = thread;
952 }
953
954 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800955 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 TAG, "Death received in " + this
957 + " for thread " + mAppThread.asBinder());
958 removeRequestedPss(mApp);
959 synchronized(ActivityManagerService.this) {
960 appDiedLocked(mApp, mPid, mAppThread);
961 }
962 }
963 }
964
965 static final int SHOW_ERROR_MSG = 1;
966 static final int SHOW_NOT_RESPONDING_MSG = 2;
967 static final int SHOW_FACTORY_ERROR_MSG = 3;
968 static final int UPDATE_CONFIGURATION_MSG = 4;
969 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
970 static final int WAIT_FOR_DEBUGGER_MSG = 6;
971 static final int BROADCAST_INTENT_MSG = 7;
972 static final int BROADCAST_TIMEOUT_MSG = 8;
973 static final int PAUSE_TIMEOUT_MSG = 9;
974 static final int IDLE_TIMEOUT_MSG = 10;
975 static final int IDLE_NOW_MSG = 11;
976 static final int SERVICE_TIMEOUT_MSG = 12;
977 static final int UPDATE_TIME_ZONE = 13;
978 static final int SHOW_UID_ERROR_MSG = 14;
979 static final int IM_FEELING_LUCKY_MSG = 15;
980 static final int LAUNCH_TIMEOUT_MSG = 16;
981 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 static final int RESUME_TOP_ACTIVITY_MSG = 19;
983 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700984 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700985 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800986 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987
988 AlertDialog mUidAlert;
989
990 final Handler mHandler = new Handler() {
991 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800992 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 //}
994
995 public void handleMessage(Message msg) {
996 switch (msg.what) {
997 case SHOW_ERROR_MSG: {
998 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 synchronized (ActivityManagerService.this) {
1000 ProcessRecord proc = (ProcessRecord)data.get("app");
1001 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001002 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 return;
1004 }
1005 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001006 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001007 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001008 d.show();
1009 proc.crashDialog = d;
1010 } else {
1011 // The device is asleep, so just pretend that the user
1012 // saw a crash dialog and hit "force quit".
1013 res.set(0);
1014 }
1015 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001016
1017 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } break;
1019 case SHOW_NOT_RESPONDING_MSG: {
1020 synchronized (ActivityManagerService.this) {
1021 HashMap data = (HashMap) msg.obj;
1022 ProcessRecord proc = (ProcessRecord)data.get("app");
1023 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001024 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 return;
1026 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001027
1028 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1029 null, null, 0, null, null, null,
1030 false, false, MY_PID, Process.SYSTEM_UID);
1031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1033 mContext, proc, (HistoryRecord)data.get("activity"));
1034 d.show();
1035 proc.anrDialog = d;
1036 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001037
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001038 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 } break;
1040 case SHOW_FACTORY_ERROR_MSG: {
1041 Dialog d = new FactoryErrorDialog(
1042 mContext, msg.getData().getCharSequence("msg"));
1043 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001044 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 } break;
1046 case UPDATE_CONFIGURATION_MSG: {
1047 final ContentResolver resolver = mContext.getContentResolver();
1048 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1049 } break;
1050 case GC_BACKGROUND_PROCESSES_MSG: {
1051 synchronized (ActivityManagerService.this) {
1052 performAppGcsIfAppropriateLocked();
1053 }
1054 } break;
1055 case WAIT_FOR_DEBUGGER_MSG: {
1056 synchronized (ActivityManagerService.this) {
1057 ProcessRecord app = (ProcessRecord)msg.obj;
1058 if (msg.arg1 != 0) {
1059 if (!app.waitedForDebugger) {
1060 Dialog d = new AppWaitingForDebuggerDialog(
1061 ActivityManagerService.this,
1062 mContext, app);
1063 app.waitDialog = d;
1064 app.waitedForDebugger = true;
1065 d.show();
1066 }
1067 } else {
1068 if (app.waitDialog != null) {
1069 app.waitDialog.dismiss();
1070 app.waitDialog = null;
1071 }
1072 }
1073 }
1074 } break;
1075 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001076 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 TAG, "Received BROADCAST_INTENT_MSG");
1078 processNextBroadcast(true);
1079 } break;
1080 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001081 if (mDidDexOpt) {
1082 mDidDexOpt = false;
1083 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1084 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1085 return;
1086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 broadcastTimeout();
1088 } break;
1089 case PAUSE_TIMEOUT_MSG: {
1090 IBinder token = (IBinder)msg.obj;
1091 // We don't at this point know if the activity is fullscreen,
1092 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001093 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 activityPaused(token, null, true);
1095 } break;
1096 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001097 if (mDidDexOpt) {
1098 mDidDexOpt = false;
1099 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1100 nmsg.obj = msg.obj;
1101 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1102 return;
1103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 // We don't at this point know if the activity is fullscreen,
1105 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001106 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001107 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001108 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 } break;
1110 case DESTROY_TIMEOUT_MSG: {
1111 IBinder token = (IBinder)msg.obj;
1112 // We don't at this point know if the activity is fullscreen,
1113 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001114 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 activityDestroyed(token);
1116 } break;
1117 case IDLE_NOW_MSG: {
1118 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001119 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 } break;
1121 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001122 if (mDidDexOpt) {
1123 mDidDexOpt = false;
1124 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1125 nmsg.obj = msg.obj;
1126 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1127 return;
1128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 serviceTimeout((ProcessRecord)msg.obj);
1130 } break;
1131 case UPDATE_TIME_ZONE: {
1132 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001133 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1134 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 if (r.thread != null) {
1136 try {
1137 r.thread.updateTimeZone();
1138 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001139 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 }
1141 }
1142 }
1143 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001144 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 case SHOW_UID_ERROR_MSG: {
1146 // XXX This is a temporary dialog, no need to localize.
1147 AlertDialog d = new BaseErrorDialog(mContext);
1148 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1149 d.setCancelable(false);
1150 d.setTitle("System UIDs Inconsistent");
1151 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1152 d.setButton("I'm Feeling Lucky",
1153 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1154 mUidAlert = d;
1155 d.show();
1156 } break;
1157 case IM_FEELING_LUCKY_MSG: {
1158 if (mUidAlert != null) {
1159 mUidAlert.dismiss();
1160 mUidAlert = null;
1161 }
1162 } break;
1163 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001164 if (mDidDexOpt) {
1165 mDidDexOpt = false;
1166 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1167 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1168 return;
1169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 synchronized (ActivityManagerService.this) {
1171 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001172 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 mLaunchingActivity.release();
1174 }
1175 }
1176 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 case RESUME_TOP_ACTIVITY_MSG: {
1178 synchronized (ActivityManagerService.this) {
1179 resumeTopActivityLocked(null);
1180 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001181 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001183 if (mDidDexOpt) {
1184 mDidDexOpt = false;
1185 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1186 nmsg.obj = msg.obj;
1187 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1188 return;
1189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 ProcessRecord app = (ProcessRecord)msg.obj;
1191 synchronized (ActivityManagerService.this) {
1192 processStartTimedOutLocked(app);
1193 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001194 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001195 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1196 synchronized (ActivityManagerService.this) {
1197 doPendingActivityLaunchesLocked(true);
1198 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001199 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001200 case KILL_APPLICATION_MSG: {
1201 synchronized (ActivityManagerService.this) {
1202 int uid = msg.arg1;
1203 boolean restart = (msg.arg2 == 1);
1204 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001205 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001206 }
1207 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001208 case FINALIZE_PENDING_INTENT_MSG: {
1209 ((PendingIntentRecord)msg.obj).completeFinalize();
1210 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 }
1212 }
1213 };
1214
1215 public static void setSystemProcess() {
1216 try {
1217 ActivityManagerService m = mSelf;
1218
1219 ServiceManager.addService("activity", m);
1220 ServiceManager.addService("meminfo", new MemBinder(m));
1221 if (MONITOR_CPU_USAGE) {
1222 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 ServiceManager.addService("permission", new PermissionController(m));
1225
1226 ApplicationInfo info =
1227 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001228 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001229 mSystemThread.installSystemApplicationInfo(info);
1230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 synchronized (mSelf) {
1232 ProcessRecord app = mSelf.newProcessRecordLocked(
1233 mSystemThread.getApplicationThread(), info,
1234 info.processName);
1235 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001236 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 app.maxAdj = SYSTEM_ADJ;
1238 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1239 synchronized (mSelf.mPidsSelfLocked) {
1240 mSelf.mPidsSelfLocked.put(app.pid, app);
1241 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001242 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 }
1244 } catch (PackageManager.NameNotFoundException e) {
1245 throw new RuntimeException(
1246 "Unable to find android system package", e);
1247 }
1248 }
1249
1250 public void setWindowManager(WindowManagerService wm) {
1251 mWindowManager = wm;
1252 }
1253
1254 public static final Context main(int factoryTest) {
1255 AThread thr = new AThread();
1256 thr.start();
1257
1258 synchronized (thr) {
1259 while (thr.mService == null) {
1260 try {
1261 thr.wait();
1262 } catch (InterruptedException e) {
1263 }
1264 }
1265 }
1266
1267 ActivityManagerService m = thr.mService;
1268 mSelf = m;
1269 ActivityThread at = ActivityThread.systemMain();
1270 mSystemThread = at;
1271 Context context = at.getSystemContext();
1272 m.mContext = context;
1273 m.mFactoryTest = factoryTest;
1274 PowerManager pm =
1275 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1276 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1277 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1278 m.mLaunchingActivity.setReferenceCounted(false);
1279
1280 m.mBatteryStatsService.publish(context);
1281 m.mUsageStatsService.publish(context);
1282
1283 synchronized (thr) {
1284 thr.mReady = true;
1285 thr.notifyAll();
1286 }
1287
1288 m.startRunning(null, null, null, null);
1289
1290 return context;
1291 }
1292
1293 public static ActivityManagerService self() {
1294 return mSelf;
1295 }
1296
1297 static class AThread extends Thread {
1298 ActivityManagerService mService;
1299 boolean mReady = false;
1300
1301 public AThread() {
1302 super("ActivityManager");
1303 }
1304
1305 public void run() {
1306 Looper.prepare();
1307
1308 android.os.Process.setThreadPriority(
1309 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1310
1311 ActivityManagerService m = new ActivityManagerService();
1312
1313 synchronized (this) {
1314 mService = m;
1315 notifyAll();
1316 }
1317
1318 synchronized (this) {
1319 while (!mReady) {
1320 try {
1321 wait();
1322 } catch (InterruptedException e) {
1323 }
1324 }
1325 }
1326
1327 Looper.loop();
1328 }
1329 }
1330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 static class MemBinder extends Binder {
1332 ActivityManagerService mActivityManagerService;
1333 MemBinder(ActivityManagerService activityManagerService) {
1334 mActivityManagerService = activityManagerService;
1335 }
1336
1337 @Override
1338 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1339 ActivityManagerService service = mActivityManagerService;
1340 ArrayList<ProcessRecord> procs;
1341 synchronized (mActivityManagerService) {
1342 if (args != null && args.length > 0
1343 && args[0].charAt(0) != '-') {
1344 procs = new ArrayList<ProcessRecord>();
1345 int pid = -1;
1346 try {
1347 pid = Integer.parseInt(args[0]);
1348 } catch (NumberFormatException e) {
1349
1350 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001351 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1352 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 if (proc.pid == pid) {
1354 procs.add(proc);
1355 } else if (proc.processName.equals(args[0])) {
1356 procs.add(proc);
1357 }
1358 }
1359 if (procs.size() <= 0) {
1360 pw.println("No process found for: " + args[0]);
1361 return;
1362 }
1363 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001364 procs = service.mLruProcesses;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 }
1366 }
1367 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1368 }
1369 }
1370
1371 static class CpuBinder extends Binder {
1372 ActivityManagerService mActivityManagerService;
1373 CpuBinder(ActivityManagerService activityManagerService) {
1374 mActivityManagerService = activityManagerService;
1375 }
1376
1377 @Override
1378 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1379 synchronized (mActivityManagerService.mProcessStatsThread) {
1380 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1381 }
1382 }
1383 }
1384
1385 private ActivityManagerService() {
1386 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1387 if (v != null && Integer.getInteger(v) != 0) {
1388 mSimpleProcessManagement = true;
1389 }
1390 v = System.getenv("ANDROID_DEBUG_APP");
1391 if (v != null) {
1392 mSimpleProcessManagement = true;
1393 }
1394
Joe Onorato8a9b2202010-02-26 18:56:32 -08001395 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 File dataDir = Environment.getDataDirectory();
1398 File systemDir = new File(dataDir, "system");
1399 systemDir.mkdirs();
1400 mBatteryStatsService = new BatteryStatsService(new File(
1401 systemDir, "batterystats.bin").toString());
1402 mBatteryStatsService.getActiveStatistics().readLocked();
1403 mBatteryStatsService.getActiveStatistics().writeLocked();
1404
1405 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001406 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407
Jack Palevichb90d28c2009-07-22 15:35:24 -07001408 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1409 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1410
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001411 mConfiguration.setToDefaults();
1412 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 mProcessStats.init();
1414
1415 // Add ourself to the Watchdog monitors.
1416 Watchdog.getInstance().addMonitor(this);
1417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 mProcessStatsThread = new Thread("ProcessStats") {
1419 public void run() {
1420 while (true) {
1421 try {
1422 try {
1423 synchronized(this) {
1424 final long now = SystemClock.uptimeMillis();
1425 long nextCpuDelay = (mLastCpuTime+MONITOR_CPU_MAX_TIME)-now;
1426 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001427 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 // + ", write delay=" + nextWriteDelay);
1429 if (nextWriteDelay < nextCpuDelay) {
1430 nextCpuDelay = nextWriteDelay;
1431 }
1432 if (nextCpuDelay > 0) {
1433 this.wait(nextCpuDelay);
1434 }
1435 }
1436 } catch (InterruptedException e) {
1437 }
1438
1439 updateCpuStatsNow();
1440 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001441 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 }
1443 }
1444 }
1445 };
1446 mProcessStatsThread.start();
1447 }
1448
1449 @Override
1450 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1451 throws RemoteException {
1452 try {
1453 return super.onTransact(code, data, reply, flags);
1454 } catch (RuntimeException e) {
1455 // The activity manager only throws security exceptions, so let's
1456 // log all others.
1457 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001458 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 }
1460 throw e;
1461 }
1462 }
1463
1464 void updateCpuStats() {
1465 synchronized (mProcessStatsThread) {
1466 final long now = SystemClock.uptimeMillis();
1467 if (mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1468 mProcessStatsThread.notify();
1469 }
1470 }
1471 }
1472
1473 void updateCpuStatsNow() {
1474 synchronized (mProcessStatsThread) {
1475 final long now = SystemClock.uptimeMillis();
1476 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 if (MONITOR_CPU_USAGE &&
1479 mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
1480 mLastCpuTime = now;
1481 haveNewCpuStats = true;
1482 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001483 //Slog.i(TAG, mProcessStats.printCurrentState());
1484 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 // + mProcessStats.getTotalCpuPercent() + "%");
1486
Joe Onorato8a9b2202010-02-26 18:56:32 -08001487 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 if ("true".equals(SystemProperties.get("events.cpu"))) {
1489 int user = mProcessStats.getLastUserTime();
1490 int system = mProcessStats.getLastSystemTime();
1491 int iowait = mProcessStats.getLastIoWaitTime();
1492 int irq = mProcessStats.getLastIrqTime();
1493 int softIrq = mProcessStats.getLastSoftIrqTime();
1494 int idle = mProcessStats.getLastIdleTime();
1495
1496 int total = user + system + iowait + irq + softIrq + idle;
1497 if (total == 0) total = 1;
1498
Doug Zongker2bec3d42009-12-04 12:52:44 -08001499 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 ((user+system+iowait+irq+softIrq) * 100) / total,
1501 (user * 100) / total,
1502 (system * 100) / total,
1503 (iowait * 100) / total,
1504 (irq * 100) / total,
1505 (softIrq * 100) / total);
1506 }
1507 }
1508
Amith Yamasanie43530a2009-08-21 13:11:37 -07001509 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001510 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001511 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 synchronized(mPidsSelfLocked) {
1513 if (haveNewCpuStats) {
1514 if (mBatteryStatsService.isOnBattery()) {
1515 final int N = mProcessStats.countWorkingStats();
1516 for (int i=0; i<N; i++) {
1517 ProcessStats.Stats st
1518 = mProcessStats.getWorkingStats(i);
1519 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1520 if (pr != null) {
1521 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1522 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001523 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001524 } else {
1525 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001526 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001527 if (ps != null) {
1528 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001529 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 }
1532 }
1533 }
1534 }
1535 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1538 mLastWriteTime = now;
1539 mBatteryStatsService.getActiveStatistics().writeLocked();
1540 }
1541 }
1542 }
1543 }
1544
1545 /**
1546 * Initialize the application bind args. These are passed to each
1547 * process when the bindApplication() IPC is sent to the process. They're
1548 * lazily setup to make sure the services are running when they're asked for.
1549 */
1550 private HashMap<String, IBinder> getCommonServicesLocked() {
1551 if (mAppBindArgs == null) {
1552 mAppBindArgs = new HashMap<String, IBinder>();
1553
1554 // Setup the application init args
1555 mAppBindArgs.put("package", ServiceManager.getService("package"));
1556 mAppBindArgs.put("window", ServiceManager.getService("window"));
1557 mAppBindArgs.put(Context.ALARM_SERVICE,
1558 ServiceManager.getService(Context.ALARM_SERVICE));
1559 }
1560 return mAppBindArgs;
1561 }
1562
1563 private final void setFocusedActivityLocked(HistoryRecord r) {
1564 if (mFocusedActivity != r) {
1565 mFocusedActivity = r;
1566 mWindowManager.setFocusedApp(r, true);
1567 }
1568 }
1569
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001570 private final void updateLruProcessLocked(ProcessRecord app,
1571 boolean oomAdj, boolean updateActivityTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001573 int lrui = mLruProcesses.indexOf(app);
1574 if (lrui >= 0) mLruProcesses.remove(lrui);
1575
1576 int i = mLruProcesses.size()-1;
1577 int skipTop = 0;
1578
1579 // compute the new weight for this process.
1580 if (updateActivityTime) {
1581 app.lastActivityTime = SystemClock.uptimeMillis();
1582 }
1583 if (app.activities.size() > 0) {
1584 // If this process has activities, we more strongly want to keep
1585 // it around.
1586 app.lruWeight = app.lastActivityTime;
1587 } else if (app.pubProviders.size() > 0) {
1588 // If this process contains content providers, we want to keep
1589 // it a little more strongly.
1590 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1591 // Also don't let it kick out the first few "real" hidden processes.
1592 skipTop = MIN_HIDDEN_APPS;
1593 } else {
1594 // If this process doesn't have activities, we less strongly
1595 // want to keep it around, and generally want to avoid getting
1596 // in front of any very recently used activities.
1597 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1598 // Also don't let it kick out the first few "real" hidden processes.
1599 skipTop = MIN_HIDDEN_APPS;
1600 }
1601 while (i >= 0) {
1602 ProcessRecord p = mLruProcesses.get(i);
1603 // If this app shouldn't be in front of the first N background
1604 // apps, then skip over that many that are currently hidden.
1605 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1606 skipTop--;
1607 }
1608 if (p.lruWeight <= app.lruWeight){
1609 mLruProcesses.add(i+1, app);
1610 break;
1611 }
1612 i--;
1613 }
1614 if (i < 0) {
1615 mLruProcesses.add(0, app);
1616 }
1617
Joe Onorato8a9b2202010-02-26 18:56:32 -08001618 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 if (oomAdj) {
1620 updateOomAdjLocked();
1621 }
1622 }
1623
1624 private final boolean updateLRUListLocked(HistoryRecord r) {
1625 final boolean hadit = mLRUActivities.remove(r);
1626 mLRUActivities.add(r);
1627 return hadit;
1628 }
1629
1630 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1631 int i = mHistory.size()-1;
1632 while (i >= 0) {
1633 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1634 if (!r.finishing && r != notTop) {
1635 return r;
1636 }
1637 i--;
1638 }
1639 return null;
1640 }
1641
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001642 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1643 int i = mHistory.size()-1;
1644 while (i >= 0) {
1645 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1646 if (!r.finishing && !r.delayedResume && r != notTop) {
1647 return r;
1648 }
1649 i--;
1650 }
1651 return null;
1652 }
1653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 /**
1655 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001656 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 *
1658 * @param token If non-null, any history records matching this token will be skipped.
1659 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1660 *
1661 * @return Returns the HistoryRecord of the next activity on the stack.
1662 */
1663 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1664 int i = mHistory.size()-1;
1665 while (i >= 0) {
1666 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1667 // Note: the taskId check depends on real taskId fields being non-zero
1668 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1669 return r;
1670 }
1671 i--;
1672 }
1673 return null;
1674 }
1675
1676 private final ProcessRecord getProcessRecordLocked(
1677 String processName, int uid) {
1678 if (uid == Process.SYSTEM_UID) {
1679 // The system gets to run in any process. If there are multiple
1680 // processes with the same uid, just pick the first (this
1681 // should never happen).
1682 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1683 processName);
1684 return procs != null ? procs.valueAt(0) : null;
1685 }
1686 ProcessRecord proc = mProcessNames.get(processName, uid);
1687 return proc;
1688 }
1689
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001690 private void ensurePackageDexOpt(String packageName) {
1691 IPackageManager pm = ActivityThread.getPackageManager();
1692 try {
1693 if (pm.performDexOpt(packageName)) {
1694 mDidDexOpt = true;
1695 }
1696 } catch (RemoteException e) {
1697 }
1698 }
1699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 private boolean isNextTransitionForward() {
1701 int transit = mWindowManager.getPendingAppTransition();
1702 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1703 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1704 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1705 }
1706
1707 private final boolean realStartActivityLocked(HistoryRecord r,
1708 ProcessRecord app, boolean andResume, boolean checkConfig)
1709 throws RemoteException {
1710
1711 r.startFreezingScreenLocked(app, 0);
1712 mWindowManager.setAppVisibility(r, true);
1713
1714 // Have the window manager re-evaluate the orientation of
1715 // the screen based on the new activity order. Note that
1716 // as a result of this, it can call back into the activity
1717 // manager with a new orientation. We don't care about that,
1718 // because the activity is not currently running so we are
1719 // just restarting it anyway.
1720 if (checkConfig) {
1721 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001722 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 r.mayFreezeScreenLocked(app) ? r : null);
1724 updateConfigurationLocked(config, r);
1725 }
1726
1727 r.app = app;
1728
Joe Onorato8a9b2202010-02-26 18:56:32 -08001729 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730
1731 int idx = app.activities.indexOf(r);
1732 if (idx < 0) {
1733 app.activities.add(r);
1734 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001735 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736
1737 try {
1738 if (app.thread == null) {
1739 throw new RemoteException();
1740 }
1741 List<ResultInfo> results = null;
1742 List<Intent> newIntents = null;
1743 if (andResume) {
1744 results = r.results;
1745 newIntents = r.newIntents;
1746 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001747 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 + " icicle=" + r.icicle
1749 + " with results=" + results + " newIntents=" + newIntents
1750 + " andResume=" + andResume);
1751 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001752 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 System.identityHashCode(r),
1754 r.task.taskId, r.shortComponentName);
1755 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001756 if (r.isHomeActivity) {
1757 mHomeProcess = app;
1758 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001759 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001761 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 r.info, r.icicle, results, newIntents, !andResume,
1763 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 } catch (RemoteException e) {
1765 if (r.launchFailed) {
1766 // This is the second time we failed -- finish activity
1767 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001768 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 + r.intent.getComponent().flattenToShortString()
1770 + ", giving up", e);
1771 appDiedLocked(app, app.pid, app.thread);
1772 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1773 "2nd-crash");
1774 return false;
1775 }
1776
1777 // This is the first time we failed -- restart process and
1778 // retry.
1779 app.activities.remove(r);
1780 throw e;
1781 }
1782
1783 r.launchFailed = false;
1784 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001785 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 + " being launched, but already in LRU list");
1787 }
1788
1789 if (andResume) {
1790 // As part of the process of launching, ActivityThread also performs
1791 // a resume.
1792 r.state = ActivityState.RESUMED;
1793 r.icicle = null;
1794 r.haveState = false;
1795 r.stopped = false;
1796 mResumedActivity = r;
1797 r.task.touchActiveTime();
1798 completeResumeLocked(r);
1799 pauseIfSleepingLocked();
1800 } else {
1801 // This activity is not starting in the resumed state... which
1802 // should look like we asked it to pause+stop (but remain visible),
1803 // and it has done so and reported back the current icicle and
1804 // other state.
1805 r.state = ActivityState.STOPPED;
1806 r.stopped = true;
1807 }
1808
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001809 // Launch the new version setup screen if needed. We do this -after-
1810 // launching the initial activity (that is, home), so that it can have
1811 // a chance to initialize itself while in the background, making the
1812 // switch back to it faster and look better.
1813 startSetupActivityLocked();
1814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 return true;
1816 }
1817
1818 private final void startSpecificActivityLocked(HistoryRecord r,
1819 boolean andResume, boolean checkConfig) {
1820 // Is this activity's application already running?
1821 ProcessRecord app = getProcessRecordLocked(r.processName,
1822 r.info.applicationInfo.uid);
1823
1824 if (r.startTime == 0) {
1825 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001826 if (mInitialStartTime == 0) {
1827 mInitialStartTime = r.startTime;
1828 }
1829 } else if (mInitialStartTime == 0) {
1830 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 }
1832
1833 if (app != null && app.thread != null) {
1834 try {
1835 realStartActivityLocked(r, app, andResume, checkConfig);
1836 return;
1837 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001838 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 + r.intent.getComponent().flattenToShortString(), e);
1840 }
1841
1842 // If a dead object exception was thrown -- fall through to
1843 // restart the application.
1844 }
1845
1846 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001847 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 }
1849
1850 private final ProcessRecord startProcessLocked(String processName,
1851 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001852 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1854 // We don't have to do anything more if:
1855 // (1) There is an existing application record; and
1856 // (2) The caller doesn't think it is dead, OR there is no thread
1857 // object attached to it so we know it couldn't have crashed; and
1858 // (3) There is a pid assigned to it, so it is either starting or
1859 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001860 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 + " app=" + app + " knownToBeDead=" + knownToBeDead
1862 + " thread=" + (app != null ? app.thread : null)
1863 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001864 if (app != null && app.pid > 0) {
1865 if (!knownToBeDead || app.thread == null) {
1866 return app;
1867 } else {
1868 // An application record is attached to a previous process,
1869 // clean it up now.
1870 handleAppDiedLocked(app, true);
1871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 String hostingNameStr = hostingName != null
1875 ? hostingName.flattenToShortString() : null;
1876
1877 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1878 // If we are in the background, then check to see if this process
1879 // is bad. If so, we will just silently fail.
1880 if (mBadProcesses.get(info.processName, info.uid) != null) {
1881 return null;
1882 }
1883 } else {
1884 // When the user is explicitly starting a process, then clear its
1885 // crash count so that we won't make it bad until they see at
1886 // least one crash dialog again, and make the process good again
1887 // if it had been bad.
1888 mProcessCrashTimes.remove(info.processName, info.uid);
1889 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001890 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 info.processName);
1892 mBadProcesses.remove(info.processName, info.uid);
1893 if (app != null) {
1894 app.bad = false;
1895 }
1896 }
1897 }
1898
1899 if (app == null) {
1900 app = newProcessRecordLocked(null, info, processName);
1901 mProcessNames.put(processName, info.uid, app);
1902 } else {
1903 // If this is a new package in the process, add the package to the list
1904 app.addPackage(info.packageName);
1905 }
1906
1907 // If the system is not ready yet, then hold off on starting this
1908 // process until it is.
1909 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001910 && !isAllowedWhileBooting(info)
1911 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 if (!mProcessesOnHold.contains(app)) {
1913 mProcessesOnHold.add(app);
1914 }
1915 return app;
1916 }
1917
1918 startProcessLocked(app, hostingType, hostingNameStr);
1919 return (app.pid != 0) ? app : null;
1920 }
1921
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001922 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1923 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1924 }
1925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001926 private final void startProcessLocked(ProcessRecord app,
1927 String hostingType, String hostingNameStr) {
1928 if (app.pid > 0 && app.pid != MY_PID) {
1929 synchronized (mPidsSelfLocked) {
1930 mPidsSelfLocked.remove(app.pid);
1931 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1932 }
1933 app.pid = 0;
1934 }
1935
1936 mProcessesOnHold.remove(app);
1937
1938 updateCpuStats();
1939
1940 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1941 mProcDeaths[0] = 0;
1942
1943 try {
1944 int uid = app.info.uid;
1945 int[] gids = null;
1946 try {
1947 gids = mContext.getPackageManager().getPackageGids(
1948 app.info.packageName);
1949 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001950 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001951 }
1952 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1953 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1954 && mTopComponent != null
1955 && app.processName.equals(mTopComponent.getPackageName())) {
1956 uid = 0;
1957 }
1958 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1959 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1960 uid = 0;
1961 }
1962 }
1963 int debugFlags = 0;
1964 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1965 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1966 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001967 // Run the app in safe mode if its manifest requests so or the
1968 // system is booted in safe mode.
1969 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1970 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001971 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1972 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001973 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1974 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1975 }
1976 if ("1".equals(SystemProperties.get("debug.assert"))) {
1977 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1978 }
1979 int pid = Process.start("android.app.ActivityThread",
1980 mSimpleProcessManagement ? app.processName : null, uid, uid,
1981 gids, debugFlags, null);
1982 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1983 synchronized (bs) {
1984 if (bs.isOnBattery()) {
1985 app.batteryStats.incStartsLocked();
1986 }
1987 }
1988
Doug Zongker2bec3d42009-12-04 12:52:44 -08001989 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 app.processName, hostingType,
1991 hostingNameStr != null ? hostingNameStr : "");
1992
1993 if (app.persistent) {
1994 Watchdog.getInstance().processStarted(app, app.processName, pid);
1995 }
1996
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001997 StringBuilder buf = mStringBuilder;
1998 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999 buf.append("Start proc ");
2000 buf.append(app.processName);
2001 buf.append(" for ");
2002 buf.append(hostingType);
2003 if (hostingNameStr != null) {
2004 buf.append(" ");
2005 buf.append(hostingNameStr);
2006 }
2007 buf.append(": pid=");
2008 buf.append(pid);
2009 buf.append(" uid=");
2010 buf.append(uid);
2011 buf.append(" gids={");
2012 if (gids != null) {
2013 for (int gi=0; gi<gids.length; gi++) {
2014 if (gi != 0) buf.append(", ");
2015 buf.append(gids[gi]);
2016
2017 }
2018 }
2019 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002020 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 if (pid == 0 || pid == MY_PID) {
2022 // Processes are being emulated with threads.
2023 app.pid = MY_PID;
2024 app.removed = false;
2025 mStartingProcesses.add(app);
2026 } else if (pid > 0) {
2027 app.pid = pid;
2028 app.removed = false;
2029 synchronized (mPidsSelfLocked) {
2030 this.mPidsSelfLocked.put(pid, app);
2031 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2032 msg.obj = app;
2033 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2034 }
2035 } else {
2036 app.pid = 0;
2037 RuntimeException e = new RuntimeException(
2038 "Failure starting process " + app.processName
2039 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002040 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 }
2042 } catch (RuntimeException e) {
2043 // XXX do better error recovery.
2044 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002045 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 }
2047 }
2048
2049 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2050 if (mPausingActivity != null) {
2051 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002052 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 + mPausingActivity, e);
2054 }
2055 HistoryRecord prev = mResumedActivity;
2056 if (prev == null) {
2057 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002058 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 resumeTopActivityLocked(null);
2060 return;
2061 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002062 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 mResumedActivity = null;
2064 mPausingActivity = prev;
2065 mLastPausedActivity = prev;
2066 prev.state = ActivityState.PAUSING;
2067 prev.task.touchActiveTime();
2068
2069 updateCpuStats();
2070
2071 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002072 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002074 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 System.identityHashCode(prev),
2076 prev.shortComponentName);
2077 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2078 prev.configChangeFlags);
2079 updateUsageStats(prev, false);
2080 } catch (Exception e) {
2081 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002082 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 mPausingActivity = null;
2084 mLastPausedActivity = null;
2085 }
2086 } else {
2087 mPausingActivity = null;
2088 mLastPausedActivity = null;
2089 }
2090
2091 // If we are not going to sleep, we want to ensure the device is
2092 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002093 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002094 mLaunchingActivity.acquire();
2095 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2096 // To be safe, don't allow the wake lock to be held for too long.
2097 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2098 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2099 }
2100 }
2101
2102
2103 if (mPausingActivity != null) {
2104 // Have the window manager pause its key dispatching until the new
2105 // activity has started. If we're pausing the activity just because
2106 // the screen is being turned off and the UI is sleeping, don't interrupt
2107 // key dispatch; the same activity will pick it up again on wakeup.
2108 if (!uiSleeping) {
2109 prev.pauseKeyDispatchingLocked();
2110 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002111 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002112 }
2113
2114 // Schedule a pause timeout in case the app doesn't respond.
2115 // We don't give it much time because this directly impacts the
2116 // responsiveness seen by the user.
2117 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2118 msg.obj = prev;
2119 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002120 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 } else {
2122 // This activity failed to schedule the
2123 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002124 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125 resumeTopActivityLocked(null);
2126 }
2127 }
2128
2129 private final void completePauseLocked() {
2130 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002131 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132
2133 if (prev != null) {
2134 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002135 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2137 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002138 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 if (prev.waitingVisible) {
2140 prev.waitingVisible = false;
2141 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002142 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 TAG, "Complete pause, no longer waiting: " + prev);
2144 }
2145 if (prev.configDestroy) {
2146 // The previous is being paused because the configuration
2147 // is changing, which means it is actually stopping...
2148 // To juggle the fact that we are also starting a new
2149 // instance right now, we need to first completely stop
2150 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002151 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 destroyActivityLocked(prev, true);
2153 } else {
2154 mStoppingActivities.add(prev);
2155 if (mStoppingActivities.size() > 3) {
2156 // If we already have a few activities waiting to stop,
2157 // then give up on things going idle and start clearing
2158 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002159 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002160 Message msg = Message.obtain();
2161 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2162 mHandler.sendMessage(msg);
2163 }
2164 }
2165 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002166 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167 prev = null;
2168 }
2169 mPausingActivity = null;
2170 }
2171
Dianne Hackborn55280a92009-05-07 15:53:46 -07002172 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 resumeTopActivityLocked(prev);
2174 } else {
2175 if (mGoingToSleep.isHeld()) {
2176 mGoingToSleep.release();
2177 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002178 if (mShuttingDown) {
2179 notifyAll();
2180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 }
2182
2183 if (prev != null) {
2184 prev.resumeKeyDispatchingLocked();
2185 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002186
2187 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2188 long diff = 0;
2189 synchronized (mProcessStatsThread) {
2190 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2191 }
2192 if (diff > 0) {
2193 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2194 synchronized (bsi) {
2195 BatteryStatsImpl.Uid.Proc ps =
2196 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2197 prev.info.packageName);
2198 if (ps != null) {
2199 ps.addForegroundTimeLocked(diff);
2200 }
2201 }
2202 }
2203 }
2204 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002205 }
2206
2207 /**
2208 * Once we know that we have asked an application to put an activity in
2209 * the resumed state (either by launching it or explicitly telling it),
2210 * this function updates the rest of our state to match that fact.
2211 */
2212 private final void completeResumeLocked(HistoryRecord next) {
2213 next.idle = false;
2214 next.results = null;
2215 next.newIntents = null;
2216
2217 // schedule an idle timeout in case the app doesn't do it for us.
2218 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2219 msg.obj = next;
2220 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2221
2222 if (false) {
2223 // The activity was never told to pause, so just keep
2224 // things going as-is. To maintain our own state,
2225 // we need to emulate it coming back and saying it is
2226 // idle.
2227 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2228 msg.obj = next;
2229 mHandler.sendMessage(msg);
2230 }
2231
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002232 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 next.thumbnail = null;
2235 setFocusedActivityLocked(next);
2236 next.resumeKeyDispatchingLocked();
2237 ensureActivitiesVisibleLocked(null, 0);
2238 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002239 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002240
2241 // Mark the point when the activity is resuming
2242 // TODO: To be more accurate, the mark should be before the onCreate,
2243 // not after the onResume. But for subsequent starts, onResume is fine.
2244 if (next.app != null) {
2245 synchronized (mProcessStatsThread) {
2246 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2247 }
2248 } else {
2249 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251 }
2252
2253 /**
2254 * Make sure that all activities that need to be visible (that is, they
2255 * currently can be seen by the user) actually are.
2256 */
2257 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2258 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002259 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002260 TAG, "ensureActivitiesVisible behind " + top
2261 + " configChanges=0x" + Integer.toHexString(configChanges));
2262
2263 // If the top activity is not fullscreen, then we need to
2264 // make sure any activities under it are now visible.
2265 final int count = mHistory.size();
2266 int i = count-1;
2267 while (mHistory.get(i) != top) {
2268 i--;
2269 }
2270 HistoryRecord r;
2271 boolean behindFullscreen = false;
2272 for (; i>=0; i--) {
2273 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002274 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 TAG, "Make visible? " + r + " finishing=" + r.finishing
2276 + " state=" + r.state);
2277 if (r.finishing) {
2278 continue;
2279 }
2280
2281 final boolean doThisProcess = onlyThisProcess == null
2282 || onlyThisProcess.equals(r.processName);
2283
2284 // First: if this is not the current activity being started, make
2285 // sure it matches the current configuration.
2286 if (r != starting && doThisProcess) {
2287 ensureActivityConfigurationLocked(r, 0);
2288 }
2289
2290 if (r.app == null || r.app.thread == null) {
2291 if (onlyThisProcess == null
2292 || onlyThisProcess.equals(r.processName)) {
2293 // This activity needs to be visible, but isn't even
2294 // running... get it started, but don't resume it
2295 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002296 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002297 TAG, "Start and freeze screen for " + r);
2298 if (r != starting) {
2299 r.startFreezingScreenLocked(r.app, configChanges);
2300 }
2301 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002302 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002303 TAG, "Starting and making visible: " + r);
2304 mWindowManager.setAppVisibility(r, true);
2305 }
2306 if (r != starting) {
2307 startSpecificActivityLocked(r, false, false);
2308 }
2309 }
2310
2311 } else if (r.visible) {
2312 // If this activity is already visible, then there is nothing
2313 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002314 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 TAG, "Skipping: already visible at " + r);
2316 r.stopFreezingScreenLocked(false);
2317
2318 } else if (onlyThisProcess == null) {
2319 // This activity is not currently visible, but is running.
2320 // Tell it to become visible.
2321 r.visible = true;
2322 if (r.state != ActivityState.RESUMED && r != starting) {
2323 // If this activity is paused, tell it
2324 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002325 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 TAG, "Making visible and scheduling visibility: " + r);
2327 try {
2328 mWindowManager.setAppVisibility(r, true);
2329 r.app.thread.scheduleWindowVisibility(r, true);
2330 r.stopFreezingScreenLocked(false);
2331 } catch (Exception e) {
2332 // Just skip on any failure; we'll make it
2333 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002334 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 + r.intent.getComponent(), e);
2336 }
2337 }
2338 }
2339
2340 // Aggregate current change flags.
2341 configChanges |= r.configChangeFlags;
2342
2343 if (r.fullscreen) {
2344 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002345 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002346 TAG, "Stopping: fullscreen at " + r);
2347 behindFullscreen = true;
2348 i--;
2349 break;
2350 }
2351 }
2352
2353 // Now for any activities that aren't visible to the user, make
2354 // sure they no longer are keeping the screen frozen.
2355 while (i >= 0) {
2356 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002357 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2359 + " state=" + r.state
2360 + " behindFullscreen=" + behindFullscreen);
2361 if (!r.finishing) {
2362 if (behindFullscreen) {
2363 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002364 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002365 TAG, "Making invisible: " + r);
2366 r.visible = false;
2367 try {
2368 mWindowManager.setAppVisibility(r, false);
2369 if ((r.state == ActivityState.STOPPING
2370 || r.state == ActivityState.STOPPED)
2371 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002372 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 TAG, "Scheduling invisibility: " + r);
2374 r.app.thread.scheduleWindowVisibility(r, false);
2375 }
2376 } catch (Exception e) {
2377 // Just skip on any failure; we'll make it
2378 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002379 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 + r.intent.getComponent(), e);
2381 }
2382 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002383 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002384 TAG, "Already invisible: " + r);
2385 }
2386 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002387 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002388 TAG, "Now behindFullscreen: " + r);
2389 behindFullscreen = true;
2390 }
2391 }
2392 i--;
2393 }
2394 }
2395
2396 /**
2397 * Version of ensureActivitiesVisible that can easily be called anywhere.
2398 */
2399 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2400 int configChanges) {
2401 HistoryRecord r = topRunningActivityLocked(null);
2402 if (r != null) {
2403 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2404 }
2405 }
2406
2407 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2408 if (resumed) {
2409 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2410 } else {
2411 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2412 }
2413 }
2414
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002415 private boolean startHomeActivityLocked() {
2416 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2417 && mTopAction == null) {
2418 // We are running in factory test mode, but unable to find
2419 // the factory test app, so just sit around displaying the
2420 // error message and don't try to start anything.
2421 return false;
2422 }
2423 Intent intent = new Intent(
2424 mTopAction,
2425 mTopData != null ? Uri.parse(mTopData) : null);
2426 intent.setComponent(mTopComponent);
2427 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2428 intent.addCategory(Intent.CATEGORY_HOME);
2429 }
2430 ActivityInfo aInfo =
2431 intent.resolveActivityInfo(mContext.getPackageManager(),
2432 STOCK_PM_FLAGS);
2433 if (aInfo != null) {
2434 intent.setComponent(new ComponentName(
2435 aInfo.applicationInfo.packageName, aInfo.name));
2436 // Don't do this if the home app is currently being
2437 // instrumented.
2438 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2439 aInfo.applicationInfo.uid);
2440 if (app == null || app.instrumentationClass == null) {
2441 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2442 startActivityLocked(null, intent, null, null, 0, aInfo,
2443 null, null, 0, 0, 0, false, false);
2444 }
2445 }
2446
2447
2448 return true;
2449 }
2450
2451 /**
2452 * Starts the "new version setup screen" if appropriate.
2453 */
2454 private void startSetupActivityLocked() {
2455 // Only do this once per boot.
2456 if (mCheckedForSetup) {
2457 return;
2458 }
2459
2460 // We will show this screen if the current one is a different
2461 // version than the last one shown, and we are not running in
2462 // low-level factory test mode.
2463 final ContentResolver resolver = mContext.getContentResolver();
2464 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2465 Settings.Secure.getInt(resolver,
2466 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2467 mCheckedForSetup = true;
2468
2469 // See if we should be showing the platform update setup UI.
2470 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2471 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2472 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2473
2474 // We don't allow third party apps to replace this.
2475 ResolveInfo ri = null;
2476 for (int i=0; ris != null && i<ris.size(); i++) {
2477 if ((ris.get(i).activityInfo.applicationInfo.flags
2478 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2479 ri = ris.get(i);
2480 break;
2481 }
2482 }
2483
2484 if (ri != null) {
2485 String vers = ri.activityInfo.metaData != null
2486 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2487 : null;
2488 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2489 vers = ri.activityInfo.applicationInfo.metaData.getString(
2490 Intent.METADATA_SETUP_VERSION);
2491 }
2492 String lastVers = Settings.Secure.getString(
2493 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2494 if (vers != null && !vers.equals(lastVers)) {
2495 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2496 intent.setComponent(new ComponentName(
2497 ri.activityInfo.packageName, ri.activityInfo.name));
2498 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2499 null, null, 0, 0, 0, false, false);
2500 }
2501 }
2502 }
2503 }
2504
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002505 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002506 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002507
2508 final int identHash = System.identityHashCode(r);
2509 updateUsageStats(r, true);
2510
2511 int i = mWatchers.beginBroadcast();
2512 while (i > 0) {
2513 i--;
2514 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2515 if (w != null) {
2516 try {
2517 w.activityResuming(identHash);
2518 } catch (RemoteException e) {
2519 }
2520 }
2521 }
2522 mWatchers.finishBroadcast();
2523 }
2524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 /**
2526 * Ensure that the top activity in the stack is resumed.
2527 *
2528 * @param prev The previously resumed activity, for when in the process
2529 * of pausing; can be null to call from elsewhere.
2530 *
2531 * @return Returns true if something is being resumed, or false if
2532 * nothing happened.
2533 */
2534 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2535 // Find the first activity that is not finishing.
2536 HistoryRecord next = topRunningActivityLocked(null);
2537
2538 // Remember how we'll process this pause/resume situation, and ensure
2539 // that the state is reset however we wind up proceeding.
2540 final boolean userLeaving = mUserLeaving;
2541 mUserLeaving = false;
2542
2543 if (next == null) {
2544 // There are no more activities! Let's just start up the
2545 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002546 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 }
2548
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002549 next.delayedResume = false;
2550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 // If the top activity is the resumed one, nothing to do.
2552 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2553 // Make sure we have executed any pending transitions, since there
2554 // should be nothing left to do at this point.
2555 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002556 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 return false;
2558 }
2559
2560 // If we are sleeping, and there is no resumed activity, and the top
2561 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002562 if ((mSleeping || mShuttingDown)
2563 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002564 // Make sure we have executed any pending transitions, since there
2565 // should be nothing left to do at this point.
2566 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002567 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 return false;
2569 }
2570
2571 // The activity may be waiting for stop, but that is no longer
2572 // appropriate for it.
2573 mStoppingActivities.remove(next);
2574 mWaitingVisibleActivities.remove(next);
2575
Joe Onorato8a9b2202010-02-26 18:56:32 -08002576 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002577
2578 // If we are currently pausing an activity, then don't do anything
2579 // until that is done.
2580 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002581 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582 return false;
2583 }
2584
2585 // We need to start pausing the current activity so the top one
2586 // can be resumed...
2587 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002588 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589 startPausingLocked(userLeaving, false);
2590 return true;
2591 }
2592
2593 if (prev != null && prev != next) {
2594 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2595 prev.waitingVisible = true;
2596 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002597 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002598 TAG, "Resuming top, waiting visible to hide: " + prev);
2599 } else {
2600 // The next activity is already visible, so hide the previous
2601 // activity's windows right now so we can show the new one ASAP.
2602 // We only do this if the previous is finishing, which should mean
2603 // it is on top of the one being resumed so hiding it quickly
2604 // is good. Otherwise, we want to do the normal route of allowing
2605 // the resumed activity to be shown so we can decide if the
2606 // previous should actually be hidden depending on whether the
2607 // new one is found to be full-screen or not.
2608 if (prev.finishing) {
2609 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002610 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002611 + prev + ", waitingVisible="
2612 + (prev != null ? prev.waitingVisible : null)
2613 + ", nowVisible=" + next.nowVisible);
2614 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002615 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting 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 }
2620 }
2621 }
2622
2623 // We are starting up the next activity, so tell the window manager
2624 // that the previous one will be hidden soon. This way it can know
2625 // to ignore it when computing the desired screen orientation.
2626 if (prev != null) {
2627 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002628 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002630 if (mNoAnimActivities.contains(prev)) {
2631 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2632 } else {
2633 mWindowManager.prepareAppTransition(prev.task == next.task
2634 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2635 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637 mWindowManager.setAppWillBeHidden(prev);
2638 mWindowManager.setAppVisibility(prev, false);
2639 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002640 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002642 if (mNoAnimActivities.contains(next)) {
2643 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2644 } else {
2645 mWindowManager.prepareAppTransition(prev.task == next.task
2646 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2647 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002649 }
2650 if (false) {
2651 mWindowManager.setAppWillBeHidden(prev);
2652 mWindowManager.setAppVisibility(prev, false);
2653 }
2654 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002655 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002656 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002657 if (mNoAnimActivities.contains(next)) {
2658 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2659 } else {
2660 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2661 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002662 }
2663
2664 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002665 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002666
2667 // This activity is now becoming visible.
2668 mWindowManager.setAppVisibility(next, true);
2669
2670 HistoryRecord lastResumedActivity = mResumedActivity;
2671 ActivityState lastState = next.state;
2672
2673 updateCpuStats();
2674
2675 next.state = ActivityState.RESUMED;
2676 mResumedActivity = next;
2677 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002678 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 updateLRUListLocked(next);
2680
2681 // Have the window manager re-evaluate the orientation of
2682 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002683 boolean updated;
2684 synchronized (this) {
2685 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2686 mConfiguration,
2687 next.mayFreezeScreenLocked(next.app) ? next : null);
2688 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002689 next.frozenBeforeDestroy = true;
2690 }
2691 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002692 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002693 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 // The configuration update wasn't able to keep the existing
2695 // instance of the activity, and instead started a new one.
2696 // We should be all done, but let's just make sure our activity
2697 // is still at the top and schedule another run if something
2698 // weird happened.
2699 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002700 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 "Activity config changed during resume: " + next
2702 + ", new next: " + nextNext);
2703 if (nextNext != next) {
2704 // Do over!
2705 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2706 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002707 setFocusedActivityLocked(next);
2708 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002709 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002710 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 return true;
2712 }
2713
2714 try {
2715 // Deliver all pending results.
2716 ArrayList a = next.results;
2717 if (a != null) {
2718 final int N = a.size();
2719 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002720 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 TAG, "Delivering results to " + next
2722 + ": " + a);
2723 next.app.thread.scheduleSendResult(next, a);
2724 }
2725 }
2726
2727 if (next.newIntents != null) {
2728 next.app.thread.scheduleNewIntent(next.newIntents, next);
2729 }
2730
Doug Zongker2bec3d42009-12-04 12:52:44 -08002731 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 System.identityHashCode(next),
2733 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734
2735 next.app.thread.scheduleResumeActivity(next,
2736 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 pauseIfSleepingLocked();
2739
2740 } catch (Exception e) {
2741 // Whoops, need to restart this activity!
2742 next.state = lastState;
2743 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002744 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 if (!next.hasBeenLaunched) {
2746 next.hasBeenLaunched = true;
2747 } else {
2748 if (SHOW_APP_STARTING_ICON) {
2749 mWindowManager.setAppStartingWindow(
2750 next, next.packageName, next.theme,
2751 next.nonLocalizedLabel,
2752 next.labelRes, next.icon, null, true);
2753 }
2754 }
2755 startSpecificActivityLocked(next, true, false);
2756 return true;
2757 }
2758
2759 // From this point on, if something goes wrong there is no way
2760 // to recover the activity.
2761 try {
2762 next.visible = true;
2763 completeResumeLocked(next);
2764 } catch (Exception e) {
2765 // If any exception gets thrown, toss away this
2766 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002767 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002768 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2769 "resume-exception");
2770 return true;
2771 }
2772
2773 // Didn't need to use the icicle, and it is now out of date.
2774 next.icicle = null;
2775 next.haveState = false;
2776 next.stopped = false;
2777
2778 } else {
2779 // Whoops, need to restart this activity!
2780 if (!next.hasBeenLaunched) {
2781 next.hasBeenLaunched = true;
2782 } else {
2783 if (SHOW_APP_STARTING_ICON) {
2784 mWindowManager.setAppStartingWindow(
2785 next, next.packageName, next.theme,
2786 next.nonLocalizedLabel,
2787 next.labelRes, next.icon, null, true);
2788 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002789 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 }
2791 startSpecificActivityLocked(next, true, true);
2792 }
2793
2794 return true;
2795 }
2796
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002797 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2798 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002799 final int NH = mHistory.size();
2800
2801 int addPos = -1;
2802
2803 if (!newTask) {
2804 // If starting in an existing task, find where that is...
2805 HistoryRecord next = null;
2806 boolean startIt = true;
2807 for (int i = NH-1; i >= 0; i--) {
2808 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2809 if (p.finishing) {
2810 continue;
2811 }
2812 if (p.task == r.task) {
2813 // Here it is! Now, if this is not yet visible to the
2814 // user, then just add it without starting; it will
2815 // get started when the user navigates back to it.
2816 addPos = i+1;
2817 if (!startIt) {
2818 mHistory.add(addPos, r);
2819 r.inHistory = true;
2820 r.task.numActivities++;
2821 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2822 r.info.screenOrientation, r.fullscreen);
2823 if (VALIDATE_TOKENS) {
2824 mWindowManager.validateAppTokens(mHistory);
2825 }
2826 return;
2827 }
2828 break;
2829 }
2830 if (p.fullscreen) {
2831 startIt = false;
2832 }
2833 next = p;
2834 }
2835 }
2836
2837 // Place a new activity at top of stack, so it is next to interact
2838 // with the user.
2839 if (addPos < 0) {
2840 addPos = mHistory.size();
2841 }
2842
2843 // If we are not placing the new activity frontmost, we do not want
2844 // to deliver the onUserLeaving callback to the actual frontmost
2845 // activity
2846 if (addPos < NH) {
2847 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002848 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002849 }
2850
2851 // Slot the activity into the history stack and proceed
2852 mHistory.add(addPos, r);
2853 r.inHistory = true;
2854 r.frontOfTask = newTask;
2855 r.task.numActivities++;
2856 if (NH > 0) {
2857 // We want to show the starting preview window if we are
2858 // switching to a new task, or the next activity's process is
2859 // not currently running.
2860 boolean showStartingIcon = newTask;
2861 ProcessRecord proc = r.app;
2862 if (proc == null) {
2863 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2864 }
2865 if (proc == null || proc.thread == null) {
2866 showStartingIcon = true;
2867 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002868 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002870 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2871 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2872 mNoAnimActivities.add(r);
2873 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2874 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2875 mNoAnimActivities.remove(r);
2876 } else {
2877 mWindowManager.prepareAppTransition(newTask
2878 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2879 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2880 mNoAnimActivities.remove(r);
2881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002882 mWindowManager.addAppToken(
2883 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2884 boolean doShow = true;
2885 if (newTask) {
2886 // Even though this activity is starting fresh, we still need
2887 // to reset it to make sure we apply affinities to move any
2888 // existing activities from other tasks in to it.
2889 // If the caller has requested that the target task be
2890 // reset, then do so.
2891 if ((r.intent.getFlags()
2892 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2893 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002894 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 }
2896 }
2897 if (SHOW_APP_STARTING_ICON && doShow) {
2898 // Figure out if we are transitioning from another activity that is
2899 // "has the same starting icon" as the next one. This allows the
2900 // window manager to keep the previous window it had previously
2901 // created, if it still had one.
2902 HistoryRecord prev = mResumedActivity;
2903 if (prev != null) {
2904 // We don't want to reuse the previous starting preview if:
2905 // (1) The current activity is in a different task.
2906 if (prev.task != r.task) prev = null;
2907 // (2) The current activity is already displayed.
2908 else if (prev.nowVisible) prev = null;
2909 }
2910 mWindowManager.setAppStartingWindow(
2911 r, r.packageName, r.theme, r.nonLocalizedLabel,
2912 r.labelRes, r.icon, prev, showStartingIcon);
2913 }
2914 } else {
2915 // If this is the first activity, don't do any fancy animations,
2916 // because there is nothing for it to animate on top of.
2917 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2918 r.info.screenOrientation, r.fullscreen);
2919 }
2920 if (VALIDATE_TOKENS) {
2921 mWindowManager.validateAppTokens(mHistory);
2922 }
2923
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002924 if (doResume) {
2925 resumeTopActivityLocked(null);
2926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002927 }
2928
2929 /**
2930 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002931 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2932 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 * an instance of that activity in the stack and, if found, finish all
2934 * activities on top of it and return the instance.
2935 *
2936 * @param newR Description of the new activity being started.
2937 * @return Returns the old activity that should be continue to be used,
2938 * or null if none was found.
2939 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002940 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002941 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002943
2944 // First find the requested task.
2945 while (i > 0) {
2946 i--;
2947 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2948 if (r.task.taskId == taskId) {
2949 i++;
2950 break;
2951 }
2952 }
2953
2954 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955 while (i > 0) {
2956 i--;
2957 HistoryRecord r = (HistoryRecord)mHistory.get(i);
2958 if (r.finishing) {
2959 continue;
2960 }
2961 if (r.task.taskId != taskId) {
2962 return null;
2963 }
2964 if (r.realActivity.equals(newR.realActivity)) {
2965 // Here it is! Now finish everything in front...
2966 HistoryRecord ret = r;
2967 if (doClear) {
2968 while (i < (mHistory.size()-1)) {
2969 i++;
2970 r = (HistoryRecord)mHistory.get(i);
2971 if (r.finishing) {
2972 continue;
2973 }
2974 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2975 null, "clear")) {
2976 i--;
2977 }
2978 }
2979 }
2980
2981 // Finally, if this is a normal launch mode (that is, not
2982 // expecting onNewIntent()), then we will finish the current
2983 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002984 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2985 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07002987 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002988 if (index >= 0) {
2989 finishActivityLocked(ret, 0, Activity.RESULT_CANCELED,
2990 null, "clear");
2991 }
2992 return null;
2993 }
2994 }
2995
2996 return ret;
2997 }
2998 }
2999
3000 return null;
3001 }
3002
3003 /**
3004 * Find the activity in the history stack within the given task. Returns
3005 * the index within the history at which it's found, or < 0 if not found.
3006 */
3007 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3008 int i = mHistory.size();
3009 while (i > 0) {
3010 i--;
3011 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3012 if (candidate.task.taskId != task) {
3013 break;
3014 }
3015 if (candidate.realActivity.equals(r.realActivity)) {
3016 return i;
3017 }
3018 }
3019
3020 return -1;
3021 }
3022
3023 /**
3024 * Reorder the history stack so that the activity at the given index is
3025 * brought to the front.
3026 */
3027 private final HistoryRecord moveActivityToFrontLocked(int where) {
3028 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3029 int top = mHistory.size();
3030 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3031 mHistory.add(top, newTop);
3032 oldTop.frontOfTask = false;
3033 newTop.frontOfTask = true;
3034 return newTop;
3035 }
3036
3037 /**
3038 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3039 * method will be called at the proper time.
3040 */
3041 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3042 boolean sent = false;
3043 if (r.state == ActivityState.RESUMED
3044 && r.app != null && r.app.thread != null) {
3045 try {
3046 ArrayList<Intent> ar = new ArrayList<Intent>();
3047 ar.add(new Intent(intent));
3048 r.app.thread.scheduleNewIntent(ar, r);
3049 sent = true;
3050 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003051 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 }
3053 }
3054 if (!sent) {
3055 r.addNewIntentLocked(new Intent(intent));
3056 }
3057 }
3058
3059 private final void logStartActivity(int tag, HistoryRecord r,
3060 TaskRecord task) {
3061 EventLog.writeEvent(tag,
3062 System.identityHashCode(r), task.taskId,
3063 r.shortComponentName, r.intent.getAction(),
3064 r.intent.getType(), r.intent.getDataString(),
3065 r.intent.getFlags());
3066 }
3067
3068 private final int startActivityLocked(IApplicationThread caller,
3069 Intent intent, String resolvedType,
3070 Uri[] grantedUriPermissions,
3071 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3072 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003073 int callingPid, int callingUid, boolean onlyIfNeeded,
3074 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003075 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003076
3077 HistoryRecord sourceRecord = null;
3078 HistoryRecord resultRecord = null;
3079 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003080 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003081 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3083 if (index >= 0) {
3084 sourceRecord = (HistoryRecord)mHistory.get(index);
3085 if (requestCode >= 0 && !sourceRecord.finishing) {
3086 resultRecord = sourceRecord;
3087 }
3088 }
3089 }
3090
3091 int launchFlags = intent.getFlags();
3092
3093 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3094 && sourceRecord != null) {
3095 // Transfer the result target from the source activity to the new
3096 // one being started, including any failures.
3097 if (requestCode >= 0) {
3098 return START_FORWARD_AND_REQUEST_CONFLICT;
3099 }
3100 resultRecord = sourceRecord.resultTo;
3101 resultWho = sourceRecord.resultWho;
3102 requestCode = sourceRecord.requestCode;
3103 sourceRecord.resultTo = null;
3104 if (resultRecord != null) {
3105 resultRecord.removeResultsLocked(
3106 sourceRecord, resultWho, requestCode);
3107 }
3108 }
3109
3110 int err = START_SUCCESS;
3111
3112 if (intent.getComponent() == null) {
3113 // We couldn't find a class that can handle the given Intent.
3114 // That's the end of that!
3115 err = START_INTENT_NOT_RESOLVED;
3116 }
3117
3118 if (err == START_SUCCESS && aInfo == null) {
3119 // We couldn't find the specific class specified in the Intent.
3120 // Also the end of the line.
3121 err = START_CLASS_NOT_FOUND;
3122 }
3123
3124 ProcessRecord callerApp = null;
3125 if (err == START_SUCCESS && caller != null) {
3126 callerApp = getRecordForAppLocked(caller);
3127 if (callerApp != null) {
3128 callingPid = callerApp.pid;
3129 callingUid = callerApp.info.uid;
3130 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003131 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 + " (pid=" + callingPid + ") when starting: "
3133 + intent.toString());
3134 err = START_PERMISSION_DENIED;
3135 }
3136 }
3137
3138 if (err != START_SUCCESS) {
3139 if (resultRecord != null) {
3140 sendActivityResultLocked(-1,
3141 resultRecord, resultWho, requestCode,
3142 Activity.RESULT_CANCELED, null);
3143 }
3144 return err;
3145 }
3146
3147 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3148 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3149 if (perm != PackageManager.PERMISSION_GRANTED) {
3150 if (resultRecord != null) {
3151 sendActivityResultLocked(-1,
3152 resultRecord, resultWho, requestCode,
3153 Activity.RESULT_CANCELED, null);
3154 }
3155 String msg = "Permission Denial: starting " + intent.toString()
3156 + " from " + callerApp + " (pid=" + callingPid
3157 + ", uid=" + callingUid + ")"
3158 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003159 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160 throw new SecurityException(msg);
3161 }
3162
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003163 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 boolean abort = false;
3165 try {
3166 // The Intent we give to the watcher has the extra data
3167 // stripped off, since it can contain private information.
3168 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003169 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003170 aInfo.applicationInfo.packageName);
3171 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003172 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003173 }
3174
3175 if (abort) {
3176 if (resultRecord != null) {
3177 sendActivityResultLocked(-1,
3178 resultRecord, resultWho, requestCode,
3179 Activity.RESULT_CANCELED, null);
3180 }
3181 // We pretend to the caller that it was really started, but
3182 // they will just get a cancel result.
3183 return START_SUCCESS;
3184 }
3185 }
3186
3187 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3188 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003189 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003190
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003191 if (mResumedActivity == null
3192 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3193 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3194 PendingActivityLaunch pal = new PendingActivityLaunch();
3195 pal.r = r;
3196 pal.sourceRecord = sourceRecord;
3197 pal.grantedUriPermissions = grantedUriPermissions;
3198 pal.grantedMode = grantedMode;
3199 pal.onlyIfNeeded = onlyIfNeeded;
3200 mPendingActivityLaunches.add(pal);
3201 return START_SWITCHES_CANCELED;
3202 }
3203 }
3204
3205 if (mDidAppSwitch) {
3206 // This is the second allowed switch since we stopped switches,
3207 // so now just generally allow switches. Use case: user presses
3208 // home (switches disabled, switch to home, mDidAppSwitch now true);
3209 // user taps a home icon (coming from home so allowed, we hit here
3210 // and now allow anyone to switch again).
3211 mAppSwitchesAllowedTime = 0;
3212 } else {
3213 mDidAppSwitch = true;
3214 }
3215
3216 doPendingActivityLaunchesLocked(false);
3217
3218 return startActivityUncheckedLocked(r, sourceRecord,
3219 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3220 }
3221
3222 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3223 final int N = mPendingActivityLaunches.size();
3224 if (N <= 0) {
3225 return;
3226 }
3227 for (int i=0; i<N; i++) {
3228 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3229 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3230 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3231 doResume && i == (N-1));
3232 }
3233 mPendingActivityLaunches.clear();
3234 }
3235
3236 private final int startActivityUncheckedLocked(HistoryRecord r,
3237 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3238 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3239 final Intent intent = r.intent;
3240 final int callingUid = r.launchedFromUid;
3241
3242 int launchFlags = intent.getFlags();
3243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003244 // We'll invoke onUserLeaving before onPause only if the launching
3245 // activity did not explicitly state that this is an automated launch.
3246 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003247 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 "startActivity() => mUserLeaving=" + mUserLeaving);
3249
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003250 // If the caller has asked not to resume at this point, we make note
3251 // of this in the record so that we can skip it when trying to find
3252 // the top running activity.
3253 if (!doResume) {
3254 r.delayedResume = true;
3255 }
3256
3257 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3258 != 0 ? r : null;
3259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260 // If the onlyIfNeeded flag is set, then we can do this if the activity
3261 // being launched is the same as the one making the call... or, as
3262 // a special case, if we do not know the caller then we count the
3263 // current top activity as the caller.
3264 if (onlyIfNeeded) {
3265 HistoryRecord checkedCaller = sourceRecord;
3266 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003267 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003268 }
3269 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3270 // Caller is not the same as launcher, so always needed.
3271 onlyIfNeeded = false;
3272 }
3273 }
3274
3275 if (grantedUriPermissions != null && callingUid > 0) {
3276 for (int i=0; i<grantedUriPermissions.length; i++) {
3277 grantUriPermissionLocked(callingUid, r.packageName,
3278 grantedUriPermissions[i], grantedMode, r);
3279 }
3280 }
3281
3282 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3283 intent, r);
3284
3285 if (sourceRecord == null) {
3286 // This activity is not being started from another... in this
3287 // case we -always- start a new task.
3288 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003289 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 -08003290 + intent);
3291 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3292 }
3293 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3294 // The original activity who is starting us is running as a single
3295 // instance... this new activity it is starting must go on its
3296 // own task.
3297 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3298 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3299 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3300 // The activity being started is a single instance... it always
3301 // gets launched into its own task.
3302 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3303 }
3304
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003305 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 // For whatever reason this activity is being launched into a new
3307 // task... yet the caller has requested a result back. Well, that
3308 // is pretty messed up, so instead immediately send back a cancel
3309 // and let the new task continue launched as normal without a
3310 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003311 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003313 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 Activity.RESULT_CANCELED, null);
3315 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 }
3317
3318 boolean addingToTask = false;
3319 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3320 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3321 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3322 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3323 // If bring to front is requested, and no result is requested, and
3324 // we can find a task that was started with this same
3325 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003326 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003327 // See if there is a task to bring to the front. If this is
3328 // a SINGLE_INSTANCE activity, there can be one and only one
3329 // instance of it in the history, and it is always in its own
3330 // unique task, so we do a special search.
3331 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3332 ? findTaskLocked(intent, r.info)
3333 : findActivityLocked(intent, r.info);
3334 if (taskTop != null) {
3335 if (taskTop.task.intent == null) {
3336 // This task was started because of movement of
3337 // the activity based on affinity... now that we
3338 // are actually launching it, we can assign the
3339 // base intent.
3340 taskTop.task.setIntent(intent, r.info);
3341 }
3342 // If the target task is not in the front, then we need
3343 // to bring it to the front... except... well, with
3344 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3345 // to have the same behavior as if a new instance was
3346 // being started, which means not bringing it to the front
3347 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003348 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349 if (curTop.task != taskTop.task) {
3350 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3351 boolean callerAtFront = sourceRecord == null
3352 || curTop.task == sourceRecord.task;
3353 if (callerAtFront) {
3354 // We really do want to push this one into the
3355 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003356 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 }
3358 }
3359 // If the caller has requested that the target task be
3360 // reset, then do so.
3361 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3362 taskTop = resetTaskIfNeededLocked(taskTop, r);
3363 }
3364 if (onlyIfNeeded) {
3365 // We don't need to start a new activity, and
3366 // the client said not to do anything if that
3367 // is the case, so this is it! And for paranoia, make
3368 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003369 if (doResume) {
3370 resumeTopActivityLocked(null);
3371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 return START_RETURN_INTENT_TO_CALLER;
3373 }
3374 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3375 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3376 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3377 // In this situation we want to remove all activities
3378 // from the task up to the one being started. In most
3379 // cases this means we are resetting the task to its
3380 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003381 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003382 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 if (top != null) {
3384 if (top.frontOfTask) {
3385 // Activity aliases may mean we use different
3386 // intents for the top activity, so make sure
3387 // the task now has the identity of the new
3388 // intent.
3389 top.task.setIntent(r.intent, r.info);
3390 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003391 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 deliverNewIntentLocked(top, r.intent);
3393 } else {
3394 // A special case: we need to
3395 // start the activity because it is not currently
3396 // running, and the caller has asked to clear the
3397 // current task to have this activity at the top.
3398 addingToTask = true;
3399 // Now pretend like this activity is being started
3400 // by the top of its task, so it is put in the
3401 // right place.
3402 sourceRecord = taskTop;
3403 }
3404 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3405 // In this case the top activity on the task is the
3406 // same as the one being launched, so we take that
3407 // as a request to bring the task to the foreground.
3408 // If the top activity in the task is the root
3409 // activity, deliver this new intent to it if it
3410 // desires.
3411 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3412 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003413 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003414 if (taskTop.frontOfTask) {
3415 taskTop.task.setIntent(r.intent, r.info);
3416 }
3417 deliverNewIntentLocked(taskTop, r.intent);
3418 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3419 // In this case we are launching the root activity
3420 // of the task, but with a different intent. We
3421 // should start a new instance on top.
3422 addingToTask = true;
3423 sourceRecord = taskTop;
3424 }
3425 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3426 // In this case an activity is being launched in to an
3427 // existing task, without resetting that task. This
3428 // is typically the situation of launching an activity
3429 // from a notification or shortcut. We want to place
3430 // the new activity on top of the current task.
3431 addingToTask = true;
3432 sourceRecord = taskTop;
3433 } else if (!taskTop.task.rootWasReset) {
3434 // In this case we are launching in to an existing task
3435 // that has not yet been started from its front door.
3436 // The current task has been brought to the front.
3437 // Ideally, we'd probably like to place this new task
3438 // at the bottom of its stack, but that's a little hard
3439 // to do with the current organization of the code so
3440 // for now we'll just drop it.
3441 taskTop.task.setIntent(r.intent, r.info);
3442 }
3443 if (!addingToTask) {
3444 // We didn't do anything... but it was needed (a.k.a., client
3445 // don't use that intent!) And for paranoia, make
3446 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003447 if (doResume) {
3448 resumeTopActivityLocked(null);
3449 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 return START_TASK_TO_FRONT;
3451 }
3452 }
3453 }
3454 }
3455
3456 //String uri = r.intent.toURI();
3457 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003458 //Slog.i(TAG, "Given intent: " + r.intent);
3459 //Slog.i(TAG, "URI is: " + uri);
3460 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003461
3462 if (r.packageName != null) {
3463 // If the activity being launched is the same as the one currently
3464 // at the top, then we need to check if it should only be launched
3465 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003466 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3467 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 if (top.realActivity.equals(r.realActivity)) {
3469 if (top.app != null && top.app.thread != null) {
3470 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3471 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3472 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003473 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 // For paranoia, make sure we have correctly
3475 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003476 if (doResume) {
3477 resumeTopActivityLocked(null);
3478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 if (onlyIfNeeded) {
3480 // We don't need to start a new activity, and
3481 // the client said not to do anything if that
3482 // is the case, so this is it!
3483 return START_RETURN_INTENT_TO_CALLER;
3484 }
3485 deliverNewIntentLocked(top, r.intent);
3486 return START_DELIVERED_TO_TOP;
3487 }
3488 }
3489 }
3490 }
3491
3492 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003493 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003495 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 Activity.RESULT_CANCELED, null);
3497 }
3498 return START_CLASS_NOT_FOUND;
3499 }
3500
3501 boolean newTask = false;
3502
3503 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003504 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003505 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3506 // todo: should do better management of integers.
3507 mCurTask++;
3508 if (mCurTask <= 0) {
3509 mCurTask = 1;
3510 }
3511 r.task = new TaskRecord(mCurTask, r.info, intent,
3512 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003513 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 + " in new task " + r.task);
3515 newTask = true;
3516 addRecentTask(r.task);
3517
3518 } else if (sourceRecord != null) {
3519 if (!addingToTask &&
3520 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3521 // In this case, we are adding the activity to an existing
3522 // task, but the caller has asked to clear that task if the
3523 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003524 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003525 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003527 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 deliverNewIntentLocked(top, r.intent);
3529 // For paranoia, make sure we have correctly
3530 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003531 if (doResume) {
3532 resumeTopActivityLocked(null);
3533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003534 return START_DELIVERED_TO_TOP;
3535 }
3536 } else if (!addingToTask &&
3537 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3538 // In this case, we are launching an activity in our own task
3539 // that may already be running somewhere in the history, and
3540 // we want to shuffle it to the front of the stack if so.
3541 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3542 if (where >= 0) {
3543 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003544 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003546 if (doResume) {
3547 resumeTopActivityLocked(null);
3548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003549 return START_DELIVERED_TO_TOP;
3550 }
3551 }
3552 // An existing activity is starting this new activity, so we want
3553 // to keep the new one in the same task as the one that is starting
3554 // it.
3555 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003556 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 + " in existing task " + r.task);
3558
3559 } else {
3560 // This not being started from an existing activity, and not part
3561 // of a new task... just put it in the top task, though these days
3562 // this case should never happen.
3563 final int N = mHistory.size();
3564 HistoryRecord prev =
3565 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3566 r.task = prev != null
3567 ? prev.task
3568 : new TaskRecord(mCurTask, r.info, intent,
3569 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003570 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003571 + " in new guessed " + r.task);
3572 }
3573 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003574 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003575 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003576 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003577 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 return START_SUCCESS;
3579 }
3580
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003581 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3582 long thisTime, long totalTime) {
3583 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3584 WaitResult w = mWaitingActivityLaunched.get(i);
3585 w.timeout = timeout;
3586 if (r != null) {
3587 w.who = new ComponentName(r.info.packageName, r.info.name);
3588 }
3589 w.thisTime = thisTime;
3590 w.totalTime = totalTime;
3591 }
3592 notify();
3593 }
3594
3595 void reportActivityVisibleLocked(HistoryRecord r) {
3596 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3597 WaitResult w = mWaitingActivityVisible.get(i);
3598 w.timeout = false;
3599 if (r != null) {
3600 w.who = new ComponentName(r.info.packageName, r.info.name);
3601 }
3602 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3603 w.thisTime = w.totalTime;
3604 }
3605 notify();
3606 }
3607
3608 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3610 int grantedMode, IBinder resultTo,
3611 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003612 boolean debug, WaitResult outResult) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 // Refuse possible leaked file descriptors
3614 if (intent != null && intent.hasFileDescriptors()) {
3615 throw new IllegalArgumentException("File descriptors passed in Intent");
3616 }
3617
The Android Open Source Project4df24232009-03-05 14:34:35 -08003618 final boolean componentSpecified = intent.getComponent() != null;
3619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 // Don't modify the client's object!
3621 intent = new Intent(intent);
3622
3623 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 ActivityInfo aInfo;
3625 try {
3626 ResolveInfo rInfo =
3627 ActivityThread.getPackageManager().resolveIntent(
3628 intent, resolvedType,
3629 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003630 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003631 aInfo = rInfo != null ? rInfo.activityInfo : null;
3632 } catch (RemoteException e) {
3633 aInfo = null;
3634 }
3635
3636 if (aInfo != null) {
3637 // Store the found target back into the intent, because now that
3638 // we have it we never want to do this again. For example, if the
3639 // user navigates back to this point in the history, we should
3640 // always restart the exact same activity.
3641 intent.setComponent(new ComponentName(
3642 aInfo.applicationInfo.packageName, aInfo.name));
3643
3644 // Don't debug things in the system process
3645 if (debug) {
3646 if (!aInfo.processName.equals("system")) {
3647 setDebugApp(aInfo.processName, true, false);
3648 }
3649 }
3650 }
3651
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003652 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003653 int callingPid;
3654 int callingUid;
3655 if (caller == null) {
3656 callingPid = Binder.getCallingPid();
3657 callingUid = Binder.getCallingUid();
3658 } else {
3659 callingPid = callingUid = -1;
3660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 final long origId = Binder.clearCallingIdentity();
3662 int res = startActivityLocked(caller, intent, resolvedType,
3663 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003664 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003665 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003666 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003667
3668 if (outResult != null) {
3669 outResult.result = res;
3670 if (res == IActivityManager.START_SUCCESS) {
3671 mWaitingActivityLaunched.add(outResult);
3672 do {
3673 try {
3674 wait();
3675 } catch (InterruptedException e) {
3676 }
3677 } while (!outResult.timeout && outResult.who == null);
3678 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3679 HistoryRecord r = this.topRunningActivityLocked(null);
3680 if (r.nowVisible) {
3681 outResult.timeout = false;
3682 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3683 outResult.totalTime = 0;
3684 outResult.thisTime = 0;
3685 } else {
3686 outResult.thisTime = SystemClock.uptimeMillis();
3687 mWaitingActivityVisible.add(outResult);
3688 do {
3689 try {
3690 wait();
3691 } catch (InterruptedException e) {
3692 }
3693 } while (!outResult.timeout && outResult.who == null);
3694 }
3695 }
3696 }
3697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 return res;
3699 }
3700 }
3701
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003702 public final int startActivity(IApplicationThread caller,
3703 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3704 int grantedMode, IBinder resultTo,
3705 String resultWho, int requestCode, boolean onlyIfNeeded,
3706 boolean debug) {
3707 return startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3708 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, null);
3709 }
3710
3711 public final WaitResult startActivityAndWait(IApplicationThread caller,
3712 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3713 int grantedMode, IBinder resultTo,
3714 String resultWho, int requestCode, boolean onlyIfNeeded,
3715 boolean debug) {
3716 WaitResult res = new WaitResult();
3717 startActivityMayWait(caller, intent, resolvedType, grantedUriPermissions,
3718 grantedMode, resultTo, resultWho, requestCode, onlyIfNeeded, debug, res);
3719 return res;
3720 }
3721
3722 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003723 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003724 IBinder resultTo, String resultWho, int requestCode,
3725 int flagsMask, int flagsValues) {
3726 // Refuse possible leaked file descriptors
3727 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3728 throw new IllegalArgumentException("File descriptors passed in Intent");
3729 }
3730
3731 IIntentSender sender = intent.getTarget();
3732 if (!(sender instanceof PendingIntentRecord)) {
3733 throw new IllegalArgumentException("Bad PendingIntent object");
3734 }
3735
3736 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003737
3738 synchronized (this) {
3739 // If this is coming from the currently resumed activity, it is
3740 // effectively saying that app switches are allowed at this point.
3741 if (mResumedActivity != null
3742 && mResumedActivity.info.applicationInfo.uid ==
3743 Binder.getCallingUid()) {
3744 mAppSwitchesAllowedTime = 0;
3745 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003746 }
3747
3748 return pir.sendInner(0, fillInIntent, resolvedType,
3749 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3750 }
3751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 public boolean startNextMatchingActivity(IBinder callingActivity,
3753 Intent intent) {
3754 // Refuse possible leaked file descriptors
3755 if (intent != null && intent.hasFileDescriptors() == true) {
3756 throw new IllegalArgumentException("File descriptors passed in Intent");
3757 }
3758
3759 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003760 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003761 if (index < 0) {
3762 return false;
3763 }
3764 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3765 if (r.app == null || r.app.thread == null) {
3766 // The caller is not running... d'oh!
3767 return false;
3768 }
3769 intent = new Intent(intent);
3770 // The caller is not allowed to change the data.
3771 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3772 // And we are resetting to find the next component...
3773 intent.setComponent(null);
3774
3775 ActivityInfo aInfo = null;
3776 try {
3777 List<ResolveInfo> resolves =
3778 ActivityThread.getPackageManager().queryIntentActivities(
3779 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003780 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781
3782 // Look for the original activity in the list...
3783 final int N = resolves != null ? resolves.size() : 0;
3784 for (int i=0; i<N; i++) {
3785 ResolveInfo rInfo = resolves.get(i);
3786 if (rInfo.activityInfo.packageName.equals(r.packageName)
3787 && rInfo.activityInfo.name.equals(r.info.name)) {
3788 // We found the current one... the next matching is
3789 // after it.
3790 i++;
3791 if (i<N) {
3792 aInfo = resolves.get(i).activityInfo;
3793 }
3794 break;
3795 }
3796 }
3797 } catch (RemoteException e) {
3798 }
3799
3800 if (aInfo == null) {
3801 // Nobody who is next!
3802 return false;
3803 }
3804
3805 intent.setComponent(new ComponentName(
3806 aInfo.applicationInfo.packageName, aInfo.name));
3807 intent.setFlags(intent.getFlags()&~(
3808 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3809 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3810 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3811 Intent.FLAG_ACTIVITY_NEW_TASK));
3812
3813 // Okay now we need to start the new activity, replacing the
3814 // currently running activity. This is a little tricky because
3815 // we want to start the new one as if the current one is finished,
3816 // but not finish the current one first so that there is no flicker.
3817 // And thus...
3818 final boolean wasFinishing = r.finishing;
3819 r.finishing = true;
3820
3821 // Propagate reply information over to the new activity.
3822 final HistoryRecord resultTo = r.resultTo;
3823 final String resultWho = r.resultWho;
3824 final int requestCode = r.requestCode;
3825 r.resultTo = null;
3826 if (resultTo != null) {
3827 resultTo.removeResultsLocked(r, resultWho, requestCode);
3828 }
3829
3830 final long origId = Binder.clearCallingIdentity();
3831 // XXX we are not dealing with propagating grantedUriPermissions...
3832 // those are not yet exposed to user code, so there is no need.
3833 int res = startActivityLocked(r.app.thread, intent,
3834 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003835 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 Binder.restoreCallingIdentity(origId);
3837
3838 r.finishing = wasFinishing;
3839 if (res != START_SUCCESS) {
3840 return false;
3841 }
3842 return true;
3843 }
3844 }
3845
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003846 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003847 Intent intent, String resolvedType, IBinder resultTo,
3848 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003849
3850 // This is so super not safe, that only the system (or okay root)
3851 // can do it.
3852 final int callingUid = Binder.getCallingUid();
3853 if (callingUid != 0 && callingUid != Process.myUid()) {
3854 throw new SecurityException(
3855 "startActivityInPackage only available to the system");
3856 }
3857
The Android Open Source Project4df24232009-03-05 14:34:35 -08003858 final boolean componentSpecified = intent.getComponent() != null;
3859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 // Don't modify the client's object!
3861 intent = new Intent(intent);
3862
3863 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 ActivityInfo aInfo;
3865 try {
3866 ResolveInfo rInfo =
3867 ActivityThread.getPackageManager().resolveIntent(
3868 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003869 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 aInfo = rInfo != null ? rInfo.activityInfo : null;
3871 } catch (RemoteException e) {
3872 aInfo = null;
3873 }
3874
3875 if (aInfo != null) {
3876 // Store the found target back into the intent, because now that
3877 // we have it we never want to do this again. For example, if the
3878 // user navigates back to this point in the history, we should
3879 // always restart the exact same activity.
3880 intent.setComponent(new ComponentName(
3881 aInfo.applicationInfo.packageName, aInfo.name));
3882 }
3883
3884 synchronized(this) {
3885 return startActivityLocked(null, intent, resolvedType,
3886 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003887 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 }
3889 }
3890
3891 private final void addRecentTask(TaskRecord task) {
3892 // Remove any existing entries that are the same kind of task.
3893 int N = mRecentTasks.size();
3894 for (int i=0; i<N; i++) {
3895 TaskRecord tr = mRecentTasks.get(i);
3896 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3897 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3898 mRecentTasks.remove(i);
3899 i--;
3900 N--;
3901 if (task.intent == null) {
3902 // If the new recent task we are adding is not fully
3903 // specified, then replace it with the existing recent task.
3904 task = tr;
3905 }
3906 }
3907 }
3908 if (N >= MAX_RECENT_TASKS) {
3909 mRecentTasks.remove(N-1);
3910 }
3911 mRecentTasks.add(0, task);
3912 }
3913
3914 public void setRequestedOrientation(IBinder token,
3915 int requestedOrientation) {
3916 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003917 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 if (index < 0) {
3919 return;
3920 }
3921 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3922 final long origId = Binder.clearCallingIdentity();
3923 mWindowManager.setAppOrientation(r, requestedOrientation);
3924 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003925 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 r.mayFreezeScreenLocked(r.app) ? r : null);
3927 if (config != null) {
3928 r.frozenBeforeDestroy = true;
3929 if (!updateConfigurationLocked(config, r)) {
3930 resumeTopActivityLocked(null);
3931 }
3932 }
3933 Binder.restoreCallingIdentity(origId);
3934 }
3935 }
3936
3937 public int getRequestedOrientation(IBinder token) {
3938 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003939 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 if (index < 0) {
3941 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3942 }
3943 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3944 return mWindowManager.getAppOrientation(r);
3945 }
3946 }
3947
3948 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003949 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3951 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3952 if (!r.finishing) {
3953 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
3954 "no-history");
3955 }
3956 } else if (r.app != null && r.app.thread != null) {
3957 if (mFocusedActivity == r) {
3958 setFocusedActivityLocked(topRunningActivityLocked(null));
3959 }
3960 r.resumeKeyDispatchingLocked();
3961 try {
3962 r.stopped = false;
3963 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003964 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965 TAG, "Stopping visible=" + r.visible + " for " + r);
3966 if (!r.visible) {
3967 mWindowManager.setAppVisibility(r, false);
3968 }
3969 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
3970 } catch (Exception e) {
3971 // Maybe just ignore exceptions here... if the process
3972 // has crashed, our death notification will clean things
3973 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003974 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003975 // Just in case, assume it to be stopped.
3976 r.stopped = true;
3977 r.state = ActivityState.STOPPED;
3978 if (r.configDestroy) {
3979 destroyActivityLocked(r, true);
3980 }
3981 }
3982 }
3983 }
3984
3985 /**
3986 * @return Returns true if the activity is being finished, false if for
3987 * some reason it is being left as-is.
3988 */
3989 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3990 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003991 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003992 TAG, "Finishing activity: token=" + token
3993 + ", result=" + resultCode + ", data=" + resultData);
3994
Dianne Hackborn75b03852009-06-12 15:43:26 -07003995 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003996 if (index < 0) {
3997 return false;
3998 }
3999 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4000
4001 // Is this the last activity left?
4002 boolean lastActivity = true;
4003 for (int i=mHistory.size()-1; i>=0; i--) {
4004 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4005 if (!p.finishing && p != r) {
4006 lastActivity = false;
4007 break;
4008 }
4009 }
4010
4011 // If this is the last activity, but it is the home activity, then
4012 // just don't finish it.
4013 if (lastActivity) {
4014 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4015 return false;
4016 }
4017 }
4018
4019 finishActivityLocked(r, index, resultCode, resultData, reason);
4020 return true;
4021 }
4022
4023 /**
4024 * @return Returns true if this activity has been removed from the history
4025 * list, or false if it is still in the list and will be removed later.
4026 */
4027 private final boolean finishActivityLocked(HistoryRecord r, int index,
4028 int resultCode, Intent resultData, String reason) {
4029 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004030 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004031 return false;
4032 }
4033
4034 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004035 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004036 System.identityHashCode(r),
4037 r.task.taskId, r.shortComponentName, reason);
4038 r.task.numActivities--;
4039 if (r.frontOfTask && index < (mHistory.size()-1)) {
4040 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4041 if (next.task == r.task) {
4042 next.frontOfTask = true;
4043 }
4044 }
4045
4046 r.pauseKeyDispatchingLocked();
4047 if (mFocusedActivity == r) {
4048 setFocusedActivityLocked(topRunningActivityLocked(null));
4049 }
4050
4051 // send the result
4052 HistoryRecord resultTo = r.resultTo;
4053 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004054 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004055 + " who=" + r.resultWho + " req=" + r.requestCode
4056 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 if (r.info.applicationInfo.uid > 0) {
4058 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4059 r.packageName, resultData, r);
4060 }
4061 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4062 resultData);
4063 r.resultTo = null;
4064 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004065 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004066
4067 // Make sure this HistoryRecord is not holding on to other resources,
4068 // because clients have remote IPC references to this object so we
4069 // can't assume that will go away and want to avoid circular IPC refs.
4070 r.results = null;
4071 r.pendingResults = null;
4072 r.newIntents = null;
4073 r.icicle = null;
4074
4075 if (mPendingThumbnails.size() > 0) {
4076 // There are clients waiting to receive thumbnails so, in case
4077 // this is an activity that someone is waiting for, add it
4078 // to the pending list so we can correctly update the clients.
4079 mCancelledThumbnails.add(r);
4080 }
4081
4082 if (mResumedActivity == r) {
4083 boolean endTask = index <= 0
4084 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004085 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086 "Prepare close transition: finishing " + r);
4087 mWindowManager.prepareAppTransition(endTask
4088 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4089 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4090
4091 // Tell window manager to prepare for this one to be removed.
4092 mWindowManager.setAppVisibility(r, false);
4093
4094 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004095 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4096 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 startPausingLocked(false, false);
4098 }
4099
4100 } else if (r.state != ActivityState.PAUSING) {
4101 // If the activity is PAUSING, we will complete the finish once
4102 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004103 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 return finishCurrentActivityLocked(r, index,
4105 FINISH_AFTER_PAUSE) == null;
4106 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004107 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108 }
4109
4110 return false;
4111 }
4112
4113 private static final int FINISH_IMMEDIATELY = 0;
4114 private static final int FINISH_AFTER_PAUSE = 1;
4115 private static final int FINISH_AFTER_VISIBLE = 2;
4116
4117 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4118 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004119 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004120 if (index < 0) {
4121 return null;
4122 }
4123
4124 return finishCurrentActivityLocked(r, index, mode);
4125 }
4126
4127 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4128 int index, int mode) {
4129 // First things first: if this activity is currently visible,
4130 // and the resumed activity is not yet visible, then hold off on
4131 // finishing until the resumed one becomes visible.
4132 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4133 if (!mStoppingActivities.contains(r)) {
4134 mStoppingActivities.add(r);
4135 if (mStoppingActivities.size() > 3) {
4136 // If we already have a few activities waiting to stop,
4137 // then give up on things going idle and start clearing
4138 // them out.
4139 Message msg = Message.obtain();
4140 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4141 mHandler.sendMessage(msg);
4142 }
4143 }
4144 r.state = ActivityState.STOPPING;
4145 updateOomAdjLocked();
4146 return r;
4147 }
4148
4149 // make sure the record is cleaned out of other places.
4150 mStoppingActivities.remove(r);
4151 mWaitingVisibleActivities.remove(r);
4152 if (mResumedActivity == r) {
4153 mResumedActivity = null;
4154 }
4155 final ActivityState prevState = r.state;
4156 r.state = ActivityState.FINISHING;
4157
4158 if (mode == FINISH_IMMEDIATELY
4159 || prevState == ActivityState.STOPPED
4160 || prevState == ActivityState.INITIALIZING) {
4161 // If this activity is already stopped, we can just finish
4162 // it right now.
4163 return destroyActivityLocked(r, true) ? null : r;
4164 } else {
4165 // Need to go through the full pause cycle to get this
4166 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004167 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 mFinishingActivities.add(r);
4169 resumeTopActivityLocked(null);
4170 }
4171 return r;
4172 }
4173
4174 /**
4175 * This is the internal entry point for handling Activity.finish().
4176 *
4177 * @param token The Binder token referencing the Activity we want to finish.
4178 * @param resultCode Result code, if any, from this Activity.
4179 * @param resultData Result data (Intent), if any, from this Activity.
4180 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004181 * @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 -08004182 */
4183 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4184 // Refuse possible leaked file descriptors
4185 if (resultData != null && resultData.hasFileDescriptors() == true) {
4186 throw new IllegalArgumentException("File descriptors passed in Intent");
4187 }
4188
4189 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004190 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004191 // Find the first activity that is not finishing.
4192 HistoryRecord next = topRunningActivityLocked(token, 0);
4193 if (next != null) {
4194 // ask watcher if this is allowed
4195 boolean resumeOK = true;
4196 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004197 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004198 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004199 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200 }
4201
4202 if (!resumeOK) {
4203 return false;
4204 }
4205 }
4206 }
4207 final long origId = Binder.clearCallingIdentity();
4208 boolean res = requestFinishActivityLocked(token, resultCode,
4209 resultData, "app-request");
4210 Binder.restoreCallingIdentity(origId);
4211 return res;
4212 }
4213 }
4214
4215 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4216 String resultWho, int requestCode, int resultCode, Intent data) {
4217
4218 if (callingUid > 0) {
4219 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4220 data, r);
4221 }
4222
Joe Onorato8a9b2202010-02-26 18:56:32 -08004223 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004224 + " : who=" + resultWho + " req=" + requestCode
4225 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004226 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4227 try {
4228 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4229 list.add(new ResultInfo(resultWho, requestCode,
4230 resultCode, data));
4231 r.app.thread.scheduleSendResult(r, list);
4232 return;
4233 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004234 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004235 }
4236 }
4237
4238 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4239 }
4240
4241 public final void finishSubActivity(IBinder token, String resultWho,
4242 int requestCode) {
4243 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004244 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 if (index < 0) {
4246 return;
4247 }
4248 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4249
4250 final long origId = Binder.clearCallingIdentity();
4251
4252 int i;
4253 for (i=mHistory.size()-1; i>=0; i--) {
4254 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4255 if (r.resultTo == self && r.requestCode == requestCode) {
4256 if ((r.resultWho == null && resultWho == null) ||
4257 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4258 finishActivityLocked(r, i,
4259 Activity.RESULT_CANCELED, null, "request-sub");
4260 }
4261 }
4262 }
4263
4264 Binder.restoreCallingIdentity(origId);
4265 }
4266 }
4267
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004268 public void overridePendingTransition(IBinder token, String packageName,
4269 int enterAnim, int exitAnim) {
4270 synchronized(this) {
4271 int index = indexOfTokenLocked(token);
4272 if (index < 0) {
4273 return;
4274 }
4275 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4276
4277 final long origId = Binder.clearCallingIdentity();
4278
4279 if (self.state == ActivityState.RESUMED
4280 || self.state == ActivityState.PAUSING) {
4281 mWindowManager.overridePendingAppTransition(packageName,
4282 enterAnim, exitAnim);
4283 }
4284
4285 Binder.restoreCallingIdentity(origId);
4286 }
4287 }
4288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 /**
4290 * Perform clean-up of service connections in an activity record.
4291 */
4292 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4293 // Throw away any services that have been bound by this activity.
4294 if (r.connections != null) {
4295 Iterator<ConnectionRecord> it = r.connections.iterator();
4296 while (it.hasNext()) {
4297 ConnectionRecord c = it.next();
4298 removeConnectionLocked(c, null, r);
4299 }
4300 r.connections = null;
4301 }
4302 }
4303
4304 /**
4305 * Perform the common clean-up of an activity record. This is called both
4306 * as part of destroyActivityLocked() (when destroying the client-side
4307 * representation) and cleaning things up as a result of its hosting
4308 * processing going away, in which case there is no remaining client-side
4309 * state to destroy so only the cleanup here is needed.
4310 */
4311 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4312 if (mResumedActivity == r) {
4313 mResumedActivity = null;
4314 }
4315 if (mFocusedActivity == r) {
4316 mFocusedActivity = null;
4317 }
4318
4319 r.configDestroy = false;
4320 r.frozenBeforeDestroy = false;
4321
4322 // Make sure this record is no longer in the pending finishes list.
4323 // This could happen, for example, if we are trimming activities
4324 // down to the max limit while they are still waiting to finish.
4325 mFinishingActivities.remove(r);
4326 mWaitingVisibleActivities.remove(r);
4327
4328 // Remove any pending results.
4329 if (r.finishing && r.pendingResults != null) {
4330 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4331 PendingIntentRecord rec = apr.get();
4332 if (rec != null) {
4333 cancelIntentSenderLocked(rec, false);
4334 }
4335 }
4336 r.pendingResults = null;
4337 }
4338
4339 if (cleanServices) {
4340 cleanUpActivityServicesLocked(r);
4341 }
4342
4343 if (mPendingThumbnails.size() > 0) {
4344 // There are clients waiting to receive thumbnails so, in case
4345 // this is an activity that someone is waiting for, add it
4346 // to the pending list so we can correctly update the clients.
4347 mCancelledThumbnails.add(r);
4348 }
4349
4350 // Get rid of any pending idle timeouts.
4351 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4352 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4353 }
4354
4355 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4356 if (r.state != ActivityState.DESTROYED) {
4357 mHistory.remove(r);
4358 r.inHistory = false;
4359 r.state = ActivityState.DESTROYED;
4360 mWindowManager.removeAppToken(r);
4361 if (VALIDATE_TOKENS) {
4362 mWindowManager.validateAppTokens(mHistory);
4363 }
4364 cleanUpActivityServicesLocked(r);
4365 removeActivityUriPermissionsLocked(r);
4366 }
4367 }
4368
4369 /**
4370 * Destroy the current CLIENT SIDE instance of an activity. This may be
4371 * called both when actually finishing an activity, or when performing
4372 * a configuration switch where we destroy the current client-side object
4373 * but then create a new client-side object for this same HistoryRecord.
4374 */
4375 private final boolean destroyActivityLocked(HistoryRecord r,
4376 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004377 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004378 TAG, "Removing activity: token=" + r
4379 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004380 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004381 System.identityHashCode(r),
4382 r.task.taskId, r.shortComponentName);
4383
4384 boolean removedFromHistory = false;
4385
4386 cleanUpActivityLocked(r, false);
4387
Dianne Hackborn03abb812010-01-04 18:43:19 -08004388 final boolean hadApp = r.app != null;
4389
4390 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 if (removeFromApp) {
4392 int idx = r.app.activities.indexOf(r);
4393 if (idx >= 0) {
4394 r.app.activities.remove(idx);
4395 }
4396 if (r.persistent) {
4397 decPersistentCountLocked(r.app);
4398 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004399 if (r.app.activities.size() == 0) {
4400 // No longer have activities, so update location in
4401 // LRU list.
4402 updateLruProcessLocked(r.app, true, false);
4403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004404 }
4405
4406 boolean skipDestroy = false;
4407
4408 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004409 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4411 r.configChangeFlags);
4412 } catch (Exception e) {
4413 // We can just ignore exceptions here... if the process
4414 // has crashed, our death notification will clean things
4415 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004416 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 if (r.finishing) {
4418 removeActivityFromHistoryLocked(r);
4419 removedFromHistory = true;
4420 skipDestroy = true;
4421 }
4422 }
4423
4424 r.app = null;
4425 r.nowVisible = false;
4426
4427 if (r.finishing && !skipDestroy) {
4428 r.state = ActivityState.DESTROYING;
4429 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4430 msg.obj = r;
4431 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4432 } else {
4433 r.state = ActivityState.DESTROYED;
4434 }
4435 } else {
4436 // remove this record from the history.
4437 if (r.finishing) {
4438 removeActivityFromHistoryLocked(r);
4439 removedFromHistory = true;
4440 } else {
4441 r.state = ActivityState.DESTROYED;
4442 }
4443 }
4444
4445 r.configChangeFlags = 0;
4446
Dianne Hackborn03abb812010-01-04 18:43:19 -08004447 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004448 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004449 }
4450
4451 return removedFromHistory;
4452 }
4453
Dianne Hackborn03abb812010-01-04 18:43:19 -08004454 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004456 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 TAG, "Removing app " + app + " from list " + list
4458 + " with " + i + " entries");
4459 while (i > 0) {
4460 i--;
4461 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004462 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4464 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004465 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 list.remove(i);
4467 }
4468 }
4469 }
4470
4471 /**
4472 * Main function for removing an existing process from the activity manager
4473 * as a result of that process going away. Clears out all connections
4474 * to the process.
4475 */
4476 private final void handleAppDiedLocked(ProcessRecord app,
4477 boolean restarting) {
4478 cleanUpApplicationRecordLocked(app, restarting, -1);
4479 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004480 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004481 }
4482
4483 // Just in case...
4484 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004485 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486 mPausingActivity = null;
4487 }
4488 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4489 mLastPausedActivity = null;
4490 }
4491
4492 // Remove this application's activities from active lists.
4493 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4494 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4495 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4496 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4497
4498 boolean atTop = true;
4499 boolean hasVisibleActivities = false;
4500
4501 // Clean out the history list.
4502 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004503 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 TAG, "Removing app " + app + " from history with " + i + " entries");
4505 while (i > 0) {
4506 i--;
4507 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004508 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004509 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4510 if (r.app == app) {
4511 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004512 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 TAG, "Removing this entry! frozen=" + r.haveState
4514 + " finishing=" + r.finishing);
4515 mHistory.remove(i);
4516
4517 r.inHistory = false;
4518 mWindowManager.removeAppToken(r);
4519 if (VALIDATE_TOKENS) {
4520 mWindowManager.validateAppTokens(mHistory);
4521 }
4522 removeActivityUriPermissionsLocked(r);
4523
4524 } else {
4525 // We have the current state for this activity, so
4526 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004527 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004528 TAG, "Keeping entry, setting app to null");
4529 if (r.visible) {
4530 hasVisibleActivities = true;
4531 }
4532 r.app = null;
4533 r.nowVisible = false;
4534 if (!r.haveState) {
4535 r.icicle = null;
4536 }
4537 }
4538
4539 cleanUpActivityLocked(r, true);
4540 r.state = ActivityState.STOPPED;
4541 }
4542 atTop = false;
4543 }
4544
4545 app.activities.clear();
4546
4547 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004548 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004549 + " running instrumentation " + app.instrumentationClass);
4550 Bundle info = new Bundle();
4551 info.putString("shortMsg", "Process crashed.");
4552 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4553 }
4554
4555 if (!restarting) {
4556 if (!resumeTopActivityLocked(null)) {
4557 // If there was nothing to resume, and we are not already
4558 // restarting this process, but there is a visible activity that
4559 // is hosted by the process... then make sure all visible
4560 // activities are running, taking care of restarting this
4561 // process.
4562 if (hasVisibleActivities) {
4563 ensureActivitiesVisibleLocked(null, 0);
4564 }
4565 }
4566 }
4567 }
4568
4569 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4570 IBinder threadBinder = thread.asBinder();
4571
4572 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004573 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4574 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4576 return i;
4577 }
4578 }
4579 return -1;
4580 }
4581
4582 private final ProcessRecord getRecordForAppLocked(
4583 IApplicationThread thread) {
4584 if (thread == null) {
4585 return null;
4586 }
4587
4588 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004589 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004590 }
4591
4592 private final void appDiedLocked(ProcessRecord app, int pid,
4593 IApplicationThread thread) {
4594
4595 mProcDeaths[0]++;
4596
Magnus Edlund7bb25812010-02-24 15:45:06 +01004597 // Clean up already done if the process has been re-started.
4598 if (app.pid == pid && app.thread != null &&
4599 app.thread.asBinder() == thread.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004600 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004601 + ") has died.");
Doug Zongker2bec3d42009-12-04 12:52:44 -08004602 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004603 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004604 TAG, "Dying app: " + app + ", pid: " + pid
4605 + ", thread: " + thread.asBinder());
4606 boolean doLowMem = app.instrumentationClass == null;
4607 handleAppDiedLocked(app, false);
4608
4609 if (doLowMem) {
4610 // If there are no longer any background processes running,
4611 // and the app that died was not running instrumentation,
4612 // then tell everyone we are now low on memory.
4613 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004614 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4615 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004616 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4617 haveBg = true;
4618 break;
4619 }
4620 }
4621
4622 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004623 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004624 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004625 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004626 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4627 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004628 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004629 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4630 // The low memory report is overriding any current
4631 // state for a GC request. Make sure to do
4632 // visible/foreground processes first.
4633 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4634 rec.lastRequestedGc = 0;
4635 } else {
4636 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004638 rec.reportLowMemory = true;
4639 rec.lastLowMemory = now;
4640 mProcessesToGc.remove(rec);
4641 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004642 }
4643 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004644 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 }
4646 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004647 } else if (app.pid != pid) {
4648 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004649 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004650 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004651 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004652 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004653 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004654 + thread.asBinder());
4655 }
4656 }
4657
Dan Egnor42471dd2010-01-07 17:25:22 -08004658 /**
4659 * If a stack trace dump file is configured, dump process stack traces.
4660 * @param pids of dalvik VM processes to dump stack traces for
4661 * @return file containing stack traces, or null if no dump file is configured
4662 */
4663 private static File dumpStackTraces(ArrayList<Integer> pids) {
4664 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4665 if (tracesPath == null || tracesPath.length() == 0) {
4666 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004667 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004668
4669 File tracesFile = new File(tracesPath);
4670 try {
4671 File tracesDir = tracesFile.getParentFile();
4672 if (!tracesDir.exists()) tracesFile.mkdirs();
4673 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4674
4675 if (tracesFile.exists()) tracesFile.delete();
4676 tracesFile.createNewFile();
4677 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4678 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004679 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004680 return null;
4681 }
4682
4683 // Use a FileObserver to detect when traces finish writing.
4684 // The order of traces is considered important to maintain for legibility.
4685 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4686 public synchronized void onEvent(int event, String path) { notify(); }
4687 };
4688
4689 try {
4690 observer.startWatching();
4691 int num = pids.size();
4692 for (int i = 0; i < num; i++) {
4693 synchronized (observer) {
4694 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4695 observer.wait(200); // Wait for write-close, give up after 200msec
4696 }
4697 }
4698 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004699 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004700 } finally {
4701 observer.stopWatching();
4702 }
4703
4704 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004705 }
4706
Dan Egnor42471dd2010-01-07 17:25:22 -08004707 final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
4708 HistoryRecord parent, final String annotation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709 if (app.notResponding || app.crashing) {
4710 return;
4711 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004713 // Log the ANR to the event log.
Dan Egnor2780e732010-01-22 14:47:35 -08004714 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4715 annotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004716
Dan Egnor42471dd2010-01-07 17:25:22 -08004717 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4718 ArrayList<Integer> pids = new ArrayList<Integer>(20);
4719 pids.add(app.pid);
4720
4721 int parentPid = app.pid;
4722 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4723 if (parentPid != app.pid) pids.add(parentPid);
4724
4725 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
4726
4727 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4728 ProcessRecord r = mLruProcesses.get(i);
4729 if (r != null && r.thread != null) {
4730 int pid = r.pid;
4731 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 }
4733 }
4734
Dan Egnor42471dd2010-01-07 17:25:22 -08004735 File tracesFile = dumpStackTraces(pids);
4736
4737 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004738 StringBuilder info = mStringBuilder;
4739 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004740 info.append("ANR in ").append(app.processName);
4741 if (activity != null && activity.shortComponentName != null) {
4742 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004743 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004744 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004746 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004748 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004749 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004751
Dan Egnor42471dd2010-01-07 17:25:22 -08004752 String cpuInfo = null;
4753 if (MONITOR_CPU_USAGE) {
4754 updateCpuStatsNow();
4755 synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
4756 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 }
4758
Joe Onorato8a9b2202010-02-26 18:56:32 -08004759 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004760 if (tracesFile == null) {
4761 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4762 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4763 }
4764
4765 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4766
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004767 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004768 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004769 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4770 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004772 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4773 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004774 }
4775 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004776 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 }
4778 }
4779
Dan Egnor42471dd2010-01-07 17:25:22 -08004780 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4781 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4782 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
4783 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4784 Process.killProcess(app.pid);
4785 return;
4786 }
4787
4788 // Set the app's notResponding state, and look up the errorReportReceiver
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 makeAppNotRespondingLocked(app,
4790 activity != null ? activity.shortComponentName : null,
4791 annotation != null ? "ANR " + annotation : "ANR",
Dan Egnorb7f03672009-12-09 16:22:32 -08004792 info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004793
4794 // Bring up the infamous App Not Responding dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004795 Message msg = Message.obtain();
4796 HashMap map = new HashMap();
4797 msg.what = SHOW_NOT_RESPONDING_MSG;
4798 msg.obj = map;
4799 map.put("app", app);
4800 if (activity != null) {
4801 map.put("activity", activity);
4802 }
4803
4804 mHandler.sendMessage(msg);
4805 return;
4806 }
4807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004808 private final void decPersistentCountLocked(ProcessRecord app)
4809 {
4810 app.persistentActivities--;
4811 if (app.persistentActivities > 0) {
4812 // Still more of 'em...
4813 return;
4814 }
4815 if (app.persistent) {
4816 // Ah, but the application itself is persistent. Whatever!
4817 return;
4818 }
4819
4820 // App is no longer persistent... make sure it and the ones
4821 // following it in the LRU list have the correc oom_adj.
4822 updateOomAdjLocked();
4823 }
4824
4825 public void setPersistent(IBinder token, boolean isPersistent) {
4826 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4827 != PackageManager.PERMISSION_GRANTED) {
4828 String msg = "Permission Denial: setPersistent() from pid="
4829 + Binder.getCallingPid()
4830 + ", uid=" + Binder.getCallingUid()
4831 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004832 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004833 throw new SecurityException(msg);
4834 }
4835
4836 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004837 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 if (index < 0) {
4839 return;
4840 }
4841 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4842 ProcessRecord app = r.app;
4843
Joe Onorato8a9b2202010-02-26 18:56:32 -08004844 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 TAG, "Setting persistence " + isPersistent + ": " + r);
4846
4847 if (isPersistent) {
4848 if (r.persistent) {
4849 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004850 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851 return;
4852 }
4853 r.persistent = true;
4854 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004855 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004856 if (app.persistentActivities > 1) {
4857 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004858 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004859 return;
4860 }
4861 if (app.persistent) {
4862 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004863 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004864 return;
4865 }
4866
4867 // App is now persistent... make sure it and the ones
4868 // following it now have the correct oom_adj.
4869 final long origId = Binder.clearCallingIdentity();
4870 updateOomAdjLocked();
4871 Binder.restoreCallingIdentity(origId);
4872
4873 } else {
4874 if (!r.persistent) {
4875 // Okay okay, I heard you already!
4876 return;
4877 }
4878 r.persistent = false;
4879 final long origId = Binder.clearCallingIdentity();
4880 decPersistentCountLocked(app);
4881 Binder.restoreCallingIdentity(origId);
4882
4883 }
4884 }
4885 }
4886
4887 public boolean clearApplicationUserData(final String packageName,
4888 final IPackageDataObserver observer) {
4889 int uid = Binder.getCallingUid();
4890 int pid = Binder.getCallingPid();
4891 long callingId = Binder.clearCallingIdentity();
4892 try {
4893 IPackageManager pm = ActivityThread.getPackageManager();
4894 int pkgUid = -1;
4895 synchronized(this) {
4896 try {
4897 pkgUid = pm.getPackageUid(packageName);
4898 } catch (RemoteException e) {
4899 }
4900 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004901 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004902 return false;
4903 }
4904 if (uid == pkgUid || checkComponentPermission(
4905 android.Manifest.permission.CLEAR_APP_USER_DATA,
4906 pid, uid, -1)
4907 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08004908 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004909 } else {
4910 throw new SecurityException(pid+" does not have permission:"+
4911 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
4912 "for process:"+packageName);
4913 }
4914 }
4915
4916 try {
4917 //clear application user data
4918 pm.clearApplicationUserData(packageName, observer);
4919 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
4920 Uri.fromParts("package", packageName, null));
4921 intent.putExtra(Intent.EXTRA_UID, pkgUid);
4922 broadcastIntentLocked(null, null, intent,
4923 null, null, 0, null, null, null,
4924 false, false, MY_PID, Process.SYSTEM_UID);
4925 } catch (RemoteException e) {
4926 }
4927 } finally {
4928 Binder.restoreCallingIdentity(callingId);
4929 }
4930 return true;
4931 }
4932
Dianne Hackborn03abb812010-01-04 18:43:19 -08004933 public void killBackgroundProcesses(final String packageName) {
4934 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
4935 != PackageManager.PERMISSION_GRANTED &&
4936 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
4937 != PackageManager.PERMISSION_GRANTED) {
4938 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 + Binder.getCallingPid()
4940 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08004941 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004942 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004943 throw new SecurityException(msg);
4944 }
4945
4946 long callingId = Binder.clearCallingIdentity();
4947 try {
4948 IPackageManager pm = ActivityThread.getPackageManager();
4949 int pkgUid = -1;
4950 synchronized(this) {
4951 try {
4952 pkgUid = pm.getPackageUid(packageName);
4953 } catch (RemoteException e) {
4954 }
4955 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004956 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 return;
4958 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08004959 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004960 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004961 }
4962 } finally {
4963 Binder.restoreCallingIdentity(callingId);
4964 }
4965 }
4966
4967 public void forceStopPackage(final String packageName) {
4968 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4969 != PackageManager.PERMISSION_GRANTED) {
4970 String msg = "Permission Denial: forceStopPackage() from pid="
4971 + Binder.getCallingPid()
4972 + ", uid=" + Binder.getCallingUid()
4973 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004974 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004975 throw new SecurityException(msg);
4976 }
4977
4978 long callingId = Binder.clearCallingIdentity();
4979 try {
4980 IPackageManager pm = ActivityThread.getPackageManager();
4981 int pkgUid = -1;
4982 synchronized(this) {
4983 try {
4984 pkgUid = pm.getPackageUid(packageName);
4985 } catch (RemoteException e) {
4986 }
4987 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004988 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004989 return;
4990 }
4991 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992 }
4993 } finally {
4994 Binder.restoreCallingIdentity(callingId);
4995 }
4996 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004997
4998 /*
4999 * The pkg name and uid have to be specified.
5000 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5001 */
5002 public void killApplicationWithUid(String pkg, int uid) {
5003 if (pkg == null) {
5004 return;
5005 }
5006 // Make sure the uid is valid.
5007 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005008 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005009 return;
5010 }
5011 int callerUid = Binder.getCallingUid();
5012 // Only the system server can kill an application
5013 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005014 // Post an aysnc message to kill the application
5015 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5016 msg.arg1 = uid;
5017 msg.arg2 = 0;
5018 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005019 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005020 } else {
5021 throw new SecurityException(callerUid + " cannot kill pkg: " +
5022 pkg);
5023 }
5024 }
5025
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005026 public void closeSystemDialogs(String reason) {
5027 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5028 if (reason != null) {
5029 intent.putExtra("reason", reason);
5030 }
5031
5032 final int uid = Binder.getCallingUid();
5033 final long origId = Binder.clearCallingIdentity();
5034 synchronized (this) {
5035 int i = mWatchers.beginBroadcast();
5036 while (i > 0) {
5037 i--;
5038 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5039 if (w != null) {
5040 try {
5041 w.closingSystemDialogs(reason);
5042 } catch (RemoteException e) {
5043 }
5044 }
5045 }
5046 mWatchers.finishBroadcast();
5047
Dianne Hackbornffa42482009-09-23 22:20:11 -07005048 mWindowManager.closeSystemDialogs(reason);
5049
5050 for (i=mHistory.size()-1; i>=0; i--) {
5051 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5052 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5053 finishActivityLocked(r, i,
5054 Activity.RESULT_CANCELED, null, "close-sys");
5055 }
5056 }
5057
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005058 broadcastIntentLocked(null, null, intent, null,
5059 null, 0, null, null, null, false, false, -1, uid);
5060 }
5061 Binder.restoreCallingIdentity(origId);
5062 }
5063
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005064 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005065 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005066 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5067 for (int i=pids.length-1; i>=0; i--) {
5068 infos[i] = new Debug.MemoryInfo();
5069 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005070 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005071 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005072 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005073
5074 public void killApplicationProcess(String processName, int uid) {
5075 if (processName == null) {
5076 return;
5077 }
5078
5079 int callerUid = Binder.getCallingUid();
5080 // Only the system server can kill an application
5081 if (callerUid == Process.SYSTEM_UID) {
5082 synchronized (this) {
5083 ProcessRecord app = getProcessRecordLocked(processName, uid);
5084 if (app != null) {
5085 try {
5086 app.thread.scheduleSuicide();
5087 } catch (RemoteException e) {
5088 // If the other end already died, then our work here is done.
5089 }
5090 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005091 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005092 + processName + " / " + uid);
5093 }
5094 }
5095 } else {
5096 throw new SecurityException(callerUid + " cannot kill app process: " +
5097 processName);
5098 }
5099 }
5100
Dianne Hackborn03abb812010-01-04 18:43:19 -08005101 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005102 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5104 Uri.fromParts("package", packageName, null));
5105 intent.putExtra(Intent.EXTRA_UID, uid);
5106 broadcastIntentLocked(null, null, intent,
5107 null, null, 0, null, null, null,
5108 false, false, MY_PID, Process.SYSTEM_UID);
5109 }
5110
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005111 private final boolean killPackageProcessesLocked(String packageName, int uid,
5112 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005113 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114
Dianne Hackborn03abb812010-01-04 18:43:19 -08005115 // Remove all processes this package may have touched: all with the
5116 // same UID (except for the system or root user), and all whose name
5117 // matches the package name.
5118 final String procNamePrefix = packageName + ":";
5119 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5120 final int NA = apps.size();
5121 for (int ia=0; ia<NA; ia++) {
5122 ProcessRecord app = apps.valueAt(ia);
5123 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005124 if (doit) {
5125 procs.add(app);
5126 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005127 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5128 || app.processName.equals(packageName)
5129 || app.processName.startsWith(procNamePrefix)) {
5130 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005131 if (!doit) {
5132 return true;
5133 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005134 app.removed = true;
5135 procs.add(app);
5136 }
5137 }
5138 }
5139 }
5140
5141 int N = procs.size();
5142 for (int i=0; i<N; i++) {
5143 removeProcessLocked(procs.get(i), callerWillRestart);
5144 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005145 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005146 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005147
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005148 private final boolean forceStopPackageLocked(String name, int uid,
5149 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005150 int i, N;
5151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 if (uid < 0) {
5153 try {
5154 uid = ActivityThread.getPackageManager().getPackageUid(name);
5155 } catch (RemoteException e) {
5156 }
5157 }
5158
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005159 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005160 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005161
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005162 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5163 while (badApps.hasNext()) {
5164 SparseArray<Long> ba = badApps.next();
5165 if (ba.get(uid) != null) {
5166 badApps.remove();
5167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 }
5169 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005170
5171 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5172 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005173
5174 for (i=mHistory.size()-1; i>=0; i--) {
5175 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5176 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005177 if (!doit) {
5178 return true;
5179 }
5180 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005181 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005182 if (r.app != null) {
5183 r.app.removed = true;
5184 }
5185 r.app = null;
5186 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5187 }
5188 }
5189
5190 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5191 for (ServiceRecord service : mServices.values()) {
5192 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005193 if (!doit) {
5194 return true;
5195 }
5196 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005197 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005198 if (service.app != null) {
5199 service.app.removed = true;
5200 }
5201 service.app = null;
5202 services.add(service);
5203 }
5204 }
5205
5206 N = services.size();
5207 for (i=0; i<N; i++) {
5208 bringDownServiceLocked(services.get(i), true);
5209 }
5210
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005211 if (doit) {
5212 if (purgeCache) {
5213 AttributeCache ac = AttributeCache.instance();
5214 if (ac != null) {
5215 ac.removePackage(name);
5216 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005217 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005218 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005219 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005220
5221 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005222 }
5223
5224 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5225 final String name = app.processName;
5226 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005227 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 TAG, "Force removing process " + app + " (" + name
5229 + "/" + uid + ")");
5230
5231 mProcessNames.remove(name, uid);
5232 boolean needRestart = false;
5233 if (app.pid > 0 && app.pid != MY_PID) {
5234 int pid = app.pid;
5235 synchronized (mPidsSelfLocked) {
5236 mPidsSelfLocked.remove(pid);
5237 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5238 }
5239 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005240 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005241 Process.killProcess(pid);
5242
5243 if (app.persistent) {
5244 if (!callerWillRestart) {
5245 addAppLocked(app.info);
5246 } else {
5247 needRestart = true;
5248 }
5249 }
5250 } else {
5251 mRemovedProcesses.add(app);
5252 }
5253
5254 return needRestart;
5255 }
5256
5257 private final void processStartTimedOutLocked(ProcessRecord app) {
5258 final int pid = app.pid;
5259 boolean gone = false;
5260 synchronized (mPidsSelfLocked) {
5261 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5262 if (knownApp != null && knownApp.thread == null) {
5263 mPidsSelfLocked.remove(pid);
5264 gone = true;
5265 }
5266 }
5267
5268 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005269 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005270 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005271 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005273 // Take care of any launching providers waiting for this process.
5274 checkAppInLaunchingProvidersLocked(app, true);
5275 // Take care of any services that are waiting for the process.
5276 for (int i=0; i<mPendingServices.size(); i++) {
5277 ServiceRecord sr = mPendingServices.get(i);
5278 if (app.info.uid == sr.appInfo.uid
5279 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005280 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005281 mPendingServices.remove(i);
5282 i--;
5283 bringDownServiceLocked(sr, true);
5284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005285 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005286 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005287 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005288 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005289 try {
5290 IBackupManager bm = IBackupManager.Stub.asInterface(
5291 ServiceManager.getService(Context.BACKUP_SERVICE));
5292 bm.agentDisconnected(app.info.packageName);
5293 } catch (RemoteException e) {
5294 // Can't happen; the backup manager is local
5295 }
5296 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005297 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005298 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005299 mPendingBroadcast = null;
5300 scheduleBroadcastsLocked();
5301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005303 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005304 }
5305 }
5306
5307 private final boolean attachApplicationLocked(IApplicationThread thread,
5308 int pid) {
5309
5310 // Find the application record that is being attached... either via
5311 // the pid if we are running in multiple processes, or just pull the
5312 // next app record if we are emulating process with anonymous threads.
5313 ProcessRecord app;
5314 if (pid != MY_PID && pid >= 0) {
5315 synchronized (mPidsSelfLocked) {
5316 app = mPidsSelfLocked.get(pid);
5317 }
5318 } else if (mStartingProcesses.size() > 0) {
5319 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005320 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 } else {
5322 app = null;
5323 }
5324
5325 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005326 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005327 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005328 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 if (pid > 0 && pid != MY_PID) {
5330 Process.killProcess(pid);
5331 } else {
5332 try {
5333 thread.scheduleExit();
5334 } catch (Exception e) {
5335 // Ignore exceptions.
5336 }
5337 }
5338 return false;
5339 }
5340
5341 // If this application record is still attached to a previous
5342 // process, clean it up now.
5343 if (app.thread != null) {
5344 handleAppDiedLocked(app, true);
5345 }
5346
5347 // Tell the process all about itself.
5348
Joe Onorato8a9b2202010-02-26 18:56:32 -08005349 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005350 TAG, "Binding process pid " + pid + " to record " + app);
5351
5352 String processName = app.processName;
5353 try {
5354 thread.asBinder().linkToDeath(new AppDeathRecipient(
5355 app, pid, thread), 0);
5356 } catch (RemoteException e) {
5357 app.resetPackageList();
5358 startProcessLocked(app, "link fail", processName);
5359 return false;
5360 }
5361
Doug Zongker2bec3d42009-12-04 12:52:44 -08005362 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363
5364 app.thread = thread;
5365 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005366 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5367 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 app.forcingToForeground = null;
5369 app.foregroundServices = false;
5370 app.debugging = false;
5371
5372 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5373
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005374 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5375 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005376
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005377 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005378 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005379 }
5380
Joe Onorato8a9b2202010-02-26 18:56:32 -08005381 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005382 TAG, "New app record " + app
5383 + " thread=" + thread.asBinder() + " pid=" + pid);
5384 try {
5385 int testMode = IApplicationThread.DEBUG_OFF;
5386 if (mDebugApp != null && mDebugApp.equals(processName)) {
5387 testMode = mWaitForDebugger
5388 ? IApplicationThread.DEBUG_WAIT
5389 : IApplicationThread.DEBUG_ON;
5390 app.debugging = true;
5391 if (mDebugTransient) {
5392 mDebugApp = mOrigDebugApp;
5393 mWaitForDebugger = mOrigWaitForDebugger;
5394 }
5395 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005396
Christopher Tate181fafa2009-05-14 11:12:14 -07005397 // If the app is being launched for restore or full backup, set it up specially
5398 boolean isRestrictedBackupMode = false;
5399 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5400 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5401 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5402 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005403
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005404 ensurePackageDexOpt(app.instrumentationInfo != null
5405 ? app.instrumentationInfo.packageName
5406 : app.info.packageName);
5407 if (app.instrumentationClass != null) {
5408 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005409 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005410 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005411 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005412 thread.bindApplication(processName, app.instrumentationInfo != null
5413 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005414 app.instrumentationClass, app.instrumentationProfileFile,
5415 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005416 isRestrictedBackupMode || !normalMode,
5417 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005418 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005419 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 } catch (Exception e) {
5421 // todo: Yikes! What should we do? For now we will try to
5422 // start another process, but that could easily get us in
5423 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005424 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005425
5426 app.resetPackageList();
5427 startProcessLocked(app, "bind fail", processName);
5428 return false;
5429 }
5430
5431 // Remove this record from the list of starting applications.
5432 mPersistentStartingProcesses.remove(app);
5433 mProcessesOnHold.remove(app);
5434
5435 boolean badApp = false;
5436 boolean didSomething = false;
5437
5438 // See if the top visible activity is waiting to run in this process...
5439 HistoryRecord hr = topRunningActivityLocked(null);
5440 if (hr != null) {
5441 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5442 && processName.equals(hr.processName)) {
5443 try {
5444 if (realStartActivityLocked(hr, app, true, true)) {
5445 didSomething = true;
5446 }
5447 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005448 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 + hr.intent.getComponent().flattenToShortString(), e);
5450 badApp = true;
5451 }
5452 } else {
5453 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5454 }
5455 }
5456
5457 // Find any services that should be running in this process...
5458 if (!badApp && mPendingServices.size() > 0) {
5459 ServiceRecord sr = null;
5460 try {
5461 for (int i=0; i<mPendingServices.size(); i++) {
5462 sr = mPendingServices.get(i);
5463 if (app.info.uid != sr.appInfo.uid
5464 || !processName.equals(sr.processName)) {
5465 continue;
5466 }
5467
5468 mPendingServices.remove(i);
5469 i--;
5470 realStartServiceLocked(sr, app);
5471 didSomething = true;
5472 }
5473 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005474 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005475 + sr.shortName, e);
5476 badApp = true;
5477 }
5478 }
5479
5480 // Check if the next broadcast receiver is in this process...
5481 BroadcastRecord br = mPendingBroadcast;
5482 if (!badApp && br != null && br.curApp == app) {
5483 try {
5484 mPendingBroadcast = null;
5485 processCurBroadcastLocked(br, app);
5486 didSomething = true;
5487 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005488 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005489 + br.curComponent.flattenToShortString(), e);
5490 badApp = true;
5491 logBroadcastReceiverDiscard(br);
5492 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5493 br.resultExtras, br.resultAbort, true);
5494 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005495 // We need to reset the state if we fails to start the receiver.
5496 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005497 }
5498 }
5499
Christopher Tate181fafa2009-05-14 11:12:14 -07005500 // Check whether the next backup agent is in this process...
5501 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005502 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005503 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005504 try {
5505 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5506 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005507 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005508 e.printStackTrace();
5509 }
5510 }
5511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005512 if (badApp) {
5513 // todo: Also need to kill application to deal with all
5514 // kinds of exceptions.
5515 handleAppDiedLocked(app, false);
5516 return false;
5517 }
5518
5519 if (!didSomething) {
5520 updateOomAdjLocked();
5521 }
5522
5523 return true;
5524 }
5525
5526 public final void attachApplication(IApplicationThread thread) {
5527 synchronized (this) {
5528 int callingPid = Binder.getCallingPid();
5529 final long origId = Binder.clearCallingIdentity();
5530 attachApplicationLocked(thread, callingPid);
5531 Binder.restoreCallingIdentity(origId);
5532 }
5533 }
5534
Dianne Hackborne88846e2009-09-30 21:34:25 -07005535 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005537 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005538 Binder.restoreCallingIdentity(origId);
5539 }
5540
5541 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5542 boolean remove) {
5543 int N = mStoppingActivities.size();
5544 if (N <= 0) return null;
5545
5546 ArrayList<HistoryRecord> stops = null;
5547
5548 final boolean nowVisible = mResumedActivity != null
5549 && mResumedActivity.nowVisible
5550 && !mResumedActivity.waitingVisible;
5551 for (int i=0; i<N; i++) {
5552 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005553 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005554 + nowVisible + " waitingVisible=" + s.waitingVisible
5555 + " finishing=" + s.finishing);
5556 if (s.waitingVisible && nowVisible) {
5557 mWaitingVisibleActivities.remove(s);
5558 s.waitingVisible = false;
5559 if (s.finishing) {
5560 // If this activity is finishing, it is sitting on top of
5561 // everyone else but we now know it is no longer needed...
5562 // so get rid of it. Otherwise, we need to go through the
5563 // normal flow and hide it once we determine that it is
5564 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005565 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005566 mWindowManager.setAppVisibility(s, false);
5567 }
5568 }
5569 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005570 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005571 if (stops == null) {
5572 stops = new ArrayList<HistoryRecord>();
5573 }
5574 stops.add(s);
5575 mStoppingActivities.remove(i);
5576 N--;
5577 i--;
5578 }
5579 }
5580
5581 return stops;
5582 }
5583
5584 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005585 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005586 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005587 mWindowManager.enableScreenAfterBoot();
5588 }
5589
Dianne Hackborne88846e2009-09-30 21:34:25 -07005590 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5591 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005592 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005593
5594 ArrayList<HistoryRecord> stops = null;
5595 ArrayList<HistoryRecord> finishes = null;
5596 ArrayList<HistoryRecord> thumbnails = null;
5597 int NS = 0;
5598 int NF = 0;
5599 int NT = 0;
5600 IApplicationThread sendThumbnail = null;
5601 boolean booting = false;
5602 boolean enableScreen = false;
5603
5604 synchronized (this) {
5605 if (token != null) {
5606 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5607 }
5608
5609 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005610 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005611 if (index >= 0) {
5612 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5613
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005614 if (fromTimeout) {
5615 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5616 }
5617
Dianne Hackborne88846e2009-09-30 21:34:25 -07005618 // This is a hack to semi-deal with a race condition
5619 // in the client where it can be constructed with a
5620 // newer configuration from when we asked it to launch.
5621 // We'll update with whatever configuration it now says
5622 // it used to launch.
5623 if (config != null) {
5624 r.configuration = config;
5625 }
5626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005627 // No longer need to keep the device awake.
5628 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5629 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5630 mLaunchingActivity.release();
5631 }
5632
5633 // We are now idle. If someone is waiting for a thumbnail from
5634 // us, we can now deliver.
5635 r.idle = true;
5636 scheduleAppGcsLocked();
5637 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5638 sendThumbnail = r.app.thread;
5639 r.thumbnailNeeded = false;
5640 }
5641
5642 // If this activity is fullscreen, set up to hide those under it.
5643
Joe Onorato8a9b2202010-02-26 18:56:32 -08005644 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005645 ensureActivitiesVisibleLocked(null, 0);
5646
Joe Onorato8a9b2202010-02-26 18:56:32 -08005647 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005648 if (!mBooted && !fromTimeout) {
5649 mBooted = true;
5650 enableScreen = true;
5651 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005652
5653 } else if (fromTimeout) {
5654 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 }
5656
5657 // Atomically retrieve all of the other things to do.
5658 stops = processStoppingActivitiesLocked(true);
5659 NS = stops != null ? stops.size() : 0;
5660 if ((NF=mFinishingActivities.size()) > 0) {
5661 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5662 mFinishingActivities.clear();
5663 }
5664 if ((NT=mCancelledThumbnails.size()) > 0) {
5665 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5666 mCancelledThumbnails.clear();
5667 }
5668
5669 booting = mBooting;
5670 mBooting = false;
5671 }
5672
5673 int i;
5674
5675 // Send thumbnail if requested.
5676 if (sendThumbnail != null) {
5677 try {
5678 sendThumbnail.requestThumbnail(token);
5679 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005680 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005681 sendPendingThumbnail(null, token, null, null, true);
5682 }
5683 }
5684
5685 // Stop any activities that are scheduled to do so but have been
5686 // waiting for the next one to start.
5687 for (i=0; i<NS; i++) {
5688 HistoryRecord r = (HistoryRecord)stops.get(i);
5689 synchronized (this) {
5690 if (r.finishing) {
5691 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5692 } else {
5693 stopActivityLocked(r);
5694 }
5695 }
5696 }
5697
5698 // Finish any activities that are scheduled to do so but have been
5699 // waiting for the next one to start.
5700 for (i=0; i<NF; i++) {
5701 HistoryRecord r = (HistoryRecord)finishes.get(i);
5702 synchronized (this) {
5703 destroyActivityLocked(r, true);
5704 }
5705 }
5706
5707 // Report back to any thumbnail receivers.
5708 for (i=0; i<NT; i++) {
5709 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5710 sendPendingThumbnail(r, null, null, null, true);
5711 }
5712
5713 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005714 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005715 }
5716
5717 trimApplications();
5718 //dump();
5719 //mWindowManager.dump();
5720
5721 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005722 enableScreenAfterBoot();
5723 }
5724 }
5725
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005726 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005727 IntentFilter pkgFilter = new IntentFilter();
5728 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5729 pkgFilter.addDataScheme("package");
5730 mContext.registerReceiver(new BroadcastReceiver() {
5731 @Override
5732 public void onReceive(Context context, Intent intent) {
5733 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5734 if (pkgs != null) {
5735 for (String pkg : pkgs) {
5736 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5737 setResultCode(Activity.RESULT_OK);
5738 return;
5739 }
5740 }
5741 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005742 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005743 }, pkgFilter);
5744
5745 synchronized (this) {
5746 // Ensure that any processes we had put on hold are now started
5747 // up.
5748 final int NP = mProcessesOnHold.size();
5749 if (NP > 0) {
5750 ArrayList<ProcessRecord> procs =
5751 new ArrayList<ProcessRecord>(mProcessesOnHold);
5752 for (int ip=0; ip<NP; ip++) {
5753 this.startProcessLocked(procs.get(ip), "on-hold", null);
5754 }
5755 }
5756
5757 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5758 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005759 broadcastIntentLocked(null, null,
5760 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5761 null, null, 0, null, null,
5762 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5763 false, false, MY_PID, Process.SYSTEM_UID);
5764 }
5765 }
5766 }
5767
5768 final void ensureBootCompleted() {
5769 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005770 boolean enableScreen;
5771 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005772 booting = mBooting;
5773 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005774 enableScreen = !mBooted;
5775 mBooted = true;
5776 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005777
5778 if (booting) {
5779 finishBooting();
5780 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005781
5782 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005783 enableScreenAfterBoot();
5784 }
5785 }
5786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005787 public final void activityPaused(IBinder token, Bundle icicle) {
5788 // Refuse possible leaked file descriptors
5789 if (icicle != null && icicle.hasFileDescriptors()) {
5790 throw new IllegalArgumentException("File descriptors passed in Bundle");
5791 }
5792
5793 final long origId = Binder.clearCallingIdentity();
5794 activityPaused(token, icicle, false);
5795 Binder.restoreCallingIdentity(origId);
5796 }
5797
5798 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005799 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005800 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5801 + ", timeout=" + timeout);
5802
5803 HistoryRecord r = null;
5804
5805 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005806 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005807 if (index >= 0) {
5808 r = (HistoryRecord)mHistory.get(index);
5809 if (!timeout) {
5810 r.icicle = icicle;
5811 r.haveState = true;
5812 }
5813 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5814 if (mPausingActivity == r) {
5815 r.state = ActivityState.PAUSED;
5816 completePauseLocked();
5817 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005818 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819 System.identityHashCode(r), r.shortComponentName,
5820 mPausingActivity != null
5821 ? mPausingActivity.shortComponentName : "(none)");
5822 }
5823 }
5824 }
5825 }
5826
5827 public final void activityStopped(IBinder token, Bitmap thumbnail,
5828 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005829 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 TAG, "Activity stopped: token=" + token);
5831
5832 HistoryRecord r = null;
5833
5834 final long origId = Binder.clearCallingIdentity();
5835
5836 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005837 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005838 if (index >= 0) {
5839 r = (HistoryRecord)mHistory.get(index);
5840 r.thumbnail = thumbnail;
5841 r.description = description;
5842 r.stopped = true;
5843 r.state = ActivityState.STOPPED;
5844 if (!r.finishing) {
5845 if (r.configDestroy) {
5846 destroyActivityLocked(r, true);
5847 resumeTopActivityLocked(null);
5848 }
5849 }
5850 }
5851 }
5852
5853 if (r != null) {
5854 sendPendingThumbnail(r, null, null, null, false);
5855 }
5856
5857 trimApplications();
5858
5859 Binder.restoreCallingIdentity(origId);
5860 }
5861
5862 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005863 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005864 synchronized (this) {
5865 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
5866
Dianne Hackborn75b03852009-06-12 15:43:26 -07005867 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 if (index >= 0) {
5869 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5870 if (r.state == ActivityState.DESTROYING) {
5871 final long origId = Binder.clearCallingIdentity();
5872 removeActivityFromHistoryLocked(r);
5873 Binder.restoreCallingIdentity(origId);
5874 }
5875 }
5876 }
5877 }
5878
5879 public String getCallingPackage(IBinder token) {
5880 synchronized (this) {
5881 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07005882 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005883 }
5884 }
5885
5886 public ComponentName getCallingActivity(IBinder token) {
5887 synchronized (this) {
5888 HistoryRecord r = getCallingRecordLocked(token);
5889 return r != null ? r.intent.getComponent() : null;
5890 }
5891 }
5892
5893 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005894 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005895 if (index >= 0) {
5896 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5897 if (r != null) {
5898 return r.resultTo;
5899 }
5900 }
5901 return null;
5902 }
5903
5904 public ComponentName getActivityClassForToken(IBinder token) {
5905 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005906 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 if (index >= 0) {
5908 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5909 return r.intent.getComponent();
5910 }
5911 return null;
5912 }
5913 }
5914
5915 public String getPackageForToken(IBinder token) {
5916 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005917 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005918 if (index >= 0) {
5919 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5920 return r.packageName;
5921 }
5922 return null;
5923 }
5924 }
5925
5926 public IIntentSender getIntentSender(int type,
5927 String packageName, IBinder token, String resultWho,
5928 int requestCode, Intent intent, String resolvedType, int flags) {
5929 // Refuse possible leaked file descriptors
5930 if (intent != null && intent.hasFileDescriptors() == true) {
5931 throw new IllegalArgumentException("File descriptors passed in Intent");
5932 }
5933
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005934 if (type == INTENT_SENDER_BROADCAST) {
5935 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
5936 throw new IllegalArgumentException(
5937 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
5938 }
5939 }
5940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 synchronized(this) {
5942 int callingUid = Binder.getCallingUid();
5943 try {
5944 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
5945 Process.supportsProcesses()) {
5946 int uid = ActivityThread.getPackageManager()
5947 .getPackageUid(packageName);
5948 if (uid != Binder.getCallingUid()) {
5949 String msg = "Permission Denial: getIntentSender() from pid="
5950 + Binder.getCallingPid()
5951 + ", uid=" + Binder.getCallingUid()
5952 + ", (need uid=" + uid + ")"
5953 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005954 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 throw new SecurityException(msg);
5956 }
5957 }
5958 } catch (RemoteException e) {
5959 throw new SecurityException(e);
5960 }
5961 HistoryRecord activity = null;
5962 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005963 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 if (index < 0) {
5965 return null;
5966 }
5967 activity = (HistoryRecord)mHistory.get(index);
5968 if (activity.finishing) {
5969 return null;
5970 }
5971 }
5972
5973 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
5974 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
5975 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
5976 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
5977 |PendingIntent.FLAG_UPDATE_CURRENT);
5978
5979 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
5980 type, packageName, activity, resultWho,
5981 requestCode, intent, resolvedType, flags);
5982 WeakReference<PendingIntentRecord> ref;
5983 ref = mIntentSenderRecords.get(key);
5984 PendingIntentRecord rec = ref != null ? ref.get() : null;
5985 if (rec != null) {
5986 if (!cancelCurrent) {
5987 if (updateCurrent) {
5988 rec.key.requestIntent.replaceExtras(intent);
5989 }
5990 return rec;
5991 }
5992 rec.canceled = true;
5993 mIntentSenderRecords.remove(key);
5994 }
5995 if (noCreate) {
5996 return rec;
5997 }
5998 rec = new PendingIntentRecord(this, key, callingUid);
5999 mIntentSenderRecords.put(key, rec.ref);
6000 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6001 if (activity.pendingResults == null) {
6002 activity.pendingResults
6003 = new HashSet<WeakReference<PendingIntentRecord>>();
6004 }
6005 activity.pendingResults.add(rec.ref);
6006 }
6007 return rec;
6008 }
6009 }
6010
6011 public void cancelIntentSender(IIntentSender sender) {
6012 if (!(sender instanceof PendingIntentRecord)) {
6013 return;
6014 }
6015 synchronized(this) {
6016 PendingIntentRecord rec = (PendingIntentRecord)sender;
6017 try {
6018 int uid = ActivityThread.getPackageManager()
6019 .getPackageUid(rec.key.packageName);
6020 if (uid != Binder.getCallingUid()) {
6021 String msg = "Permission Denial: cancelIntentSender() from pid="
6022 + Binder.getCallingPid()
6023 + ", uid=" + Binder.getCallingUid()
6024 + " is not allowed to cancel packges "
6025 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006026 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006027 throw new SecurityException(msg);
6028 }
6029 } catch (RemoteException e) {
6030 throw new SecurityException(e);
6031 }
6032 cancelIntentSenderLocked(rec, true);
6033 }
6034 }
6035
6036 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6037 rec.canceled = true;
6038 mIntentSenderRecords.remove(rec.key);
6039 if (cleanActivity && rec.key.activity != null) {
6040 rec.key.activity.pendingResults.remove(rec.ref);
6041 }
6042 }
6043
6044 public String getPackageForIntentSender(IIntentSender pendingResult) {
6045 if (!(pendingResult instanceof PendingIntentRecord)) {
6046 return null;
6047 }
6048 synchronized(this) {
6049 try {
6050 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6051 return res.key.packageName;
6052 } catch (ClassCastException e) {
6053 }
6054 }
6055 return null;
6056 }
6057
6058 public void setProcessLimit(int max) {
6059 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6060 "setProcessLimit()");
6061 mProcessLimit = max;
6062 }
6063
6064 public int getProcessLimit() {
6065 return mProcessLimit;
6066 }
6067
6068 void foregroundTokenDied(ForegroundToken token) {
6069 synchronized (ActivityManagerService.this) {
6070 synchronized (mPidsSelfLocked) {
6071 ForegroundToken cur
6072 = mForegroundProcesses.get(token.pid);
6073 if (cur != token) {
6074 return;
6075 }
6076 mForegroundProcesses.remove(token.pid);
6077 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6078 if (pr == null) {
6079 return;
6080 }
6081 pr.forcingToForeground = null;
6082 pr.foregroundServices = false;
6083 }
6084 updateOomAdjLocked();
6085 }
6086 }
6087
6088 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6089 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6090 "setProcessForeground()");
6091 synchronized(this) {
6092 boolean changed = false;
6093
6094 synchronized (mPidsSelfLocked) {
6095 ProcessRecord pr = mPidsSelfLocked.get(pid);
6096 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006097 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006098 return;
6099 }
6100 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6101 if (oldToken != null) {
6102 oldToken.token.unlinkToDeath(oldToken, 0);
6103 mForegroundProcesses.remove(pid);
6104 pr.forcingToForeground = null;
6105 changed = true;
6106 }
6107 if (isForeground && token != null) {
6108 ForegroundToken newToken = new ForegroundToken() {
6109 public void binderDied() {
6110 foregroundTokenDied(this);
6111 }
6112 };
6113 newToken.pid = pid;
6114 newToken.token = token;
6115 try {
6116 token.linkToDeath(newToken, 0);
6117 mForegroundProcesses.put(pid, newToken);
6118 pr.forcingToForeground = token;
6119 changed = true;
6120 } catch (RemoteException e) {
6121 // If the process died while doing this, we will later
6122 // do the cleanup with the process death link.
6123 }
6124 }
6125 }
6126
6127 if (changed) {
6128 updateOomAdjLocked();
6129 }
6130 }
6131 }
6132
6133 // =========================================================
6134 // PERMISSIONS
6135 // =========================================================
6136
6137 static class PermissionController extends IPermissionController.Stub {
6138 ActivityManagerService mActivityManagerService;
6139 PermissionController(ActivityManagerService activityManagerService) {
6140 mActivityManagerService = activityManagerService;
6141 }
6142
6143 public boolean checkPermission(String permission, int pid, int uid) {
6144 return mActivityManagerService.checkPermission(permission, pid,
6145 uid) == PackageManager.PERMISSION_GRANTED;
6146 }
6147 }
6148
6149 /**
6150 * This can be called with or without the global lock held.
6151 */
6152 int checkComponentPermission(String permission, int pid, int uid,
6153 int reqUid) {
6154 // We might be performing an operation on behalf of an indirect binder
6155 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6156 // client identity accordingly before proceeding.
6157 Identity tlsIdentity = sCallerIdentity.get();
6158 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006159 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006160 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6161 uid = tlsIdentity.uid;
6162 pid = tlsIdentity.pid;
6163 }
6164
6165 // Root, system server and our own process get to do everything.
6166 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6167 !Process.supportsProcesses()) {
6168 return PackageManager.PERMISSION_GRANTED;
6169 }
6170 // If the target requires a specific UID, always fail for others.
6171 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006172 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006173 return PackageManager.PERMISSION_DENIED;
6174 }
6175 if (permission == null) {
6176 return PackageManager.PERMISSION_GRANTED;
6177 }
6178 try {
6179 return ActivityThread.getPackageManager()
6180 .checkUidPermission(permission, uid);
6181 } catch (RemoteException e) {
6182 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006183 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006184 }
6185 return PackageManager.PERMISSION_DENIED;
6186 }
6187
6188 /**
6189 * As the only public entry point for permissions checking, this method
6190 * can enforce the semantic that requesting a check on a null global
6191 * permission is automatically denied. (Internally a null permission
6192 * string is used when calling {@link #checkComponentPermission} in cases
6193 * when only uid-based security is needed.)
6194 *
6195 * This can be called with or without the global lock held.
6196 */
6197 public int checkPermission(String permission, int pid, int uid) {
6198 if (permission == null) {
6199 return PackageManager.PERMISSION_DENIED;
6200 }
6201 return checkComponentPermission(permission, pid, uid, -1);
6202 }
6203
6204 /**
6205 * Binder IPC calls go through the public entry point.
6206 * This can be called with or without the global lock held.
6207 */
6208 int checkCallingPermission(String permission) {
6209 return checkPermission(permission,
6210 Binder.getCallingPid(),
6211 Binder.getCallingUid());
6212 }
6213
6214 /**
6215 * This can be called with or without the global lock held.
6216 */
6217 void enforceCallingPermission(String permission, String func) {
6218 if (checkCallingPermission(permission)
6219 == PackageManager.PERMISSION_GRANTED) {
6220 return;
6221 }
6222
6223 String msg = "Permission Denial: " + func + " from pid="
6224 + Binder.getCallingPid()
6225 + ", uid=" + Binder.getCallingUid()
6226 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006227 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006228 throw new SecurityException(msg);
6229 }
6230
6231 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6232 ProviderInfo pi, int uid, int modeFlags) {
6233 try {
6234 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6235 if ((pi.readPermission != null) &&
6236 (pm.checkUidPermission(pi.readPermission, uid)
6237 != PackageManager.PERMISSION_GRANTED)) {
6238 return false;
6239 }
6240 }
6241 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6242 if ((pi.writePermission != null) &&
6243 (pm.checkUidPermission(pi.writePermission, uid)
6244 != PackageManager.PERMISSION_GRANTED)) {
6245 return false;
6246 }
6247 }
6248 return true;
6249 } catch (RemoteException e) {
6250 return false;
6251 }
6252 }
6253
6254 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6255 int modeFlags) {
6256 // Root gets to do everything.
6257 if (uid == 0 || !Process.supportsProcesses()) {
6258 return true;
6259 }
6260 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6261 if (perms == null) return false;
6262 UriPermission perm = perms.get(uri);
6263 if (perm == null) return false;
6264 return (modeFlags&perm.modeFlags) == modeFlags;
6265 }
6266
6267 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6268 // Another redirected-binder-call permissions check as in
6269 // {@link checkComponentPermission}.
6270 Identity tlsIdentity = sCallerIdentity.get();
6271 if (tlsIdentity != null) {
6272 uid = tlsIdentity.uid;
6273 pid = tlsIdentity.pid;
6274 }
6275
6276 // Our own process gets to do everything.
6277 if (pid == MY_PID) {
6278 return PackageManager.PERMISSION_GRANTED;
6279 }
6280 synchronized(this) {
6281 return checkUriPermissionLocked(uri, uid, modeFlags)
6282 ? PackageManager.PERMISSION_GRANTED
6283 : PackageManager.PERMISSION_DENIED;
6284 }
6285 }
6286
6287 private void grantUriPermissionLocked(int callingUid,
6288 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6289 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6290 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6291 if (modeFlags == 0) {
6292 return;
6293 }
6294
Joe Onorato8a9b2202010-02-26 18:56:32 -08006295 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006296 "Requested grant " + targetPkg + " permission to " + uri);
6297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 final IPackageManager pm = ActivityThread.getPackageManager();
6299
6300 // If this is not a content: uri, we can't do anything with it.
6301 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006302 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006303 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 return;
6305 }
6306
6307 String name = uri.getAuthority();
6308 ProviderInfo pi = null;
6309 ContentProviderRecord cpr
6310 = (ContentProviderRecord)mProvidersByName.get(name);
6311 if (cpr != null) {
6312 pi = cpr.info;
6313 } else {
6314 try {
6315 pi = pm.resolveContentProvider(name,
6316 PackageManager.GET_URI_PERMISSION_PATTERNS);
6317 } catch (RemoteException ex) {
6318 }
6319 }
6320 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006321 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 return;
6323 }
6324
6325 int targetUid;
6326 try {
6327 targetUid = pm.getPackageUid(targetPkg);
6328 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006329 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006330 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 return;
6332 }
6333 } catch (RemoteException ex) {
6334 return;
6335 }
6336
6337 // First... does the target actually need this permission?
6338 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6339 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006340 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006341 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 return;
6343 }
6344
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006345 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 if (!pi.grantUriPermissions) {
6347 throw new SecurityException("Provider " + pi.packageName
6348 + "/" + pi.name
6349 + " does not allow granting of Uri permissions (uri "
6350 + uri + ")");
6351 }
6352 if (pi.uriPermissionPatterns != null) {
6353 final int N = pi.uriPermissionPatterns.length;
6354 boolean allowed = false;
6355 for (int i=0; i<N; i++) {
6356 if (pi.uriPermissionPatterns[i] != null
6357 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6358 allowed = true;
6359 break;
6360 }
6361 }
6362 if (!allowed) {
6363 throw new SecurityException("Provider " + pi.packageName
6364 + "/" + pi.name
6365 + " does not allow granting of permission to path of Uri "
6366 + uri);
6367 }
6368 }
6369
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006370 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 // this uri?
6372 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6373 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6374 throw new SecurityException("Uid " + callingUid
6375 + " does not have permission to uri " + uri);
6376 }
6377 }
6378
6379 // Okay! So here we are: the caller has the assumed permission
6380 // to the uri, and the target doesn't. Let's now give this to
6381 // the target.
6382
Joe Onorato8a9b2202010-02-26 18:56:32 -08006383 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006384 "Granting " + targetPkg + " permission to " + uri);
6385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006386 HashMap<Uri, UriPermission> targetUris
6387 = mGrantedUriPermissions.get(targetUid);
6388 if (targetUris == null) {
6389 targetUris = new HashMap<Uri, UriPermission>();
6390 mGrantedUriPermissions.put(targetUid, targetUris);
6391 }
6392
6393 UriPermission perm = targetUris.get(uri);
6394 if (perm == null) {
6395 perm = new UriPermission(targetUid, uri);
6396 targetUris.put(uri, perm);
6397
6398 }
6399 perm.modeFlags |= modeFlags;
6400 if (activity == null) {
6401 perm.globalModeFlags |= modeFlags;
6402 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6403 perm.readActivities.add(activity);
6404 if (activity.readUriPermissions == null) {
6405 activity.readUriPermissions = new HashSet<UriPermission>();
6406 }
6407 activity.readUriPermissions.add(perm);
6408 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6409 perm.writeActivities.add(activity);
6410 if (activity.writeUriPermissions == null) {
6411 activity.writeUriPermissions = new HashSet<UriPermission>();
6412 }
6413 activity.writeUriPermissions.add(perm);
6414 }
6415 }
6416
6417 private void grantUriPermissionFromIntentLocked(int callingUid,
6418 String targetPkg, Intent intent, HistoryRecord activity) {
6419 if (intent == null) {
6420 return;
6421 }
6422 Uri data = intent.getData();
6423 if (data == null) {
6424 return;
6425 }
6426 grantUriPermissionLocked(callingUid, targetPkg, data,
6427 intent.getFlags(), activity);
6428 }
6429
6430 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6431 Uri uri, int modeFlags) {
6432 synchronized(this) {
6433 final ProcessRecord r = getRecordForAppLocked(caller);
6434 if (r == null) {
6435 throw new SecurityException("Unable to find app for caller "
6436 + caller
6437 + " when granting permission to uri " + uri);
6438 }
6439 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006440 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006441 return;
6442 }
6443 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006444 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 return;
6446 }
6447
6448 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6449 null);
6450 }
6451 }
6452
6453 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6454 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6455 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6456 HashMap<Uri, UriPermission> perms
6457 = mGrantedUriPermissions.get(perm.uid);
6458 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006459 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006460 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006461 perms.remove(perm.uri);
6462 if (perms.size() == 0) {
6463 mGrantedUriPermissions.remove(perm.uid);
6464 }
6465 }
6466 }
6467 }
6468
6469 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6470 if (activity.readUriPermissions != null) {
6471 for (UriPermission perm : activity.readUriPermissions) {
6472 perm.readActivities.remove(activity);
6473 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6474 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6475 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6476 removeUriPermissionIfNeededLocked(perm);
6477 }
6478 }
6479 }
6480 if (activity.writeUriPermissions != null) {
6481 for (UriPermission perm : activity.writeUriPermissions) {
6482 perm.writeActivities.remove(activity);
6483 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6484 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6485 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6486 removeUriPermissionIfNeededLocked(perm);
6487 }
6488 }
6489 }
6490 }
6491
6492 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6493 int modeFlags) {
6494 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6495 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6496 if (modeFlags == 0) {
6497 return;
6498 }
6499
Joe Onorato8a9b2202010-02-26 18:56:32 -08006500 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006501 "Revoking all granted permissions to " + uri);
6502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 final IPackageManager pm = ActivityThread.getPackageManager();
6504
6505 final String authority = uri.getAuthority();
6506 ProviderInfo pi = null;
6507 ContentProviderRecord cpr
6508 = (ContentProviderRecord)mProvidersByName.get(authority);
6509 if (cpr != null) {
6510 pi = cpr.info;
6511 } else {
6512 try {
6513 pi = pm.resolveContentProvider(authority,
6514 PackageManager.GET_URI_PERMISSION_PATTERNS);
6515 } catch (RemoteException ex) {
6516 }
6517 }
6518 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006519 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006520 return;
6521 }
6522
6523 // Does the caller have this permission on the URI?
6524 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6525 // Right now, if you are not the original owner of the permission,
6526 // you are not allowed to revoke it.
6527 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6528 throw new SecurityException("Uid " + callingUid
6529 + " does not have permission to uri " + uri);
6530 //}
6531 }
6532
6533 // Go through all of the permissions and remove any that match.
6534 final List<String> SEGMENTS = uri.getPathSegments();
6535 if (SEGMENTS != null) {
6536 final int NS = SEGMENTS.size();
6537 int N = mGrantedUriPermissions.size();
6538 for (int i=0; i<N; i++) {
6539 HashMap<Uri, UriPermission> perms
6540 = mGrantedUriPermissions.valueAt(i);
6541 Iterator<UriPermission> it = perms.values().iterator();
6542 toploop:
6543 while (it.hasNext()) {
6544 UriPermission perm = it.next();
6545 Uri targetUri = perm.uri;
6546 if (!authority.equals(targetUri.getAuthority())) {
6547 continue;
6548 }
6549 List<String> targetSegments = targetUri.getPathSegments();
6550 if (targetSegments == null) {
6551 continue;
6552 }
6553 if (targetSegments.size() < NS) {
6554 continue;
6555 }
6556 for (int j=0; j<NS; j++) {
6557 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6558 continue toploop;
6559 }
6560 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006561 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006562 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006563 perm.clearModes(modeFlags);
6564 if (perm.modeFlags == 0) {
6565 it.remove();
6566 }
6567 }
6568 if (perms.size() == 0) {
6569 mGrantedUriPermissions.remove(
6570 mGrantedUriPermissions.keyAt(i));
6571 N--;
6572 i--;
6573 }
6574 }
6575 }
6576 }
6577
6578 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6579 int modeFlags) {
6580 synchronized(this) {
6581 final ProcessRecord r = getRecordForAppLocked(caller);
6582 if (r == null) {
6583 throw new SecurityException("Unable to find app for caller "
6584 + caller
6585 + " when revoking permission to uri " + uri);
6586 }
6587 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006588 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006589 return;
6590 }
6591
6592 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6593 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6594 if (modeFlags == 0) {
6595 return;
6596 }
6597
6598 final IPackageManager pm = ActivityThread.getPackageManager();
6599
6600 final String authority = uri.getAuthority();
6601 ProviderInfo pi = null;
6602 ContentProviderRecord cpr
6603 = (ContentProviderRecord)mProvidersByName.get(authority);
6604 if (cpr != null) {
6605 pi = cpr.info;
6606 } else {
6607 try {
6608 pi = pm.resolveContentProvider(authority,
6609 PackageManager.GET_URI_PERMISSION_PATTERNS);
6610 } catch (RemoteException ex) {
6611 }
6612 }
6613 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006614 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006615 return;
6616 }
6617
6618 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6619 }
6620 }
6621
6622 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6623 synchronized (this) {
6624 ProcessRecord app =
6625 who != null ? getRecordForAppLocked(who) : null;
6626 if (app == null) return;
6627
6628 Message msg = Message.obtain();
6629 msg.what = WAIT_FOR_DEBUGGER_MSG;
6630 msg.obj = app;
6631 msg.arg1 = waiting ? 1 : 0;
6632 mHandler.sendMessage(msg);
6633 }
6634 }
6635
6636 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6637 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006638 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006639 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006640 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006641 }
6642
6643 // =========================================================
6644 // TASK MANAGEMENT
6645 // =========================================================
6646
6647 public List getTasks(int maxNum, int flags,
6648 IThumbnailReceiver receiver) {
6649 ArrayList list = new ArrayList();
6650
6651 PendingThumbnailsRecord pending = null;
6652 IApplicationThread topThumbnail = null;
6653 HistoryRecord topRecord = null;
6654
6655 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006656 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006657 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6658 + ", receiver=" + receiver);
6659
6660 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6661 != PackageManager.PERMISSION_GRANTED) {
6662 if (receiver != null) {
6663 // If the caller wants to wait for pending thumbnails,
6664 // it ain't gonna get them.
6665 try {
6666 receiver.finished();
6667 } catch (RemoteException ex) {
6668 }
6669 }
6670 String msg = "Permission Denial: getTasks() from pid="
6671 + Binder.getCallingPid()
6672 + ", uid=" + Binder.getCallingUid()
6673 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006674 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006675 throw new SecurityException(msg);
6676 }
6677
6678 int pos = mHistory.size()-1;
6679 HistoryRecord next =
6680 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6681 HistoryRecord top = null;
6682 CharSequence topDescription = null;
6683 TaskRecord curTask = null;
6684 int numActivities = 0;
6685 int numRunning = 0;
6686 while (pos >= 0 && maxNum > 0) {
6687 final HistoryRecord r = next;
6688 pos--;
6689 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6690
6691 // Initialize state for next task if needed.
6692 if (top == null ||
6693 (top.state == ActivityState.INITIALIZING
6694 && top.task == r.task)) {
6695 top = r;
6696 topDescription = r.description;
6697 curTask = r.task;
6698 numActivities = numRunning = 0;
6699 }
6700
6701 // Add 'r' into the current task.
6702 numActivities++;
6703 if (r.app != null && r.app.thread != null) {
6704 numRunning++;
6705 }
6706 if (topDescription == null) {
6707 topDescription = r.description;
6708 }
6709
Joe Onorato8a9b2202010-02-26 18:56:32 -08006710 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006711 TAG, r.intent.getComponent().flattenToShortString()
6712 + ": task=" + r.task);
6713
6714 // If the next one is a different task, generate a new
6715 // TaskInfo entry for what we have.
6716 if (next == null || next.task != curTask) {
6717 ActivityManager.RunningTaskInfo ci
6718 = new ActivityManager.RunningTaskInfo();
6719 ci.id = curTask.taskId;
6720 ci.baseActivity = r.intent.getComponent();
6721 ci.topActivity = top.intent.getComponent();
6722 ci.thumbnail = top.thumbnail;
6723 ci.description = topDescription;
6724 ci.numActivities = numActivities;
6725 ci.numRunning = numRunning;
6726 //System.out.println(
6727 // "#" + maxNum + ": " + " descr=" + ci.description);
6728 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006729 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006730 TAG, "State=" + top.state + "Idle=" + top.idle
6731 + " app=" + top.app
6732 + " thr=" + (top.app != null ? top.app.thread : null));
6733 if (top.state == ActivityState.RESUMED
6734 || top.state == ActivityState.PAUSING) {
6735 if (top.idle && top.app != null
6736 && top.app.thread != null) {
6737 topRecord = top;
6738 topThumbnail = top.app.thread;
6739 } else {
6740 top.thumbnailNeeded = true;
6741 }
6742 }
6743 if (pending == null) {
6744 pending = new PendingThumbnailsRecord(receiver);
6745 }
6746 pending.pendingRecords.add(top);
6747 }
6748 list.add(ci);
6749 maxNum--;
6750 top = null;
6751 }
6752 }
6753
6754 if (pending != null) {
6755 mPendingThumbnails.add(pending);
6756 }
6757 }
6758
Joe Onorato8a9b2202010-02-26 18:56:32 -08006759 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006760
6761 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006762 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006763 try {
6764 topThumbnail.requestThumbnail(topRecord);
6765 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006766 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006767 sendPendingThumbnail(null, topRecord, null, null, true);
6768 }
6769 }
6770
6771 if (pending == null && receiver != null) {
6772 // In this case all thumbnails were available and the client
6773 // is being asked to be told when the remaining ones come in...
6774 // which is unusually, since the top-most currently running
6775 // activity should never have a canned thumbnail! Oh well.
6776 try {
6777 receiver.finished();
6778 } catch (RemoteException ex) {
6779 }
6780 }
6781
6782 return list;
6783 }
6784
6785 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6786 int flags) {
6787 synchronized (this) {
6788 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6789 "getRecentTasks()");
6790
6791 final int N = mRecentTasks.size();
6792 ArrayList<ActivityManager.RecentTaskInfo> res
6793 = new ArrayList<ActivityManager.RecentTaskInfo>(
6794 maxNum < N ? maxNum : N);
6795 for (int i=0; i<N && maxNum > 0; i++) {
6796 TaskRecord tr = mRecentTasks.get(i);
6797 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6798 || (tr.intent == null)
6799 || ((tr.intent.getFlags()
6800 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6801 ActivityManager.RecentTaskInfo rti
6802 = new ActivityManager.RecentTaskInfo();
6803 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6804 rti.baseIntent = new Intent(
6805 tr.intent != null ? tr.intent : tr.affinityIntent);
6806 rti.origActivity = tr.origActivity;
6807 res.add(rti);
6808 maxNum--;
6809 }
6810 }
6811 return res;
6812 }
6813 }
6814
6815 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6816 int j;
6817 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6818 TaskRecord jt = startTask;
6819
6820 // First look backwards
6821 for (j=startIndex-1; j>=0; j--) {
6822 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6823 if (r.task != jt) {
6824 jt = r.task;
6825 if (affinity.equals(jt.affinity)) {
6826 return j;
6827 }
6828 }
6829 }
6830
6831 // Now look forwards
6832 final int N = mHistory.size();
6833 jt = startTask;
6834 for (j=startIndex+1; j<N; j++) {
6835 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6836 if (r.task != jt) {
6837 if (affinity.equals(jt.affinity)) {
6838 return j;
6839 }
6840 jt = r.task;
6841 }
6842 }
6843
6844 // Might it be at the top?
6845 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
6846 return N-1;
6847 }
6848
6849 return -1;
6850 }
6851
6852 /**
6853 * Perform a reset of the given task, if needed as part of launching it.
6854 * Returns the new HistoryRecord at the top of the task.
6855 */
6856 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
6857 HistoryRecord newActivity) {
6858 boolean forceReset = (newActivity.info.flags
6859 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
6860 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
6861 if ((newActivity.info.flags
6862 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
6863 forceReset = true;
6864 }
6865 }
6866
6867 final TaskRecord task = taskTop.task;
6868
6869 // We are going to move through the history list so that we can look
6870 // at each activity 'target' with 'below' either the interesting
6871 // activity immediately below it in the stack or null.
6872 HistoryRecord target = null;
6873 int targetI = 0;
6874 int taskTopI = -1;
6875 int replyChainEnd = -1;
6876 int lastReparentPos = -1;
6877 for (int i=mHistory.size()-1; i>=-1; i--) {
6878 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
6879
6880 if (below != null && below.finishing) {
6881 continue;
6882 }
6883 if (target == null) {
6884 target = below;
6885 targetI = i;
6886 // If we were in the middle of a reply chain before this
6887 // task, it doesn't appear like the root of the chain wants
6888 // anything interesting, so drop it.
6889 replyChainEnd = -1;
6890 continue;
6891 }
6892
6893 final int flags = target.info.flags;
6894
6895 final boolean finishOnTaskLaunch =
6896 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
6897 final boolean allowTaskReparenting =
6898 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
6899
6900 if (target.task == task) {
6901 // We are inside of the task being reset... we'll either
6902 // finish this activity, push it out for another task,
6903 // or leave it as-is. We only do this
6904 // for activities that are not the root of the task (since
6905 // if we finish the root, we may no longer have the task!).
6906 if (taskTopI < 0) {
6907 taskTopI = targetI;
6908 }
6909 if (below != null && below.task == task) {
6910 final boolean clearWhenTaskReset =
6911 (target.intent.getFlags()
6912 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07006913 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006914 // If this activity is sending a reply to a previous
6915 // activity, we can't do anything with it now until
6916 // we reach the start of the reply chain.
6917 // XXX note that we are assuming the result is always
6918 // to the previous activity, which is almost always
6919 // the case but we really shouldn't count on.
6920 if (replyChainEnd < 0) {
6921 replyChainEnd = targetI;
6922 }
Ed Heyl73798232009-03-24 21:32:21 -07006923 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006924 && target.taskAffinity != null
6925 && !target.taskAffinity.equals(task.affinity)) {
6926 // If this activity has an affinity for another
6927 // task, then we need to move it out of here. We will
6928 // move it as far out of the way as possible, to the
6929 // bottom of the activity stack. This also keeps it
6930 // correctly ordered with any activities we previously
6931 // moved.
6932 HistoryRecord p = (HistoryRecord)mHistory.get(0);
6933 if (target.taskAffinity != null
6934 && target.taskAffinity.equals(p.task.affinity)) {
6935 // If the activity currently at the bottom has the
6936 // same task affinity as the one we are moving,
6937 // then merge it into the same task.
6938 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006939 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006940 + " out to bottom task " + p.task);
6941 } else {
6942 mCurTask++;
6943 if (mCurTask <= 0) {
6944 mCurTask = 1;
6945 }
6946 target.task = new TaskRecord(mCurTask, target.info, null,
6947 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
6948 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006949 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006950 + " out to new task " + target.task);
6951 }
6952 mWindowManager.setAppGroupId(target, task.taskId);
6953 if (replyChainEnd < 0) {
6954 replyChainEnd = targetI;
6955 }
6956 int dstPos = 0;
6957 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
6958 p = (HistoryRecord)mHistory.get(srcPos);
6959 if (p.finishing) {
6960 continue;
6961 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006962 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006963 + " out to target's task " + target.task);
6964 task.numActivities--;
6965 p.task = target.task;
6966 target.task.numActivities++;
6967 mHistory.remove(srcPos);
6968 mHistory.add(dstPos, p);
6969 mWindowManager.moveAppToken(dstPos, p);
6970 mWindowManager.setAppGroupId(p, p.task.taskId);
6971 dstPos++;
6972 if (VALIDATE_TOKENS) {
6973 mWindowManager.validateAppTokens(mHistory);
6974 }
6975 i++;
6976 }
6977 if (taskTop == p) {
6978 taskTop = below;
6979 }
6980 if (taskTopI == replyChainEnd) {
6981 taskTopI = -1;
6982 }
6983 replyChainEnd = -1;
6984 addRecentTask(target.task);
6985 } else if (forceReset || finishOnTaskLaunch
6986 || clearWhenTaskReset) {
6987 // If the activity should just be removed -- either
6988 // because it asks for it, or the task should be
6989 // cleared -- then finish it and anything that is
6990 // part of its reply chain.
6991 if (clearWhenTaskReset) {
6992 // In this case, we want to finish this activity
6993 // and everything above it, so be sneaky and pretend
6994 // like these are all in the reply chain.
6995 replyChainEnd = targetI+1;
6996 while (replyChainEnd < mHistory.size() &&
6997 ((HistoryRecord)mHistory.get(
6998 replyChainEnd)).task == task) {
6999 replyChainEnd++;
7000 }
7001 replyChainEnd--;
7002 } else if (replyChainEnd < 0) {
7003 replyChainEnd = targetI;
7004 }
7005 HistoryRecord p = null;
7006 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7007 p = (HistoryRecord)mHistory.get(srcPos);
7008 if (p.finishing) {
7009 continue;
7010 }
7011 if (finishActivityLocked(p, srcPos,
7012 Activity.RESULT_CANCELED, null, "reset")) {
7013 replyChainEnd--;
7014 srcPos--;
7015 }
7016 }
7017 if (taskTop == p) {
7018 taskTop = below;
7019 }
7020 if (taskTopI == replyChainEnd) {
7021 taskTopI = -1;
7022 }
7023 replyChainEnd = -1;
7024 } else {
7025 // If we were in the middle of a chain, well the
7026 // activity that started it all doesn't want anything
7027 // special, so leave it all as-is.
7028 replyChainEnd = -1;
7029 }
7030 } else {
7031 // Reached the bottom of the task -- any reply chain
7032 // should be left as-is.
7033 replyChainEnd = -1;
7034 }
7035
7036 } else if (target.resultTo != null) {
7037 // If this activity is sending a reply to a previous
7038 // activity, we can't do anything with it now until
7039 // we reach the start of the reply chain.
7040 // XXX note that we are assuming the result is always
7041 // to the previous activity, which is almost always
7042 // the case but we really shouldn't count on.
7043 if (replyChainEnd < 0) {
7044 replyChainEnd = targetI;
7045 }
7046
7047 } else if (taskTopI >= 0 && allowTaskReparenting
7048 && task.affinity != null
7049 && task.affinity.equals(target.taskAffinity)) {
7050 // We are inside of another task... if this activity has
7051 // an affinity for our task, then either remove it if we are
7052 // clearing or move it over to our task. Note that
7053 // we currently punt on the case where we are resetting a
7054 // task that is not at the top but who has activities above
7055 // with an affinity to it... this is really not a normal
7056 // case, and we will need to later pull that task to the front
7057 // and usually at that point we will do the reset and pick
7058 // up those remaining activities. (This only happens if
7059 // someone starts an activity in a new task from an activity
7060 // in a task that is not currently on top.)
7061 if (forceReset || finishOnTaskLaunch) {
7062 if (replyChainEnd < 0) {
7063 replyChainEnd = targetI;
7064 }
7065 HistoryRecord p = null;
7066 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7067 p = (HistoryRecord)mHistory.get(srcPos);
7068 if (p.finishing) {
7069 continue;
7070 }
7071 if (finishActivityLocked(p, srcPos,
7072 Activity.RESULT_CANCELED, null, "reset")) {
7073 taskTopI--;
7074 lastReparentPos--;
7075 replyChainEnd--;
7076 srcPos--;
7077 }
7078 }
7079 replyChainEnd = -1;
7080 } else {
7081 if (replyChainEnd < 0) {
7082 replyChainEnd = targetI;
7083 }
7084 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7085 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7086 if (p.finishing) {
7087 continue;
7088 }
7089 if (lastReparentPos < 0) {
7090 lastReparentPos = taskTopI;
7091 taskTop = p;
7092 } else {
7093 lastReparentPos--;
7094 }
7095 mHistory.remove(srcPos);
7096 p.task.numActivities--;
7097 p.task = task;
7098 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007099 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007100 + " in to resetting task " + task);
7101 task.numActivities++;
7102 mWindowManager.moveAppToken(lastReparentPos, p);
7103 mWindowManager.setAppGroupId(p, p.task.taskId);
7104 if (VALIDATE_TOKENS) {
7105 mWindowManager.validateAppTokens(mHistory);
7106 }
7107 }
7108 replyChainEnd = -1;
7109
7110 // Now we've moved it in to place... but what if this is
7111 // a singleTop activity and we have put it on top of another
7112 // instance of the same activity? Then we drop the instance
7113 // below so it remains singleTop.
7114 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7115 for (int j=lastReparentPos-1; j>=0; j--) {
7116 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7117 if (p.finishing) {
7118 continue;
7119 }
7120 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7121 if (finishActivityLocked(p, j,
7122 Activity.RESULT_CANCELED, null, "replace")) {
7123 taskTopI--;
7124 lastReparentPos--;
7125 }
7126 }
7127 }
7128 }
7129 }
7130 }
7131
7132 target = below;
7133 targetI = i;
7134 }
7135
7136 return taskTop;
7137 }
7138
7139 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007140 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007141 */
7142 public void moveTaskToFront(int task) {
7143 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7144 "moveTaskToFront()");
7145
7146 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007147 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7148 Binder.getCallingUid(), "Task to front")) {
7149 return;
7150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007151 final long origId = Binder.clearCallingIdentity();
7152 try {
7153 int N = mRecentTasks.size();
7154 for (int i=0; i<N; i++) {
7155 TaskRecord tr = mRecentTasks.get(i);
7156 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007157 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158 return;
7159 }
7160 }
7161 for (int i=mHistory.size()-1; i>=0; i--) {
7162 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7163 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007164 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 return;
7166 }
7167 }
7168 } finally {
7169 Binder.restoreCallingIdentity(origId);
7170 }
7171 }
7172 }
7173
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007174 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007175 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007176
7177 final int task = tr.taskId;
7178 int top = mHistory.size()-1;
7179
7180 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7181 // nothing to do!
7182 return;
7183 }
7184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007185 ArrayList moved = new ArrayList();
7186
7187 // Applying the affinities may have removed entries from the history,
7188 // so get the size again.
7189 top = mHistory.size()-1;
7190 int pos = top;
7191
7192 // Shift all activities with this task up to the top
7193 // of the stack, keeping them in the same internal order.
7194 while (pos >= 0) {
7195 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007196 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007197 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7198 boolean first = true;
7199 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007200 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007201 mHistory.remove(pos);
7202 mHistory.add(top, r);
7203 moved.add(0, r);
7204 top--;
7205 if (first) {
7206 addRecentTask(r.task);
7207 first = false;
7208 }
7209 }
7210 pos--;
7211 }
7212
Joe Onorato8a9b2202010-02-26 18:56:32 -08007213 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007214 "Prepare to front transition: task=" + tr);
7215 if (reason != null &&
7216 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7217 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7218 HistoryRecord r = topRunningActivityLocked(null);
7219 if (r != null) {
7220 mNoAnimActivities.add(r);
7221 }
7222 } else {
7223 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7224 }
7225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007226 mWindowManager.moveAppTokensToTop(moved);
7227 if (VALIDATE_TOKENS) {
7228 mWindowManager.validateAppTokens(mHistory);
7229 }
7230
7231 finishTaskMove(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007232 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007233 }
7234
7235 private final void finishTaskMove(int task) {
7236 resumeTopActivityLocked(null);
7237 }
7238
7239 public void moveTaskToBack(int task) {
7240 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7241 "moveTaskToBack()");
7242
7243 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007244 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7245 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7246 Binder.getCallingUid(), "Task to back")) {
7247 return;
7248 }
7249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007251 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 Binder.restoreCallingIdentity(origId);
7253 }
7254 }
7255
7256 /**
7257 * Moves an activity, and all of the other activities within the same task, to the bottom
7258 * of the history stack. The activity's order within the task is unchanged.
7259 *
7260 * @param token A reference to the activity we wish to move
7261 * @param nonRoot If false then this only works if the activity is the root
7262 * of a task; if true it will work for any activity in a task.
7263 * @return Returns true if the move completed, false if not.
7264 */
7265 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7266 synchronized(this) {
7267 final long origId = Binder.clearCallingIdentity();
7268 int taskId = getTaskForActivityLocked(token, !nonRoot);
7269 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007270 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271 }
7272 Binder.restoreCallingIdentity(origId);
7273 }
7274 return false;
7275 }
7276
7277 /**
7278 * Worker method for rearranging history stack. Implements the function of moving all
7279 * activities for a specific task (gathering them if disjoint) into a single group at the
7280 * bottom of the stack.
7281 *
7282 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7283 * to premeptively cancel the move.
7284 *
7285 * @param task The taskId to collect and move to the bottom.
7286 * @return Returns true if the move completed, false if not.
7287 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007288 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007289 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007290
7291 // If we have a watcher, preflight the move before committing to it. First check
7292 // for *other* available tasks, but if none are available, then try again allowing the
7293 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007294 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295 HistoryRecord next = topRunningActivityLocked(null, task);
7296 if (next == null) {
7297 next = topRunningActivityLocked(null, 0);
7298 }
7299 if (next != null) {
7300 // ask watcher if this is allowed
7301 boolean moveOK = true;
7302 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007303 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007304 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007305 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 }
7307 if (!moveOK) {
7308 return false;
7309 }
7310 }
7311 }
7312
7313 ArrayList moved = new ArrayList();
7314
Joe Onorato8a9b2202010-02-26 18:56:32 -08007315 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007317
7318 final int N = mHistory.size();
7319 int bottom = 0;
7320 int pos = 0;
7321
7322 // Shift all activities with this task down to the bottom
7323 // of the stack, keeping them in the same internal order.
7324 while (pos < N) {
7325 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007326 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007327 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7328 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007329 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007330 mHistory.remove(pos);
7331 mHistory.add(bottom, r);
7332 moved.add(r);
7333 bottom++;
7334 }
7335 pos++;
7336 }
7337
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007338 if (reason != null &&
7339 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7340 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7341 HistoryRecord r = topRunningActivityLocked(null);
7342 if (r != null) {
7343 mNoAnimActivities.add(r);
7344 }
7345 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007346 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007348 mWindowManager.moveAppTokensToBottom(moved);
7349 if (VALIDATE_TOKENS) {
7350 mWindowManager.validateAppTokens(mHistory);
7351 }
7352
7353 finishTaskMove(task);
7354 return true;
7355 }
7356
7357 public void moveTaskBackwards(int task) {
7358 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7359 "moveTaskBackwards()");
7360
7361 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007362 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7363 Binder.getCallingUid(), "Task backwards")) {
7364 return;
7365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007366 final long origId = Binder.clearCallingIdentity();
7367 moveTaskBackwardsLocked(task);
7368 Binder.restoreCallingIdentity(origId);
7369 }
7370 }
7371
7372 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007373 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007374 }
7375
7376 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7377 synchronized(this) {
7378 return getTaskForActivityLocked(token, onlyRoot);
7379 }
7380 }
7381
7382 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7383 final int N = mHistory.size();
7384 TaskRecord lastTask = null;
7385 for (int i=0; i<N; i++) {
7386 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7387 if (r == token) {
7388 if (!onlyRoot || lastTask != r.task) {
7389 return r.task.taskId;
7390 }
7391 return -1;
7392 }
7393 lastTask = r.task;
7394 }
7395
7396 return -1;
7397 }
7398
7399 /**
7400 * Returns the top activity in any existing task matching the given
7401 * Intent. Returns null if no such task is found.
7402 */
7403 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7404 ComponentName cls = intent.getComponent();
7405 if (info.targetActivity != null) {
7406 cls = new ComponentName(info.packageName, info.targetActivity);
7407 }
7408
7409 TaskRecord cp = null;
7410
7411 final int N = mHistory.size();
7412 for (int i=(N-1); i>=0; i--) {
7413 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7414 if (!r.finishing && r.task != cp
7415 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7416 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007417 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007418 // + "/aff=" + r.task.affinity + " to new cls="
7419 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7420 if (r.task.affinity != null) {
7421 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007422 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 return r;
7424 }
7425 } else if (r.task.intent != null
7426 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007427 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007428 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007429 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 return r;
7431 } else if (r.task.affinityIntent != null
7432 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007433 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007435 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 return r;
7437 }
7438 }
7439 }
7440
7441 return null;
7442 }
7443
7444 /**
7445 * Returns the first activity (starting from the top of the stack) that
7446 * is the same as the given activity. Returns null if no such activity
7447 * is found.
7448 */
7449 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7450 ComponentName cls = intent.getComponent();
7451 if (info.targetActivity != null) {
7452 cls = new ComponentName(info.packageName, info.targetActivity);
7453 }
7454
7455 final int N = mHistory.size();
7456 for (int i=(N-1); i>=0; i--) {
7457 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7458 if (!r.finishing) {
7459 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007460 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007462 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007463 return r;
7464 }
7465 }
7466 }
7467
7468 return null;
7469 }
7470
7471 public void finishOtherInstances(IBinder token, ComponentName className) {
7472 synchronized(this) {
7473 final long origId = Binder.clearCallingIdentity();
7474
7475 int N = mHistory.size();
7476 TaskRecord lastTask = null;
7477 for (int i=0; i<N; i++) {
7478 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7479 if (r.realActivity.equals(className)
7480 && r != token && lastTask != r.task) {
7481 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7482 null, "others")) {
7483 i--;
7484 N--;
7485 }
7486 }
7487 lastTask = r.task;
7488 }
7489
7490 Binder.restoreCallingIdentity(origId);
7491 }
7492 }
7493
7494 // =========================================================
7495 // THUMBNAILS
7496 // =========================================================
7497
7498 public void reportThumbnail(IBinder token,
7499 Bitmap thumbnail, CharSequence description) {
7500 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7501 final long origId = Binder.clearCallingIdentity();
7502 sendPendingThumbnail(null, token, thumbnail, description, true);
7503 Binder.restoreCallingIdentity(origId);
7504 }
7505
7506 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7507 Bitmap thumbnail, CharSequence description, boolean always) {
7508 TaskRecord task = null;
7509 ArrayList receivers = null;
7510
7511 //System.out.println("Send pending thumbnail: " + r);
7512
7513 synchronized(this) {
7514 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007515 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007516 if (index < 0) {
7517 return;
7518 }
7519 r = (HistoryRecord)mHistory.get(index);
7520 }
7521 if (thumbnail == null) {
7522 thumbnail = r.thumbnail;
7523 description = r.description;
7524 }
7525 if (thumbnail == null && !always) {
7526 // If there is no thumbnail, and this entry is not actually
7527 // going away, then abort for now and pick up the next
7528 // thumbnail we get.
7529 return;
7530 }
7531 task = r.task;
7532
7533 int N = mPendingThumbnails.size();
7534 int i=0;
7535 while (i<N) {
7536 PendingThumbnailsRecord pr =
7537 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7538 //System.out.println("Looking in " + pr.pendingRecords);
7539 if (pr.pendingRecords.remove(r)) {
7540 if (receivers == null) {
7541 receivers = new ArrayList();
7542 }
7543 receivers.add(pr);
7544 if (pr.pendingRecords.size() == 0) {
7545 pr.finished = true;
7546 mPendingThumbnails.remove(i);
7547 N--;
7548 continue;
7549 }
7550 }
7551 i++;
7552 }
7553 }
7554
7555 if (receivers != null) {
7556 final int N = receivers.size();
7557 for (int i=0; i<N; i++) {
7558 try {
7559 PendingThumbnailsRecord pr =
7560 (PendingThumbnailsRecord)receivers.get(i);
7561 pr.receiver.newThumbnail(
7562 task != null ? task.taskId : -1, thumbnail, description);
7563 if (pr.finished) {
7564 pr.receiver.finished();
7565 }
7566 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007567 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568 }
7569 }
7570 }
7571 }
7572
7573 // =========================================================
7574 // CONTENT PROVIDERS
7575 // =========================================================
7576
7577 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7578 List providers = null;
7579 try {
7580 providers = ActivityThread.getPackageManager().
7581 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007582 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 } catch (RemoteException ex) {
7584 }
7585 if (providers != null) {
7586 final int N = providers.size();
7587 for (int i=0; i<N; i++) {
7588 ProviderInfo cpi =
7589 (ProviderInfo)providers.get(i);
7590 ContentProviderRecord cpr =
7591 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7592 if (cpr == null) {
7593 cpr = new ContentProviderRecord(cpi, app.info);
7594 mProvidersByClass.put(cpi.name, cpr);
7595 }
7596 app.pubProviders.put(cpi.name, cpr);
7597 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007598 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 }
7600 }
7601 return providers;
7602 }
7603
7604 private final String checkContentProviderPermissionLocked(
7605 ProviderInfo cpi, ProcessRecord r, int mode) {
7606 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7607 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7608 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7609 cpi.exported ? -1 : cpi.applicationInfo.uid)
7610 == PackageManager.PERMISSION_GRANTED
7611 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7612 return null;
7613 }
7614 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7615 cpi.exported ? -1 : cpi.applicationInfo.uid)
7616 == PackageManager.PERMISSION_GRANTED) {
7617 return null;
7618 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007619
7620 PathPermission[] pps = cpi.pathPermissions;
7621 if (pps != null) {
7622 int i = pps.length;
7623 while (i > 0) {
7624 i--;
7625 PathPermission pp = pps[i];
7626 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7627 cpi.exported ? -1 : cpi.applicationInfo.uid)
7628 == PackageManager.PERMISSION_GRANTED
7629 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7630 return null;
7631 }
7632 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7633 cpi.exported ? -1 : cpi.applicationInfo.uid)
7634 == PackageManager.PERMISSION_GRANTED) {
7635 return null;
7636 }
7637 }
7638 }
7639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007640 String msg = "Permission Denial: opening provider " + cpi.name
7641 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7642 + ", uid=" + callingUid + ") requires "
7643 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007644 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007645 return msg;
7646 }
7647
7648 private final ContentProviderHolder getContentProviderImpl(
7649 IApplicationThread caller, String name) {
7650 ContentProviderRecord cpr;
7651 ProviderInfo cpi = null;
7652
7653 synchronized(this) {
7654 ProcessRecord r = null;
7655 if (caller != null) {
7656 r = getRecordForAppLocked(caller);
7657 if (r == null) {
7658 throw new SecurityException(
7659 "Unable to find app for caller " + caller
7660 + " (pid=" + Binder.getCallingPid()
7661 + ") when getting content provider " + name);
7662 }
7663 }
7664
7665 // First check if this content provider has been published...
7666 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7667 if (cpr != null) {
7668 cpi = cpr.info;
7669 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7670 return new ContentProviderHolder(cpi,
7671 cpi.readPermission != null
7672 ? cpi.readPermission : cpi.writePermission);
7673 }
7674
7675 if (r != null && cpr.canRunHere(r)) {
7676 // This provider has been published or is in the process
7677 // of being published... but it is also allowed to run
7678 // in the caller's process, so don't make a connection
7679 // and just let the caller instantiate its own instance.
7680 if (cpr.provider != null) {
7681 // don't give caller the provider object, it needs
7682 // to make its own.
7683 cpr = new ContentProviderRecord(cpr);
7684 }
7685 return cpr;
7686 }
7687
7688 final long origId = Binder.clearCallingIdentity();
7689
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007690 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007691 // return it right away.
7692 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007693 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007694 "Adding provider requested by "
7695 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007696 + cpr.info.processName);
7697 Integer cnt = r.conProviders.get(cpr);
7698 if (cnt == null) {
7699 r.conProviders.put(cpr, new Integer(1));
7700 } else {
7701 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007703 cpr.clients.add(r);
7704 } else {
7705 cpr.externals++;
7706 }
7707
7708 if (cpr.app != null) {
7709 updateOomAdjLocked(cpr.app);
7710 }
7711
7712 Binder.restoreCallingIdentity(origId);
7713
7714 } else {
7715 try {
7716 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007717 resolveContentProvider(name,
7718 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007719 } catch (RemoteException ex) {
7720 }
7721 if (cpi == null) {
7722 return null;
7723 }
7724
7725 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7726 return new ContentProviderHolder(cpi,
7727 cpi.readPermission != null
7728 ? cpi.readPermission : cpi.writePermission);
7729 }
7730
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007731 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7732 && !cpi.processName.equals("system")) {
7733 // If this content provider does not run in the system
7734 // process, and the system is not yet ready to run other
7735 // processes, then fail fast instead of hanging.
7736 throw new IllegalArgumentException(
7737 "Attempt to launch content provider before system ready");
7738 }
7739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007740 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7741 final boolean firstClass = cpr == null;
7742 if (firstClass) {
7743 try {
7744 ApplicationInfo ai =
7745 ActivityThread.getPackageManager().
7746 getApplicationInfo(
7747 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007748 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007750 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751 + cpi.name);
7752 return null;
7753 }
7754 cpr = new ContentProviderRecord(cpi, ai);
7755 } catch (RemoteException ex) {
7756 // pm is in same process, this will never happen.
7757 }
7758 }
7759
7760 if (r != null && cpr.canRunHere(r)) {
7761 // If this is a multiprocess provider, then just return its
7762 // info and allow the caller to instantiate it. Only do
7763 // this if the provider is the same user as the caller's
7764 // process, or can run as root (so can be in any process).
7765 return cpr;
7766 }
7767
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007768 if (DEBUG_PROVIDER) {
7769 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007770 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007771 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007772 }
7773
7774 // This is single process, and our app is now connecting to it.
7775 // See if we are already in the process of launching this
7776 // provider.
7777 final int N = mLaunchingProviders.size();
7778 int i;
7779 for (i=0; i<N; i++) {
7780 if (mLaunchingProviders.get(i) == cpr) {
7781 break;
7782 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007783 }
7784
7785 // If the provider is not already being launched, then get it
7786 // started.
7787 if (i >= N) {
7788 final long origId = Binder.clearCallingIdentity();
7789 ProcessRecord proc = startProcessLocked(cpi.processName,
7790 cpr.appInfo, false, 0, "content provider",
7791 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007792 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007793 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007794 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007795 + cpi.applicationInfo.packageName + "/"
7796 + cpi.applicationInfo.uid + " for provider "
7797 + name + ": process is bad");
7798 return null;
7799 }
7800 cpr.launchingApp = proc;
7801 mLaunchingProviders.add(cpr);
7802 Binder.restoreCallingIdentity(origId);
7803 }
7804
7805 // Make sure the provider is published (the same provider class
7806 // may be published under multiple names).
7807 if (firstClass) {
7808 mProvidersByClass.put(cpi.name, cpr);
7809 }
7810 mProvidersByName.put(name, cpr);
7811
7812 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007813 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007814 "Adding provider requested by "
7815 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007816 + cpr.info.processName);
7817 Integer cnt = r.conProviders.get(cpr);
7818 if (cnt == null) {
7819 r.conProviders.put(cpr, new Integer(1));
7820 } else {
7821 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 cpr.clients.add(r);
7824 } else {
7825 cpr.externals++;
7826 }
7827 }
7828 }
7829
7830 // Wait for the provider to be published...
7831 synchronized (cpr) {
7832 while (cpr.provider == null) {
7833 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007834 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007835 + cpi.applicationInfo.packageName + "/"
7836 + cpi.applicationInfo.uid + " for provider "
7837 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007838 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007839 cpi.applicationInfo.packageName,
7840 cpi.applicationInfo.uid, name);
7841 return null;
7842 }
7843 try {
7844 cpr.wait();
7845 } catch (InterruptedException ex) {
7846 }
7847 }
7848 }
7849 return cpr;
7850 }
7851
7852 public final ContentProviderHolder getContentProvider(
7853 IApplicationThread caller, String name) {
7854 if (caller == null) {
7855 String msg = "null IApplicationThread when getting content provider "
7856 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007857 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007858 throw new SecurityException(msg);
7859 }
7860
7861 return getContentProviderImpl(caller, name);
7862 }
7863
7864 private ContentProviderHolder getContentProviderExternal(String name) {
7865 return getContentProviderImpl(null, name);
7866 }
7867
7868 /**
7869 * Drop a content provider from a ProcessRecord's bookkeeping
7870 * @param cpr
7871 */
7872 public void removeContentProvider(IApplicationThread caller, String name) {
7873 synchronized (this) {
7874 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7875 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007876 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007877 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007878 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007879 return;
7880 }
7881 final ProcessRecord r = getRecordForAppLocked(caller);
7882 if (r == null) {
7883 throw new SecurityException(
7884 "Unable to find app for caller " + caller +
7885 " when removing content provider " + name);
7886 }
7887 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007888 ContentProviderRecord localCpr = (ContentProviderRecord)
7889 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007890 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007891 + r.info.processName + " from process "
7892 + localCpr.appInfo.processName);
7893 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007894 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08007895 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007896 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007897 return;
7898 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007899 Integer cnt = r.conProviders.get(localCpr);
7900 if (cnt == null || cnt.intValue() <= 1) {
7901 localCpr.clients.remove(r);
7902 r.conProviders.remove(localCpr);
7903 } else {
7904 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
7905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 }
7907 updateOomAdjLocked();
7908 }
7909 }
7910
7911 private void removeContentProviderExternal(String name) {
7912 synchronized (this) {
7913 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
7914 if(cpr == null) {
7915 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08007916 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007917 return;
7918 }
7919
7920 //update content provider record entry info
7921 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
7922 localCpr.externals--;
7923 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007924 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007925 }
7926 updateOomAdjLocked();
7927 }
7928 }
7929
7930 public final void publishContentProviders(IApplicationThread caller,
7931 List<ContentProviderHolder> providers) {
7932 if (providers == null) {
7933 return;
7934 }
7935
7936 synchronized(this) {
7937 final ProcessRecord r = getRecordForAppLocked(caller);
7938 if (r == null) {
7939 throw new SecurityException(
7940 "Unable to find app for caller " + caller
7941 + " (pid=" + Binder.getCallingPid()
7942 + ") when publishing content providers");
7943 }
7944
7945 final long origId = Binder.clearCallingIdentity();
7946
7947 final int N = providers.size();
7948 for (int i=0; i<N; i++) {
7949 ContentProviderHolder src = providers.get(i);
7950 if (src == null || src.info == null || src.provider == null) {
7951 continue;
7952 }
7953 ContentProviderRecord dst =
7954 (ContentProviderRecord)r.pubProviders.get(src.info.name);
7955 if (dst != null) {
7956 mProvidersByClass.put(dst.info.name, dst);
7957 String names[] = dst.info.authority.split(";");
7958 for (int j = 0; j < names.length; j++) {
7959 mProvidersByName.put(names[j], dst);
7960 }
7961
7962 int NL = mLaunchingProviders.size();
7963 int j;
7964 for (j=0; j<NL; j++) {
7965 if (mLaunchingProviders.get(j) == dst) {
7966 mLaunchingProviders.remove(j);
7967 j--;
7968 NL--;
7969 }
7970 }
7971 synchronized (dst) {
7972 dst.provider = src.provider;
7973 dst.app = r;
7974 dst.notifyAll();
7975 }
7976 updateOomAdjLocked(r);
7977 }
7978 }
7979
7980 Binder.restoreCallingIdentity(origId);
7981 }
7982 }
7983
7984 public static final void installSystemProviders() {
7985 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
7986 List providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007987 if (providers != null) {
7988 for (int i=providers.size()-1; i>=0; i--) {
7989 ProviderInfo pi = (ProviderInfo)providers.get(i);
7990 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007991 Slog.w(TAG, "Not installing system proc provider " + pi.name
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007992 + ": not system .apk");
7993 providers.remove(i);
7994 }
7995 }
7996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007997 mSystemThread.installSystemProviders(providers);
7998 }
7999
8000 // =========================================================
8001 // GLOBAL MANAGEMENT
8002 // =========================================================
8003
8004 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8005 ApplicationInfo info, String customProcess) {
8006 String proc = customProcess != null ? customProcess : info.processName;
8007 BatteryStatsImpl.Uid.Proc ps = null;
8008 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8009 synchronized (stats) {
8010 ps = stats.getProcessStatsLocked(info.uid, proc);
8011 }
8012 return new ProcessRecord(ps, thread, info, proc);
8013 }
8014
8015 final ProcessRecord addAppLocked(ApplicationInfo info) {
8016 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8017
8018 if (app == null) {
8019 app = newProcessRecordLocked(null, info, null);
8020 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008021 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008022 }
8023
8024 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8025 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8026 app.persistent = true;
8027 app.maxAdj = CORE_SERVER_ADJ;
8028 }
8029 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8030 mPersistentStartingProcesses.add(app);
8031 startProcessLocked(app, "added application", app.processName);
8032 }
8033
8034 return app;
8035 }
8036
8037 public void unhandledBack() {
8038 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8039 "unhandledBack()");
8040
8041 synchronized(this) {
8042 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008043 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 TAG, "Performing unhandledBack(): stack size = " + count);
8045 if (count > 1) {
8046 final long origId = Binder.clearCallingIdentity();
8047 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8048 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8049 Binder.restoreCallingIdentity(origId);
8050 }
8051 }
8052 }
8053
8054 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8055 String name = uri.getAuthority();
8056 ContentProviderHolder cph = getContentProviderExternal(name);
8057 ParcelFileDescriptor pfd = null;
8058 if (cph != null) {
8059 // We record the binder invoker's uid in thread-local storage before
8060 // going to the content provider to open the file. Later, in the code
8061 // that handles all permissions checks, we look for this uid and use
8062 // that rather than the Activity Manager's own uid. The effect is that
8063 // we do the check against the caller's permissions even though it looks
8064 // to the content provider like the Activity Manager itself is making
8065 // the request.
8066 sCallerIdentity.set(new Identity(
8067 Binder.getCallingPid(), Binder.getCallingUid()));
8068 try {
8069 pfd = cph.provider.openFile(uri, "r");
8070 } catch (FileNotFoundException e) {
8071 // do nothing; pfd will be returned null
8072 } finally {
8073 // Ensure that whatever happens, we clean up the identity state
8074 sCallerIdentity.remove();
8075 }
8076
8077 // We've got the fd now, so we're done with the provider.
8078 removeContentProviderExternal(name);
8079 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008080 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 }
8082 return pfd;
8083 }
8084
8085 public void goingToSleep() {
8086 synchronized(this) {
8087 mSleeping = true;
8088 mWindowManager.setEventDispatching(false);
8089
8090 if (mResumedActivity != null) {
8091 pauseIfSleepingLocked();
8092 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008093 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008094 }
8095 }
8096 }
8097
Dianne Hackborn55280a92009-05-07 15:53:46 -07008098 public boolean shutdown(int timeout) {
8099 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8100 != PackageManager.PERMISSION_GRANTED) {
8101 throw new SecurityException("Requires permission "
8102 + android.Manifest.permission.SHUTDOWN);
8103 }
8104
8105 boolean timedout = false;
8106
8107 synchronized(this) {
8108 mShuttingDown = true;
8109 mWindowManager.setEventDispatching(false);
8110
8111 if (mResumedActivity != null) {
8112 pauseIfSleepingLocked();
8113 final long endTime = System.currentTimeMillis() + timeout;
8114 while (mResumedActivity != null || mPausingActivity != null) {
8115 long delay = endTime - System.currentTimeMillis();
8116 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008117 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008118 timedout = true;
8119 break;
8120 }
8121 try {
8122 this.wait();
8123 } catch (InterruptedException e) {
8124 }
8125 }
8126 }
8127 }
8128
8129 mUsageStatsService.shutdown();
8130 mBatteryStatsService.shutdown();
8131
8132 return timedout;
8133 }
8134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008135 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008136 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 if (!mGoingToSleep.isHeld()) {
8138 mGoingToSleep.acquire();
8139 if (mLaunchingActivity.isHeld()) {
8140 mLaunchingActivity.release();
8141 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8142 }
8143 }
8144
8145 // If we are not currently pausing an activity, get the current
8146 // one to pause. If we are pausing one, we will just let that stuff
8147 // run and release the wake lock when all done.
8148 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008149 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8150 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008151 startPausingLocked(false, true);
8152 }
8153 }
8154 }
8155
8156 public void wakingUp() {
8157 synchronized(this) {
8158 if (mGoingToSleep.isHeld()) {
8159 mGoingToSleep.release();
8160 }
8161 mWindowManager.setEventDispatching(true);
8162 mSleeping = false;
8163 resumeTopActivityLocked(null);
8164 }
8165 }
8166
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008167 public void stopAppSwitches() {
8168 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8169 != PackageManager.PERMISSION_GRANTED) {
8170 throw new SecurityException("Requires permission "
8171 + android.Manifest.permission.STOP_APP_SWITCHES);
8172 }
8173
8174 synchronized(this) {
8175 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8176 + APP_SWITCH_DELAY_TIME;
8177 mDidAppSwitch = false;
8178 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8179 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8180 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8181 }
8182 }
8183
8184 public void resumeAppSwitches() {
8185 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8186 != PackageManager.PERMISSION_GRANTED) {
8187 throw new SecurityException("Requires permission "
8188 + android.Manifest.permission.STOP_APP_SWITCHES);
8189 }
8190
8191 synchronized(this) {
8192 // Note that we don't execute any pending app switches... we will
8193 // let those wait until either the timeout, or the next start
8194 // activity request.
8195 mAppSwitchesAllowedTime = 0;
8196 }
8197 }
8198
8199 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8200 String name) {
8201 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8202 return true;
8203 }
8204
8205 final int perm = checkComponentPermission(
8206 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8207 callingUid, -1);
8208 if (perm == PackageManager.PERMISSION_GRANTED) {
8209 return true;
8210 }
8211
Joe Onorato8a9b2202010-02-26 18:56:32 -08008212 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008213 return false;
8214 }
8215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008216 public void setDebugApp(String packageName, boolean waitForDebugger,
8217 boolean persistent) {
8218 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8219 "setDebugApp()");
8220
8221 // Note that this is not really thread safe if there are multiple
8222 // callers into it at the same time, but that's not a situation we
8223 // care about.
8224 if (persistent) {
8225 final ContentResolver resolver = mContext.getContentResolver();
8226 Settings.System.putString(
8227 resolver, Settings.System.DEBUG_APP,
8228 packageName);
8229 Settings.System.putInt(
8230 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8231 waitForDebugger ? 1 : 0);
8232 }
8233
8234 synchronized (this) {
8235 if (!persistent) {
8236 mOrigDebugApp = mDebugApp;
8237 mOrigWaitForDebugger = mWaitForDebugger;
8238 }
8239 mDebugApp = packageName;
8240 mWaitForDebugger = waitForDebugger;
8241 mDebugTransient = !persistent;
8242 if (packageName != null) {
8243 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008244 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008245 Binder.restoreCallingIdentity(origId);
8246 }
8247 }
8248 }
8249
8250 public void setAlwaysFinish(boolean enabled) {
8251 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8252 "setAlwaysFinish()");
8253
8254 Settings.System.putInt(
8255 mContext.getContentResolver(),
8256 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8257
8258 synchronized (this) {
8259 mAlwaysFinishActivities = enabled;
8260 }
8261 }
8262
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008263 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008264 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008265 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008267 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268 }
8269 }
8270
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008271 public boolean isUserAMonkey() {
8272 // For now the fact that there is a controller implies
8273 // we have a monkey.
8274 synchronized (this) {
8275 return mController != null;
8276 }
8277 }
8278
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008279 public void registerActivityWatcher(IActivityWatcher watcher) {
8280 mWatchers.register(watcher);
8281 }
8282
8283 public void unregisterActivityWatcher(IActivityWatcher watcher) {
8284 mWatchers.unregister(watcher);
8285 }
8286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008287 public final void enterSafeMode() {
8288 synchronized(this) {
8289 // It only makes sense to do this before the system is ready
8290 // and started launching other packages.
8291 if (!mSystemReady) {
8292 try {
8293 ActivityThread.getPackageManager().enterSafeMode();
8294 } catch (RemoteException e) {
8295 }
8296
8297 View v = LayoutInflater.from(mContext).inflate(
8298 com.android.internal.R.layout.safe_mode, null);
8299 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8300 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8301 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8302 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8303 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8304 lp.format = v.getBackground().getOpacity();
8305 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8306 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8307 ((WindowManager)mContext.getSystemService(
8308 Context.WINDOW_SERVICE)).addView(v, lp);
8309 }
8310 }
8311 }
8312
8313 public void noteWakeupAlarm(IIntentSender sender) {
8314 if (!(sender instanceof PendingIntentRecord)) {
8315 return;
8316 }
8317 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8318 synchronized (stats) {
8319 if (mBatteryStatsService.isOnBattery()) {
8320 mBatteryStatsService.enforceCallingPermission();
8321 PendingIntentRecord rec = (PendingIntentRecord)sender;
8322 int MY_UID = Binder.getCallingUid();
8323 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8324 BatteryStatsImpl.Uid.Pkg pkg =
8325 stats.getPackageStatsLocked(uid, rec.key.packageName);
8326 pkg.incWakeupsLocked();
8327 }
8328 }
8329 }
8330
8331 public boolean killPidsForMemory(int[] pids) {
8332 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
8333 throw new SecurityException("killPidsForMemory only available to the system");
8334 }
8335
8336 // XXX Note: don't acquire main activity lock here, because the window
8337 // manager calls in with its locks held.
8338
8339 boolean killed = false;
8340 synchronized (mPidsSelfLocked) {
8341 int[] types = new int[pids.length];
8342 int worstType = 0;
8343 for (int i=0; i<pids.length; i++) {
8344 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8345 if (proc != null) {
8346 int type = proc.setAdj;
8347 types[i] = type;
8348 if (type > worstType) {
8349 worstType = type;
8350 }
8351 }
8352 }
8353
8354 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8355 // then constrain it so we will kill all hidden procs.
8356 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8357 worstType = HIDDEN_APP_MIN_ADJ;
8358 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008359 Slog.w(TAG, "Killing processes for memory at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008360 for (int i=0; i<pids.length; i++) {
8361 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8362 if (proc == null) {
8363 continue;
8364 }
8365 int adj = proc.setAdj;
8366 if (adj >= worstType) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008367 Slog.w(TAG, "Killing for memory: " + proc + " (adj "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008368 + adj + ")");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008369 EventLog.writeEvent(EventLogTags.AM_KILL_FOR_MEMORY, proc.pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008370 proc.processName, adj);
8371 killed = true;
8372 Process.killProcess(pids[i]);
8373 }
8374 }
8375 }
8376 return killed;
8377 }
8378
8379 public void reportPss(IApplicationThread caller, int pss) {
8380 Watchdog.PssRequestor req;
8381 String name;
8382 ProcessRecord callerApp;
8383 synchronized (this) {
8384 if (caller == null) {
8385 return;
8386 }
8387 callerApp = getRecordForAppLocked(caller);
8388 if (callerApp == null) {
8389 return;
8390 }
8391 callerApp.lastPss = pss;
8392 req = callerApp;
8393 name = callerApp.processName;
8394 }
8395 Watchdog.getInstance().reportPss(req, name, pss);
8396 if (!callerApp.persistent) {
8397 removeRequestedPss(callerApp);
8398 }
8399 }
8400
8401 public void requestPss(Runnable completeCallback) {
8402 ArrayList<ProcessRecord> procs;
8403 synchronized (this) {
8404 mRequestPssCallback = completeCallback;
8405 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008406 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8407 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008408 if (!proc.persistent) {
8409 mRequestPssList.add(proc);
8410 }
8411 }
8412 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8413 }
8414
8415 int oldPri = Process.getThreadPriority(Process.myTid());
8416 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8417 for (int i=procs.size()-1; i>=0; i--) {
8418 ProcessRecord proc = procs.get(i);
8419 proc.lastPss = 0;
8420 proc.requestPss();
8421 }
8422 Process.setThreadPriority(oldPri);
8423 }
8424
8425 void removeRequestedPss(ProcessRecord proc) {
8426 Runnable callback = null;
8427 synchronized (this) {
8428 if (mRequestPssList.remove(proc)) {
8429 if (mRequestPssList.size() == 0) {
8430 callback = mRequestPssCallback;
8431 mRequestPssCallback = null;
8432 }
8433 }
8434 }
8435
8436 if (callback != null) {
8437 callback.run();
8438 }
8439 }
8440
8441 public void collectPss(Watchdog.PssStats stats) {
8442 stats.mEmptyPss = 0;
8443 stats.mEmptyCount = 0;
8444 stats.mBackgroundPss = 0;
8445 stats.mBackgroundCount = 0;
8446 stats.mServicePss = 0;
8447 stats.mServiceCount = 0;
8448 stats.mVisiblePss = 0;
8449 stats.mVisibleCount = 0;
8450 stats.mForegroundPss = 0;
8451 stats.mForegroundCount = 0;
8452 stats.mNoPssCount = 0;
8453 synchronized (this) {
8454 int i;
8455 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8456 ? mProcDeaths.length : stats.mProcDeaths.length;
8457 int aggr = 0;
8458 for (i=0; i<NPD; i++) {
8459 aggr += mProcDeaths[i];
8460 stats.mProcDeaths[i] = aggr;
8461 }
8462 while (i<stats.mProcDeaths.length) {
8463 stats.mProcDeaths[i] = 0;
8464 i++;
8465 }
8466
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008467 for (i=mLruProcesses.size()-1; i>=0; i--) {
8468 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008469 if (proc.persistent) {
8470 continue;
8471 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008472 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008473 if (proc.lastPss == 0) {
8474 stats.mNoPssCount++;
8475 continue;
8476 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008477 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8478 if (proc.empty) {
8479 stats.mEmptyPss += proc.lastPss;
8480 stats.mEmptyCount++;
8481 } else {
8482 stats.mBackgroundPss += proc.lastPss;
8483 stats.mBackgroundCount++;
8484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008485 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8486 stats.mVisiblePss += proc.lastPss;
8487 stats.mVisibleCount++;
8488 } else {
8489 stats.mForegroundPss += proc.lastPss;
8490 stats.mForegroundCount++;
8491 }
8492 }
8493 }
8494 }
8495
8496 public final void startRunning(String pkg, String cls, String action,
8497 String data) {
8498 synchronized(this) {
8499 if (mStartRunning) {
8500 return;
8501 }
8502 mStartRunning = true;
8503 mTopComponent = pkg != null && cls != null
8504 ? new ComponentName(pkg, cls) : null;
8505 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8506 mTopData = data;
8507 if (!mSystemReady) {
8508 return;
8509 }
8510 }
8511
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008512 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008513 }
8514
8515 private void retrieveSettings() {
8516 final ContentResolver resolver = mContext.getContentResolver();
8517 String debugApp = Settings.System.getString(
8518 resolver, Settings.System.DEBUG_APP);
8519 boolean waitForDebugger = Settings.System.getInt(
8520 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8521 boolean alwaysFinishActivities = Settings.System.getInt(
8522 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8523
8524 Configuration configuration = new Configuration();
8525 Settings.System.getConfiguration(resolver, configuration);
8526
8527 synchronized (this) {
8528 mDebugApp = mOrigDebugApp = debugApp;
8529 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8530 mAlwaysFinishActivities = alwaysFinishActivities;
8531 // This happens before any activities are started, so we can
8532 // change mConfiguration in-place.
8533 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008534 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008535 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008536 }
8537 }
8538
8539 public boolean testIsSystemReady() {
8540 // no need to synchronize(this) just to read & return the value
8541 return mSystemReady;
8542 }
8543
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008544 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008545 // In the simulator, startRunning will never have been called, which
8546 // normally sets a few crucial variables. Do it here instead.
8547 if (!Process.supportsProcesses()) {
8548 mStartRunning = true;
8549 mTopAction = Intent.ACTION_MAIN;
8550 }
8551
8552 synchronized(this) {
8553 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008554 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 return;
8556 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008557
8558 // Check to see if there are any update receivers to run.
8559 if (!mDidUpdate) {
8560 if (mWaitingUpdate) {
8561 return;
8562 }
8563 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8564 List<ResolveInfo> ris = null;
8565 try {
8566 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8567 intent, null, 0);
8568 } catch (RemoteException e) {
8569 }
8570 if (ris != null) {
8571 for (int i=ris.size()-1; i>=0; i--) {
8572 if ((ris.get(i).activityInfo.applicationInfo.flags
8573 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8574 ris.remove(i);
8575 }
8576 }
8577 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8578 for (int i=0; i<ris.size(); i++) {
8579 ActivityInfo ai = ris.get(i).activityInfo;
8580 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8581 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008582 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008583 finisher = new IIntentReceiver.Stub() {
8584 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008585 String data, Bundle extras, boolean ordered,
8586 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008587 throws RemoteException {
8588 synchronized (ActivityManagerService.this) {
8589 mDidUpdate = true;
8590 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008591 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008592 }
8593 };
8594 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008595 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008596 broadcastIntentLocked(null, null, intent, null, finisher,
8597 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008598 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008599 mWaitingUpdate = true;
8600 }
8601 }
8602 }
8603 if (mWaitingUpdate) {
8604 return;
8605 }
8606 mDidUpdate = true;
8607 }
8608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008609 mSystemReady = true;
8610 if (!mStartRunning) {
8611 return;
8612 }
8613 }
8614
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008615 ArrayList<ProcessRecord> procsToKill = null;
8616 synchronized(mPidsSelfLocked) {
8617 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8618 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8619 if (!isAllowedWhileBooting(proc.info)){
8620 if (procsToKill == null) {
8621 procsToKill = new ArrayList<ProcessRecord>();
8622 }
8623 procsToKill.add(proc);
8624 }
8625 }
8626 }
8627
8628 if (procsToKill != null) {
8629 synchronized(this) {
8630 for (int i=procsToKill.size()-1; i>=0; i--) {
8631 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008632 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008633 removeProcessLocked(proc, true);
8634 }
8635 }
8636 }
8637
Joe Onorato8a9b2202010-02-26 18:56:32 -08008638 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008639 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008640 SystemClock.uptimeMillis());
8641
8642 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008643 // Make sure we have no pre-ready processes sitting around.
8644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008645 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8646 ResolveInfo ri = mContext.getPackageManager()
8647 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008648 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 CharSequence errorMsg = null;
8650 if (ri != null) {
8651 ActivityInfo ai = ri.activityInfo;
8652 ApplicationInfo app = ai.applicationInfo;
8653 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8654 mTopAction = Intent.ACTION_FACTORY_TEST;
8655 mTopData = null;
8656 mTopComponent = new ComponentName(app.packageName,
8657 ai.name);
8658 } else {
8659 errorMsg = mContext.getResources().getText(
8660 com.android.internal.R.string.factorytest_not_system);
8661 }
8662 } else {
8663 errorMsg = mContext.getResources().getText(
8664 com.android.internal.R.string.factorytest_no_action);
8665 }
8666 if (errorMsg != null) {
8667 mTopAction = null;
8668 mTopData = null;
8669 mTopComponent = null;
8670 Message msg = Message.obtain();
8671 msg.what = SHOW_FACTORY_ERROR_MSG;
8672 msg.getData().putCharSequence("msg", errorMsg);
8673 mHandler.sendMessage(msg);
8674 }
8675 }
8676 }
8677
8678 retrieveSettings();
8679
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008680 if (goingCallback != null) goingCallback.run();
8681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008682 synchronized (this) {
8683 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8684 try {
8685 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008686 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008687 if (apps != null) {
8688 int N = apps.size();
8689 int i;
8690 for (i=0; i<N; i++) {
8691 ApplicationInfo info
8692 = (ApplicationInfo)apps.get(i);
8693 if (info != null &&
8694 !info.packageName.equals("android")) {
8695 addAppLocked(info);
8696 }
8697 }
8698 }
8699 } catch (RemoteException ex) {
8700 // pm is in same process, this will never happen.
8701 }
8702 }
8703
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008704 // Start up initial activity.
8705 mBooting = true;
8706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008707 try {
8708 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8709 Message msg = Message.obtain();
8710 msg.what = SHOW_UID_ERROR_MSG;
8711 mHandler.sendMessage(msg);
8712 }
8713 } catch (RemoteException e) {
8714 }
8715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008716 resumeTopActivityLocked(null);
8717 }
8718 }
8719
Dan Egnorb7f03672009-12-09 16:22:32 -08008720 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008721 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008722 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008723 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008724 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008725 startAppProblemLocked(app);
8726 app.stopFreezingAllLocked();
8727 return handleAppCrashLocked(app);
8728 }
8729
Dan Egnorb7f03672009-12-09 16:22:32 -08008730 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008731 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008732 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008733 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008734 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8735 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008736 startAppProblemLocked(app);
8737 app.stopFreezingAllLocked();
8738 }
8739
8740 /**
8741 * Generate a process error record, suitable for attachment to a ProcessRecord.
8742 *
8743 * @param app The ProcessRecord in which the error occurred.
8744 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8745 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008746 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008747 * @param shortMsg Short message describing the crash.
8748 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008749 * @param stackTrace Full crash stack trace, may be null.
8750 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008751 * @return Returns a fully-formed AppErrorStateInfo record.
8752 */
8753 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008754 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008755 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 report.condition = condition;
8758 report.processName = app.processName;
8759 report.pid = app.pid;
8760 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008761 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008762 report.shortMsg = shortMsg;
8763 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008764 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008765
8766 return report;
8767 }
8768
Dan Egnor42471dd2010-01-07 17:25:22 -08008769 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008770 synchronized (this) {
8771 app.crashing = false;
8772 app.crashingReport = null;
8773 app.notResponding = false;
8774 app.notRespondingReport = null;
8775 if (app.anrDialog == fromDialog) {
8776 app.anrDialog = null;
8777 }
8778 if (app.waitDialog == fromDialog) {
8779 app.waitDialog = null;
8780 }
8781 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008782 handleAppCrashLocked(app);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008783 Slog.i(ActivityManagerService.TAG, "Killing process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008784 + app.processName
8785 + " (pid=" + app.pid + ") at user's request");
8786 Process.killProcess(app.pid);
8787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 }
8789 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008790
Dan Egnorb7f03672009-12-09 16:22:32 -08008791 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008792 long now = SystemClock.uptimeMillis();
8793
8794 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8795 app.info.uid);
8796 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8797 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008798 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008799 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008800 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 app.info.processName, app.info.uid);
8802 killServicesLocked(app, false);
8803 for (int i=mHistory.size()-1; i>=0; i--) {
8804 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8805 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008806 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 + r.intent.getComponent().flattenToShortString());
8808 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8809 }
8810 }
8811 if (!app.persistent) {
8812 // We don't want to start this process again until the user
8813 // explicitly does so... but for persistent process, we really
8814 // need to keep it running. If a persistent process is actually
8815 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008816 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008817 app.info.processName);
8818 mBadProcesses.put(app.info.processName, app.info.uid, now);
8819 app.bad = true;
8820 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8821 app.removed = true;
8822 removeProcessLocked(app, false);
8823 return false;
8824 }
8825 }
8826
8827 // Bump up the crash count of any services currently running in the proc.
8828 if (app.services.size() != 0) {
8829 // Any services running in the application need to be placed
8830 // back in the pending list.
8831 Iterator it = app.services.iterator();
8832 while (it.hasNext()) {
8833 ServiceRecord sr = (ServiceRecord)it.next();
8834 sr.crashCount++;
8835 }
8836 }
8837
8838 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
8839 return true;
8840 }
8841
8842 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008843 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
8844 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008845 skipCurrentReceiverLocked(app);
8846 }
8847
8848 void skipCurrentReceiverLocked(ProcessRecord app) {
8849 boolean reschedule = false;
8850 BroadcastRecord r = app.curReceiver;
8851 if (r != null) {
8852 // The current broadcast is waiting for this app's receiver
8853 // to be finished. Looks like that's not going to happen, so
8854 // let the broadcast continue.
8855 logBroadcastReceiverDiscard(r);
8856 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8857 r.resultExtras, r.resultAbort, true);
8858 reschedule = true;
8859 }
8860 r = mPendingBroadcast;
8861 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008862 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008863 "skip & discard pending app " + r);
8864 logBroadcastReceiverDiscard(r);
8865 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
8866 r.resultExtras, r.resultAbort, true);
8867 reschedule = true;
8868 }
8869 if (reschedule) {
8870 scheduleBroadcastsLocked();
8871 }
8872 }
8873
Dan Egnor60d87622009-12-16 16:32:58 -08008874 /**
8875 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
8876 * The application process will exit immediately after this call returns.
8877 * @param app object of the crashing app, null for the system server
8878 * @param crashInfo describing the exception
8879 */
8880 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
8881 ProcessRecord r = findAppProcess(app);
8882
8883 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
8884 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008885 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008886 crashInfo.exceptionClassName,
8887 crashInfo.exceptionMessage,
8888 crashInfo.throwFileName,
8889 crashInfo.throwLineNumber);
8890
Dan Egnor42471dd2010-01-07 17:25:22 -08008891 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008892
8893 crashApplication(r, crashInfo);
8894 }
8895
8896 /**
8897 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
8898 * @param app object of the crashing app, null for the system server
8899 * @param tag reported by the caller
8900 * @param crashInfo describing the context of the error
8901 * @return true if the process should exit immediately (WTF is fatal)
8902 */
8903 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08008904 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08008905 ProcessRecord r = findAppProcess(app);
8906
8907 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
8908 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08008909 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08008910 tag, crashInfo.exceptionMessage);
8911
Dan Egnor42471dd2010-01-07 17:25:22 -08008912 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08008913
Doug Zongker43866e02010-01-07 12:09:54 -08008914 if (Settings.Secure.getInt(mContext.getContentResolver(),
8915 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008916 crashApplication(r, crashInfo);
8917 return true;
8918 } else {
8919 return false;
8920 }
8921 }
8922
8923 /**
8924 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
8925 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
8926 */
8927 private ProcessRecord findAppProcess(IBinder app) {
8928 if (app == null) {
8929 return null;
8930 }
8931
8932 synchronized (this) {
8933 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
8934 final int NA = apps.size();
8935 for (int ia=0; ia<NA; ia++) {
8936 ProcessRecord p = apps.valueAt(ia);
8937 if (p.thread != null && p.thread.asBinder() == app) {
8938 return p;
8939 }
8940 }
8941 }
8942
Joe Onorato8a9b2202010-02-26 18:56:32 -08008943 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08008944 return null;
8945 }
8946 }
8947
8948 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08008949 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08008950 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08008951 * @param process which caused the error, null means the system server
8952 * @param activity which triggered the error, null if unknown
8953 * @param parent activity related to the error, null if unknown
8954 * @param subject line related to the error, null if absent
8955 * @param report in long form describing the error, null if absent
8956 * @param logFile to include in the report, null if none
8957 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08008958 */
Dan Egnor42471dd2010-01-07 17:25:22 -08008959 private void addErrorToDropBox(String eventType,
8960 ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
8961 String subject, String report, File logFile,
Dan Egnor60d87622009-12-16 16:32:58 -08008962 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008963 String dropboxTag;
8964 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008965 dropboxTag = "system_server_" + eventType;
Dan Egnor42471dd2010-01-07 17:25:22 -08008966 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08008967 dropboxTag = "system_app_" + eventType;
8968 } else {
8969 dropboxTag = "data_app_" + eventType;
8970 }
8971
8972 DropBoxManager dbox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
8973 if (dbox != null && dbox.isTagEnabled(dropboxTag)) {
8974 StringBuilder sb = new StringBuilder(1024);
Dan Egnor42471dd2010-01-07 17:25:22 -08008975 if (process == null || process.pid == MY_PID) {
Dan Egnor60d87622009-12-16 16:32:58 -08008976 sb.append("Process: system_server\n");
8977 } else {
Dan Egnor42471dd2010-01-07 17:25:22 -08008978 sb.append("Process: ").append(process.processName).append("\n");
Dan Egnor66c40e72010-01-26 16:23:11 -08008979 }
8980 if (process != null) {
8981 int flags = process.info.flags;
8982 IPackageManager pm = ActivityThread.getPackageManager();
8983 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
8984 for (String pkg : process.pkgList) {
8985 sb.append("Package: ").append(pkg);
8986 try {
8987 PackageInfo pi = pm.getPackageInfo(pkg, 0);
8988 if (pi != null) {
8989 sb.append(" v").append(pi.versionCode);
8990 if (pi.versionName != null) {
8991 sb.append(" (").append(pi.versionName).append(")");
8992 }
8993 }
8994 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008995 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor66c40e72010-01-26 16:23:11 -08008996 }
8997 sb.append("\n");
8998 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008999 }
9000 if (activity != null) {
9001 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9002 }
9003 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9004 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9005 }
9006 if (parent != null && parent != activity) {
9007 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9008 }
9009 if (subject != null) {
9010 sb.append("Subject: ").append(subject).append("\n");
9011 }
9012 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9013 sb.append("\n");
9014 if (report != null) {
9015 sb.append(report);
9016 }
9017 if (logFile != null) {
9018 try {
9019 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9020 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009021 Slog.e(TAG, "Error reading " + logFile, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009022 }
9023 }
Dan Egnor60d87622009-12-16 16:32:58 -08009024 if (crashInfo != null && crashInfo.stackTrace != null) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009025 sb.append(crashInfo.stackTrace);
Dan Egnor60d87622009-12-16 16:32:58 -08009026 }
9027 dbox.addText(dropboxTag, sb.toString());
9028 }
9029 }
9030
9031 /**
9032 * Bring up the "unexpected error" dialog box for a crashing app.
9033 * Deal with edge cases (intercepts from instrumented applications,
9034 * ActivityController, error intent receivers, that sort of thing).
9035 * @param r the application crashing
9036 * @param crashInfo describing the failure
9037 */
9038 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009039 long timeMillis = System.currentTimeMillis();
9040 String shortMsg = crashInfo.exceptionClassName;
9041 String longMsg = crashInfo.exceptionMessage;
9042 String stackTrace = crashInfo.stackTrace;
9043 if (shortMsg != null && longMsg != null) {
9044 longMsg = shortMsg + ": " + longMsg;
9045 } else if (shortMsg != null) {
9046 longMsg = shortMsg;
9047 }
9048
Dan Egnor60d87622009-12-16 16:32:58 -08009049 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009050 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009051 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009052 try {
9053 String name = r != null ? r.processName : null;
9054 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009055 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009056 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009057 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009058 + " at watcher's request");
9059 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009060 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009061 }
9062 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009063 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009064 }
9065 }
9066
9067 final long origId = Binder.clearCallingIdentity();
9068
9069 // If this process is running instrumentation, finish it.
9070 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009071 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009072 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009073 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9074 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009075 Bundle info = new Bundle();
9076 info.putString("shortMsg", shortMsg);
9077 info.putString("longMsg", longMsg);
9078 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9079 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009080 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 }
9082
Dan Egnor60d87622009-12-16 16:32:58 -08009083 // If we can't identify the process or it's already exceeded its crash quota,
9084 // quit right away without showing a crash dialog.
9085 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009087 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088 }
9089
9090 Message msg = Message.obtain();
9091 msg.what = SHOW_ERROR_MSG;
9092 HashMap data = new HashMap();
9093 data.put("result", result);
9094 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009095 msg.obj = data;
9096 mHandler.sendMessage(msg);
9097
9098 Binder.restoreCallingIdentity(origId);
9099 }
9100
9101 int res = result.get();
9102
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009103 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009104 synchronized (this) {
9105 if (r != null) {
9106 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9107 SystemClock.uptimeMillis());
9108 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009109 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009110 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009111 }
9112 }
9113
9114 if (appErrorIntent != null) {
9115 try {
9116 mContext.startActivity(appErrorIntent);
9117 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009118 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009121 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009122
9123 Intent createAppErrorIntentLocked(ProcessRecord r,
9124 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9125 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009126 if (report == null) {
9127 return null;
9128 }
9129 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9130 result.setComponent(r.errorReportReceiver);
9131 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9132 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9133 return result;
9134 }
9135
Dan Egnorb7f03672009-12-09 16:22:32 -08009136 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9137 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009138 if (r.errorReportReceiver == null) {
9139 return null;
9140 }
9141
9142 if (!r.crashing && !r.notResponding) {
9143 return null;
9144 }
9145
Dan Egnorb7f03672009-12-09 16:22:32 -08009146 ApplicationErrorReport report = new ApplicationErrorReport();
9147 report.packageName = r.info.packageName;
9148 report.installerPackageName = r.errorReportReceiver.getPackageName();
9149 report.processName = r.processName;
9150 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009151 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009152
Dan Egnorb7f03672009-12-09 16:22:32 -08009153 if (r.crashing) {
9154 report.type = ApplicationErrorReport.TYPE_CRASH;
9155 report.crashInfo = crashInfo;
9156 } else if (r.notResponding) {
9157 report.type = ApplicationErrorReport.TYPE_ANR;
9158 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009159
Dan Egnorb7f03672009-12-09 16:22:32 -08009160 report.anrInfo.activity = r.notRespondingReport.tag;
9161 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9162 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009163 }
9164
Dan Egnorb7f03672009-12-09 16:22:32 -08009165 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009166 }
9167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009168 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9169 // assume our apps are happy - lazy create the list
9170 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9171
9172 synchronized (this) {
9173
9174 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009175 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9176 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9178 // This one's in trouble, so we'll generate a report for it
9179 // crashes are higher priority (in case there's a crash *and* an anr)
9180 ActivityManager.ProcessErrorStateInfo report = null;
9181 if (app.crashing) {
9182 report = app.crashingReport;
9183 } else if (app.notResponding) {
9184 report = app.notRespondingReport;
9185 }
9186
9187 if (report != null) {
9188 if (errList == null) {
9189 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9190 }
9191 errList.add(report);
9192 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009193 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009194 " crashing = " + app.crashing +
9195 " notResponding = " + app.notResponding);
9196 }
9197 }
9198 }
9199 }
9200
9201 return errList;
9202 }
9203
9204 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9205 // Lazy instantiation of list
9206 List<ActivityManager.RunningAppProcessInfo> runList = null;
9207 synchronized (this) {
9208 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009209 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9210 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009211 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9212 // Generate process state info for running application
9213 ActivityManager.RunningAppProcessInfo currApp =
9214 new ActivityManager.RunningAppProcessInfo(app.processName,
9215 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009216 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009218 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009219 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9220 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9221 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009222 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9223 } else if (adj >= HOME_APP_ADJ) {
9224 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9225 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 } else if (adj >= SECONDARY_SERVER_ADJ) {
9227 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9228 } else if (adj >= VISIBLE_APP_ADJ) {
9229 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9230 } else {
9231 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9232 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009233 currApp.importanceReasonCode = app.adjTypeCode;
9234 if (app.adjSource instanceof ProcessRecord) {
9235 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9236 } else if (app.adjSource instanceof HistoryRecord) {
9237 HistoryRecord r = (HistoryRecord)app.adjSource;
9238 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9239 }
9240 if (app.adjTarget instanceof ComponentName) {
9241 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9242 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009243 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009244 // + " lru=" + currApp.lru);
9245 if (runList == null) {
9246 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9247 }
9248 runList.add(currApp);
9249 }
9250 }
9251 }
9252 return runList;
9253 }
9254
9255 @Override
9256 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009257 if (checkCallingPermission(android.Manifest.permission.DUMP)
9258 != PackageManager.PERMISSION_GRANTED) {
9259 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9260 + Binder.getCallingPid()
9261 + ", uid=" + Binder.getCallingUid()
9262 + " without permission "
9263 + android.Manifest.permission.DUMP);
9264 return;
9265 }
9266
9267 boolean dumpAll = false;
9268
9269 int opti = 0;
9270 while (opti < args.length) {
9271 String opt = args[opti];
9272 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9273 break;
9274 }
9275 opti++;
9276 if ("-a".equals(opt)) {
9277 dumpAll = true;
9278 } else if ("-h".equals(opt)) {
9279 pw.println("Activity manager dump options:");
9280 pw.println(" [-a] [h- [cmd] ...");
9281 pw.println(" cmd may be one of:");
9282 pw.println(" activities: activity stack state");
9283 pw.println(" broadcasts: broadcast state");
9284 pw.println(" intents: pending intent state");
9285 pw.println(" processes: process state");
9286 pw.println(" providers: content provider state");
9287 pw.println(" services: service state");
9288 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009289 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009290 } else {
9291 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009292 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009293 }
9294
9295 // Is the caller requesting to dump a particular piece of data?
9296 if (opti < args.length) {
9297 String cmd = args[opti];
9298 opti++;
9299 if ("activities".equals(cmd) || "a".equals(cmd)) {
9300 synchronized (this) {
9301 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009302 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009303 return;
9304 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9305 synchronized (this) {
9306 dumpBroadcastsLocked(fd, pw, args, opti, true);
9307 }
9308 return;
9309 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9310 synchronized (this) {
9311 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9312 }
9313 return;
9314 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9315 synchronized (this) {
9316 dumpProcessesLocked(fd, pw, args, opti, true);
9317 }
9318 return;
9319 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9320 synchronized (this) {
9321 dumpProvidersLocked(fd, pw, args, opti, true);
9322 }
9323 return;
9324 } else if ("service".equals(cmd)) {
9325 dumpService(fd, pw, args, opti, true);
9326 return;
9327 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9328 synchronized (this) {
9329 dumpServicesLocked(fd, pw, args, opti, true);
9330 }
9331 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009332 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009333 }
9334
9335 // No piece of data specified, dump everything.
9336 synchronized (this) {
9337 boolean needSep;
9338 if (dumpAll) {
9339 pw.println("Providers in Current Activity Manager State:");
9340 }
9341 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9342 if (needSep) {
9343 pw.println(" ");
9344 }
9345 if (dumpAll) {
9346 pw.println("-------------------------------------------------------------------------------");
9347 pw.println("Broadcasts in Current Activity Manager State:");
9348 }
9349 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9350 if (needSep) {
9351 pw.println(" ");
9352 }
9353 if (dumpAll) {
9354 pw.println("-------------------------------------------------------------------------------");
9355 pw.println("Services in Current Activity Manager State:");
9356 }
9357 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9358 if (needSep) {
9359 pw.println(" ");
9360 }
9361 if (dumpAll) {
9362 pw.println("-------------------------------------------------------------------------------");
9363 pw.println("PendingIntents in Current Activity Manager State:");
9364 }
9365 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9366 if (needSep) {
9367 pw.println(" ");
9368 }
9369 if (dumpAll) {
9370 pw.println("-------------------------------------------------------------------------------");
9371 pw.println("Activities in Current Activity Manager State:");
9372 }
9373 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9374 if (needSep) {
9375 pw.println(" ");
9376 }
9377 if (dumpAll) {
9378 pw.println("-------------------------------------------------------------------------------");
9379 pw.println("Processes in Current Activity Manager State:");
9380 }
9381 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9382 }
9383 }
9384
9385 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9386 int opti, boolean dumpAll, boolean needHeader) {
9387 if (needHeader) {
9388 pw.println(" Activity stack:");
9389 }
9390 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9391 pw.println(" ");
9392 pw.println(" Running activities (most recent first):");
9393 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9394 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009395 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009396 pw.println(" Activities waiting for another to become visible:");
9397 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9398 }
9399 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009400 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009401 pw.println(" Activities waiting to stop:");
9402 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9403 }
9404 if (mFinishingActivities.size() > 0) {
9405 pw.println(" ");
9406 pw.println(" Activities waiting to finish:");
9407 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009409
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009410 pw.println(" ");
9411 pw.println(" mPausingActivity: " + mPausingActivity);
9412 pw.println(" mResumedActivity: " + mResumedActivity);
9413 pw.println(" mFocusedActivity: " + mFocusedActivity);
9414 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009415
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009416 if (dumpAll && mRecentTasks.size() > 0) {
9417 pw.println(" ");
9418 pw.println("Recent tasks in Current Activity Manager State:");
9419
9420 final int N = mRecentTasks.size();
9421 for (int i=0; i<N; i++) {
9422 TaskRecord tr = mRecentTasks.get(i);
9423 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9424 pw.println(tr);
9425 mRecentTasks.get(i).dump(pw, " ");
9426 }
9427 }
9428
9429 pw.println(" ");
9430 pw.println(" mCurTask: " + mCurTask);
9431
9432 return true;
9433 }
9434
9435 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9436 int opti, boolean dumpAll) {
9437 boolean needSep = false;
9438 int numPers = 0;
9439
9440 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009441 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9442 final int NA = procs.size();
9443 for (int ia=0; ia<NA; ia++) {
9444 if (!needSep) {
9445 pw.println(" All known processes:");
9446 needSep = true;
9447 }
9448 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009449 pw.print(r.persistent ? " *PERS*" : " *APP*");
9450 pw.print(" UID "); pw.print(procs.keyAt(ia));
9451 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 r.dump(pw, " ");
9453 if (r.persistent) {
9454 numPers++;
9455 }
9456 }
9457 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009458 }
9459
9460 if (mLruProcesses.size() > 0) {
9461 if (needSep) pw.println(" ");
9462 needSep = true;
9463 pw.println(" Running processes (most recent first):");
9464 dumpProcessList(pw, this, mLruProcesses, " ",
9465 "App ", "PERS", true);
9466 needSep = true;
9467 }
9468
9469 synchronized (mPidsSelfLocked) {
9470 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 if (needSep) pw.println(" ");
9472 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009473 pw.println(" PID mappings:");
9474 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9475 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9476 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009477 }
9478 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009479 }
9480
9481 if (mForegroundProcesses.size() > 0) {
9482 if (needSep) pw.println(" ");
9483 needSep = true;
9484 pw.println(" Foreground Processes:");
9485 for (int i=0; i<mForegroundProcesses.size(); i++) {
9486 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9487 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009488 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009489 }
9490
9491 if (mPersistentStartingProcesses.size() > 0) {
9492 if (needSep) pw.println(" ");
9493 needSep = true;
9494 pw.println(" Persisent processes that are starting:");
9495 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9496 "Starting Norm", "Restarting PERS", false);
9497 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009498
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009499 if (mStartingProcesses.size() > 0) {
9500 if (needSep) pw.println(" ");
9501 needSep = true;
9502 pw.println(" Processes that are starting:");
9503 dumpProcessList(pw, this, mStartingProcesses, " ",
9504 "Starting Norm", "Starting PERS", false);
9505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009506
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009507 if (mRemovedProcesses.size() > 0) {
9508 if (needSep) pw.println(" ");
9509 needSep = true;
9510 pw.println(" Processes that are being removed:");
9511 dumpProcessList(pw, this, mRemovedProcesses, " ",
9512 "Removed Norm", "Removed PERS", false);
9513 }
9514
9515 if (mProcessesOnHold.size() > 0) {
9516 if (needSep) pw.println(" ");
9517 needSep = true;
9518 pw.println(" Processes that are on old until the system is ready:");
9519 dumpProcessList(pw, this, mProcessesOnHold, " ",
9520 "OnHold Norm", "OnHold PERS", false);
9521 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009522
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009523 if (mProcessesToGc.size() > 0) {
9524 if (needSep) pw.println(" ");
9525 needSep = true;
9526 pw.println(" Processes that are waiting to GC:");
9527 long now = SystemClock.uptimeMillis();
9528 for (int i=0; i<mProcessesToGc.size(); i++) {
9529 ProcessRecord proc = mProcessesToGc.get(i);
9530 pw.print(" Process "); pw.println(proc);
9531 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9532 pw.print(", last gced=");
9533 pw.print(now-proc.lastRequestedGc);
9534 pw.print(" ms ago, last lowMem=");
9535 pw.print(now-proc.lastLowMemory);
9536 pw.println(" ms ago");
9537
9538 }
9539 }
9540
9541 if (mProcessCrashTimes.getMap().size() > 0) {
9542 if (needSep) pw.println(" ");
9543 needSep = true;
9544 pw.println(" Time since processes crashed:");
9545 long now = SystemClock.uptimeMillis();
9546 for (Map.Entry<String, SparseArray<Long>> procs
9547 : mProcessCrashTimes.getMap().entrySet()) {
9548 SparseArray<Long> uids = procs.getValue();
9549 final int N = uids.size();
9550 for (int i=0; i<N; i++) {
9551 pw.print(" Process "); pw.print(procs.getKey());
9552 pw.print(" uid "); pw.print(uids.keyAt(i));
9553 pw.print(": last crashed ");
9554 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009555 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009556 }
9557 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009559
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009560 if (mBadProcesses.getMap().size() > 0) {
9561 if (needSep) pw.println(" ");
9562 needSep = true;
9563 pw.println(" Bad processes:");
9564 for (Map.Entry<String, SparseArray<Long>> procs
9565 : mBadProcesses.getMap().entrySet()) {
9566 SparseArray<Long> uids = procs.getValue();
9567 final int N = uids.size();
9568 for (int i=0; i<N; i++) {
9569 pw.print(" Bad process "); pw.print(procs.getKey());
9570 pw.print(" uid "); pw.print(uids.keyAt(i));
9571 pw.print(": crashed at time ");
9572 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009573 }
9574 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009576
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009577 pw.println(" ");
9578 pw.println(" mHomeProcess: " + mHomeProcess);
9579 pw.println(" mConfiguration: " + mConfiguration);
9580 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9581 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9582 || mOrigWaitForDebugger) {
9583 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9584 + " mDebugTransient=" + mDebugTransient
9585 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9586 }
9587 if (mAlwaysFinishActivities || mController != null) {
9588 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9589 + " mController=" + mController);
9590 }
9591 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009592 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009593 pw.println(" mStartRunning=" + mStartRunning
9594 + " mSystemReady=" + mSystemReady
9595 + " mBooting=" + mBooting
9596 + " mBooted=" + mBooted
9597 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598 pw.println(" mGoingToSleep=" + mGoingToSleep);
9599 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009600 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009601
9602 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009603 }
9604
9605 /**
9606 * There are three ways to call this:
9607 * - no service specified: dump all the services
9608 * - a flattened component name that matched an existing service was specified as the
9609 * first arg: dump that one service
9610 * - the first arg isn't the flattened component name of an existing service:
9611 * dump all services whose component contains the first arg as a substring
9612 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009613 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9614 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009615 String[] newArgs;
9616 String componentNameString;
9617 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009618 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009619 componentNameString = null;
9620 newArgs = EMPTY_STRING_ARRAY;
9621 r = null;
9622 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009623 componentNameString = args[opti];
9624 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009625 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9626 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009627 newArgs = new String[args.length - opti];
9628 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009629 }
9630
9631 if (r != null) {
9632 dumpService(fd, pw, r, newArgs);
9633 } else {
9634 for (ServiceRecord r1 : mServices.values()) {
9635 if (componentNameString == null
9636 || r1.name.flattenToString().contains(componentNameString)) {
9637 dumpService(fd, pw, r1, newArgs);
9638 }
9639 }
9640 }
9641 }
9642
9643 /**
9644 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9645 * there is a thread associated with the service.
9646 */
9647 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9648 pw.println(" Service " + r.name.flattenToString());
9649 if (r.app != null && r.app.thread != null) {
9650 try {
9651 // flush anything that is already in the PrintWriter since the thread is going
9652 // to write to the file descriptor directly
9653 pw.flush();
9654 r.app.thread.dumpService(fd, r, args);
9655 pw.print("\n");
9656 } catch (RemoteException e) {
9657 pw.println("got a RemoteException while dumping the service");
9658 }
9659 }
9660 }
9661
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009662 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9663 int opti, boolean dumpAll) {
9664 boolean needSep = false;
9665
9666 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 if (mRegisteredReceivers.size() > 0) {
9668 pw.println(" ");
9669 pw.println(" Registered Receivers:");
9670 Iterator it = mRegisteredReceivers.values().iterator();
9671 while (it.hasNext()) {
9672 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009673 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009674 r.dump(pw, " ");
9675 }
9676 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009678 pw.println(" ");
9679 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009680 mReceiverResolver.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009681 needSep = true;
9682 }
9683
9684 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9685 || mPendingBroadcast != null) {
9686 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009687 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009688 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009690 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9691 pw.println(" Broadcast #" + i + ":");
9692 mParallelBroadcasts.get(i).dump(pw, " ");
9693 }
9694 if (mOrderedBroadcasts.size() > 0) {
9695 pw.println(" ");
9696 pw.println(" Active serialized broadcasts:");
9697 }
9698 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9699 pw.println(" Serialized Broadcast #" + i + ":");
9700 mOrderedBroadcasts.get(i).dump(pw, " ");
9701 }
9702 pw.println(" ");
9703 pw.println(" Pending broadcast:");
9704 if (mPendingBroadcast != null) {
9705 mPendingBroadcast.dump(pw, " ");
9706 } else {
9707 pw.println(" (null)");
9708 }
9709 needSep = true;
9710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009711
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009712 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009713 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009714 pw.println(" Historical broadcasts:");
9715 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9716 BroadcastRecord r = mBroadcastHistory[i];
9717 if (r == null) {
9718 break;
9719 }
9720 pw.println(" Historical Broadcast #" + i + ":");
9721 r.dump(pw, " ");
9722 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009723 needSep = true;
9724 }
9725
9726 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08009727 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009728 pw.println(" Sticky broadcasts:");
9729 StringBuilder sb = new StringBuilder(128);
9730 for (Map.Entry<String, ArrayList<Intent>> ent
9731 : mStickyBroadcasts.entrySet()) {
9732 pw.print(" * Sticky action "); pw.print(ent.getKey());
9733 pw.println(":");
9734 ArrayList<Intent> intents = ent.getValue();
9735 final int N = intents.size();
9736 for (int i=0; i<N; i++) {
9737 sb.setLength(0);
9738 sb.append(" Intent: ");
9739 intents.get(i).toShortString(sb, true, false);
9740 pw.println(sb.toString());
9741 Bundle bundle = intents.get(i).getExtras();
9742 if (bundle != null) {
9743 pw.print(" ");
9744 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009745 }
9746 }
9747 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009748 needSep = true;
9749 }
9750
9751 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009752 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009753 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009754 pw.println(" mHandler:");
9755 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009756 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009758
9759 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009760 }
9761
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009762 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9763 int opti, boolean dumpAll) {
9764 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009766 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009767 if (mServices.size() > 0) {
9768 pw.println(" Active services:");
9769 Iterator<ServiceRecord> it = mServices.values().iterator();
9770 while (it.hasNext()) {
9771 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009772 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009773 r.dump(pw, " ");
9774 }
9775 needSep = true;
9776 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009778
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009779 if (mPendingServices.size() > 0) {
9780 if (needSep) pw.println(" ");
9781 pw.println(" Pending services:");
9782 for (int i=0; i<mPendingServices.size(); i++) {
9783 ServiceRecord r = mPendingServices.get(i);
9784 pw.print(" * Pending "); pw.println(r);
9785 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009786 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009787 needSep = true;
9788 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009789
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009790 if (mRestartingServices.size() > 0) {
9791 if (needSep) pw.println(" ");
9792 pw.println(" Restarting services:");
9793 for (int i=0; i<mRestartingServices.size(); i++) {
9794 ServiceRecord r = mRestartingServices.get(i);
9795 pw.print(" * Restarting "); pw.println(r);
9796 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009797 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009798 needSep = true;
9799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009800
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009801 if (mStoppingServices.size() > 0) {
9802 if (needSep) pw.println(" ");
9803 pw.println(" Stopping services:");
9804 for (int i=0; i<mStoppingServices.size(); i++) {
9805 ServiceRecord r = mStoppingServices.get(i);
9806 pw.print(" * Stopping "); pw.println(r);
9807 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009808 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009809 needSep = true;
9810 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009811
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009812 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 if (mServiceConnections.size() > 0) {
9814 if (needSep) pw.println(" ");
9815 pw.println(" Connection bindings to services:");
9816 Iterator<ConnectionRecord> it
9817 = mServiceConnections.values().iterator();
9818 while (it.hasNext()) {
9819 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009820 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 r.dump(pw, " ");
9822 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009823 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 }
9825 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009826
9827 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009828 }
9829
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009830 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9831 int opti, boolean dumpAll) {
9832 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009834 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835 if (mProvidersByClass.size() > 0) {
9836 if (needSep) pw.println(" ");
9837 pw.println(" Published content providers (by class):");
9838 Iterator it = mProvidersByClass.entrySet().iterator();
9839 while (it.hasNext()) {
9840 Map.Entry e = (Map.Entry)it.next();
9841 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009842 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009843 r.dump(pw, " ");
9844 }
9845 needSep = true;
9846 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009847
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009848 if (mProvidersByName.size() > 0) {
9849 pw.println(" ");
9850 pw.println(" Authority to provider mappings:");
9851 Iterator it = mProvidersByName.entrySet().iterator();
9852 while (it.hasNext()) {
9853 Map.Entry e = (Map.Entry)it.next();
9854 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
9855 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
9856 pw.println(r);
9857 }
9858 needSep = true;
9859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009861
9862 if (mLaunchingProviders.size() > 0) {
9863 if (needSep) pw.println(" ");
9864 pw.println(" Launching content providers:");
9865 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
9866 pw.print(" Launching #"); pw.print(i); pw.print(": ");
9867 pw.println(mLaunchingProviders.get(i));
9868 }
9869 needSep = true;
9870 }
9871
9872 if (mGrantedUriPermissions.size() > 0) {
9873 pw.println();
9874 pw.println("Granted Uri Permissions:");
9875 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9876 int uid = mGrantedUriPermissions.keyAt(i);
9877 HashMap<Uri, UriPermission> perms
9878 = mGrantedUriPermissions.valueAt(i);
9879 pw.print(" * UID "); pw.print(uid);
9880 pw.println(" holds:");
9881 for (UriPermission perm : perms.values()) {
9882 pw.print(" "); pw.println(perm);
9883 perm.dump(pw, " ");
9884 }
9885 }
9886 needSep = true;
9887 }
9888
9889 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009890 }
9891
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009892 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9893 int opti, boolean dumpAll) {
9894 boolean needSep = false;
9895
9896 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009897 if (this.mIntentSenderRecords.size() > 0) {
9898 Iterator<WeakReference<PendingIntentRecord>> it
9899 = mIntentSenderRecords.values().iterator();
9900 while (it.hasNext()) {
9901 WeakReference<PendingIntentRecord> ref = it.next();
9902 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009903 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009904 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009905 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009906 rec.dump(pw, " ");
9907 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009908 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009909 }
9910 }
9911 }
9912 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009913
9914 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009915 }
9916
9917 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009918 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009919 TaskRecord lastTask = null;
9920 for (int i=list.size()-1; i>=0; i--) {
9921 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009922 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009923 if (lastTask != r.task) {
9924 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009925 pw.print(prefix);
9926 pw.print(full ? "* " : " ");
9927 pw.println(lastTask);
9928 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009929 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009930 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009931 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009932 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9933 pw.print(" #"); pw.print(i); pw.print(": ");
9934 pw.println(r);
9935 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009936 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009938 }
9939 }
9940
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009941 private static String buildOomTag(String prefix, String space, int val, int base) {
9942 if (val == base) {
9943 if (space == null) return prefix;
9944 return prefix + " ";
9945 }
9946 return prefix + "+" + Integer.toString(val-base);
9947 }
9948
9949 private static final int dumpProcessList(PrintWriter pw,
9950 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009951 String prefix, String normalLabel, String persistentLabel,
9952 boolean inclOomAdj) {
9953 int numPers = 0;
9954 for (int i=list.size()-1; i>=0; i--) {
9955 ProcessRecord r = (ProcessRecord)list.get(i);
9956 if (false) {
9957 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
9958 + " #" + i + ":");
9959 r.dump(pw, prefix + " ");
9960 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009961 String oomAdj;
9962 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009963 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009964 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009965 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
9966 } else if (r.setAdj >= HOME_APP_ADJ) {
9967 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
9968 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
9969 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
9970 } else if (r.setAdj >= BACKUP_APP_ADJ) {
9971 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
9972 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
9973 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
9974 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
9975 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009976 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009977 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009978 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009979 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009980 } else {
9981 oomAdj = Integer.toString(r.setAdj);
9982 }
9983 String schedGroup;
9984 switch (r.setSchedGroup) {
9985 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9986 schedGroup = "B";
9987 break;
9988 case Process.THREAD_GROUP_DEFAULT:
9989 schedGroup = "F";
9990 break;
9991 default:
9992 schedGroup = Integer.toString(r.setSchedGroup);
9993 break;
9994 }
9995 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009996 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009997 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009998 if (r.adjSource != null || r.adjTarget != null) {
9999 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010000 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 } else {
10003 pw.println(String.format("%s%s #%2d: %s",
10004 prefix, (r.persistent ? persistentLabel : normalLabel),
10005 i, r.toString()));
10006 }
10007 if (r.persistent) {
10008 numPers++;
10009 }
10010 }
10011 return numPers;
10012 }
10013
10014 private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
10015 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010016 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010017 long uptime = SystemClock.uptimeMillis();
10018 long realtime = SystemClock.elapsedRealtime();
10019
10020 if (isCheckinRequest) {
10021 // short checkin version
10022 pw.println(uptime + "," + realtime);
10023 pw.flush();
10024 } else {
10025 pw.println("Applications Memory Usage (kB):");
10026 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10027 }
10028 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10029 ProcessRecord r = (ProcessRecord)list.get(i);
10030 if (r.thread != null) {
10031 if (!isCheckinRequest) {
10032 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10033 pw.flush();
10034 }
10035 try {
10036 r.thread.asBinder().dump(fd, args);
10037 } catch (RemoteException e) {
10038 if (!isCheckinRequest) {
10039 pw.println("Got RemoteException!");
10040 pw.flush();
10041 }
10042 }
10043 }
10044 }
10045 }
10046
10047 /**
10048 * Searches array of arguments for the specified string
10049 * @param args array of argument strings
10050 * @param value value to search for
10051 * @return true if the value is contained in the array
10052 */
10053 private static boolean scanArgs(String[] args, String value) {
10054 if (args != null) {
10055 for (String arg : args) {
10056 if (value.equals(arg)) {
10057 return true;
10058 }
10059 }
10060 }
10061 return false;
10062 }
10063
Dianne Hackborn75b03852009-06-12 15:43:26 -070010064 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010065 int count = mHistory.size();
10066
10067 // convert the token to an entry in the history.
10068 HistoryRecord r = null;
10069 int index = -1;
10070 for (int i=count-1; i>=0; i--) {
10071 Object o = mHistory.get(i);
10072 if (o == token) {
10073 r = (HistoryRecord)o;
10074 index = i;
10075 break;
10076 }
10077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010078
10079 return index;
10080 }
10081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010082 private final void killServicesLocked(ProcessRecord app,
10083 boolean allowRestart) {
10084 // Report disconnected services.
10085 if (false) {
10086 // XXX we are letting the client link to the service for
10087 // death notifications.
10088 if (app.services.size() > 0) {
10089 Iterator it = app.services.iterator();
10090 while (it.hasNext()) {
10091 ServiceRecord r = (ServiceRecord)it.next();
10092 if (r.connections.size() > 0) {
10093 Iterator<ConnectionRecord> jt
10094 = r.connections.values().iterator();
10095 while (jt.hasNext()) {
10096 ConnectionRecord c = jt.next();
10097 if (c.binding.client != app) {
10098 try {
10099 //c.conn.connected(r.className, null);
10100 } catch (Exception e) {
10101 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010102 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010103 + r.shortName
10104 + " from app " + app.processName, e);
10105 }
10106 }
10107 }
10108 }
10109 }
10110 }
10111 }
10112
10113 // Clean up any connections this application has to other services.
10114 if (app.connections.size() > 0) {
10115 Iterator<ConnectionRecord> it = app.connections.iterator();
10116 while (it.hasNext()) {
10117 ConnectionRecord r = it.next();
10118 removeConnectionLocked(r, app, null);
10119 }
10120 }
10121 app.connections.clear();
10122
10123 if (app.services.size() != 0) {
10124 // Any services running in the application need to be placed
10125 // back in the pending list.
10126 Iterator it = app.services.iterator();
10127 while (it.hasNext()) {
10128 ServiceRecord sr = (ServiceRecord)it.next();
10129 synchronized (sr.stats.getBatteryStats()) {
10130 sr.stats.stopLaunchedLocked();
10131 }
10132 sr.app = null;
10133 sr.executeNesting = 0;
10134 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010135
10136 boolean hasClients = sr.bindings.size() > 0;
10137 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010138 Iterator<IntentBindRecord> bindings
10139 = sr.bindings.values().iterator();
10140 while (bindings.hasNext()) {
10141 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010142 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010143 + ": shouldUnbind=" + b.hasBound);
10144 b.binder = null;
10145 b.requested = b.received = b.hasBound = false;
10146 }
10147 }
10148
10149 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010150 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010151 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010152 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010153 sr.crashCount, sr.shortName, app.pid);
10154 bringDownServiceLocked(sr, true);
10155 } else if (!allowRestart) {
10156 bringDownServiceLocked(sr, true);
10157 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010158 boolean canceled = scheduleServiceRestartLocked(sr, true);
10159
10160 // Should the service remain running? Note that in the
10161 // extreme case of so many attempts to deliver a command
10162 // that it failed, that we also will stop it here.
10163 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10164 if (sr.pendingStarts.size() == 0) {
10165 sr.startRequested = false;
10166 if (!hasClients) {
10167 // Whoops, no reason to restart!
10168 bringDownServiceLocked(sr, true);
10169 }
10170 }
10171 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010172 }
10173 }
10174
10175 if (!allowRestart) {
10176 app.services.clear();
10177 }
10178 }
10179
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010180 // Make sure we have no more records on the stopping list.
10181 int i = mStoppingServices.size();
10182 while (i > 0) {
10183 i--;
10184 ServiceRecord sr = mStoppingServices.get(i);
10185 if (sr.app == app) {
10186 mStoppingServices.remove(i);
10187 }
10188 }
10189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010190 app.executingServices.clear();
10191 }
10192
10193 private final void removeDyingProviderLocked(ProcessRecord proc,
10194 ContentProviderRecord cpr) {
10195 synchronized (cpr) {
10196 cpr.launchingApp = null;
10197 cpr.notifyAll();
10198 }
10199
10200 mProvidersByClass.remove(cpr.info.name);
10201 String names[] = cpr.info.authority.split(";");
10202 for (int j = 0; j < names.length; j++) {
10203 mProvidersByName.remove(names[j]);
10204 }
10205
10206 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10207 while (cit.hasNext()) {
10208 ProcessRecord capp = cit.next();
10209 if (!capp.persistent && capp.thread != null
10210 && capp.pid != 0
10211 && capp.pid != MY_PID) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010212 Slog.i(TAG, "Killing app " + capp.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010213 + " (pid " + capp.pid
10214 + ") because provider " + cpr.info.name
10215 + " is in dying process " + proc.processName);
10216 Process.killProcess(capp.pid);
10217 }
10218 }
10219
10220 mLaunchingProviders.remove(cpr);
10221 }
10222
10223 /**
10224 * Main code for cleaning up a process when it has gone away. This is
10225 * called both as a result of the process dying, or directly when stopping
10226 * a process when running in single process mode.
10227 */
10228 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10229 boolean restarting, int index) {
10230 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010231 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010232 }
10233
Dianne Hackborn36124872009-10-08 16:22:03 -070010234 mProcessesToGc.remove(app);
10235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 // Dismiss any open dialogs.
10237 if (app.crashDialog != null) {
10238 app.crashDialog.dismiss();
10239 app.crashDialog = null;
10240 }
10241 if (app.anrDialog != null) {
10242 app.anrDialog.dismiss();
10243 app.anrDialog = null;
10244 }
10245 if (app.waitDialog != null) {
10246 app.waitDialog.dismiss();
10247 app.waitDialog = null;
10248 }
10249
10250 app.crashing = false;
10251 app.notResponding = false;
10252
10253 app.resetPackageList();
10254 app.thread = null;
10255 app.forcingToForeground = null;
10256 app.foregroundServices = false;
10257
10258 killServicesLocked(app, true);
10259
10260 boolean restart = false;
10261
10262 int NL = mLaunchingProviders.size();
10263
10264 // Remove published content providers.
10265 if (!app.pubProviders.isEmpty()) {
10266 Iterator it = app.pubProviders.values().iterator();
10267 while (it.hasNext()) {
10268 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10269 cpr.provider = null;
10270 cpr.app = null;
10271
10272 // See if someone is waiting for this provider... in which
10273 // case we don't remove it, but just let it restart.
10274 int i = 0;
10275 if (!app.bad) {
10276 for (; i<NL; i++) {
10277 if (mLaunchingProviders.get(i) == cpr) {
10278 restart = true;
10279 break;
10280 }
10281 }
10282 } else {
10283 i = NL;
10284 }
10285
10286 if (i >= NL) {
10287 removeDyingProviderLocked(app, cpr);
10288 NL = mLaunchingProviders.size();
10289 }
10290 }
10291 app.pubProviders.clear();
10292 }
10293
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010294 // Take care of any launching providers waiting for this process.
10295 if (checkAppInLaunchingProvidersLocked(app, false)) {
10296 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010297 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 // Unregister from connected content providers.
10300 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010301 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010302 while (it.hasNext()) {
10303 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10304 cpr.clients.remove(app);
10305 }
10306 app.conProviders.clear();
10307 }
10308
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010309 // At this point there may be remaining entries in mLaunchingProviders
10310 // where we were the only one waiting, so they are no longer of use.
10311 // Look for these and clean up if found.
10312 // XXX Commented out for now. Trying to figure out a way to reproduce
10313 // the actual situation to identify what is actually going on.
10314 if (false) {
10315 for (int i=0; i<NL; i++) {
10316 ContentProviderRecord cpr = (ContentProviderRecord)
10317 mLaunchingProviders.get(i);
10318 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10319 synchronized (cpr) {
10320 cpr.launchingApp = null;
10321 cpr.notifyAll();
10322 }
10323 }
10324 }
10325 }
10326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327 skipCurrentReceiverLocked(app);
10328
10329 // Unregister any receivers.
10330 if (app.receivers.size() > 0) {
10331 Iterator<ReceiverList> it = app.receivers.iterator();
10332 while (it.hasNext()) {
10333 removeReceiverLocked(it.next());
10334 }
10335 app.receivers.clear();
10336 }
10337
Christopher Tate181fafa2009-05-14 11:12:14 -070010338 // If the app is undergoing backup, tell the backup manager about it
10339 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010340 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010341 try {
10342 IBackupManager bm = IBackupManager.Stub.asInterface(
10343 ServiceManager.getService(Context.BACKUP_SERVICE));
10344 bm.agentDisconnected(app.info.packageName);
10345 } catch (RemoteException e) {
10346 // can't happen; backup manager is local
10347 }
10348 }
10349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010350 // If the caller is restarting this app, then leave it in its
10351 // current lists and let the caller take care of it.
10352 if (restarting) {
10353 return;
10354 }
10355
10356 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010357 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010358 "Removing non-persistent process during cleanup: " + app);
10359 mProcessNames.remove(app.processName, app.info.uid);
10360 } else if (!app.removed) {
10361 // This app is persistent, so we need to keep its record around.
10362 // If it is not already on the pending app list, add it there
10363 // and start a new process for it.
10364 app.thread = null;
10365 app.forcingToForeground = null;
10366 app.foregroundServices = false;
10367 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10368 mPersistentStartingProcesses.add(app);
10369 restart = true;
10370 }
10371 }
10372 mProcessesOnHold.remove(app);
10373
The Android Open Source Project4df24232009-03-05 14:34:35 -080010374 if (app == mHomeProcess) {
10375 mHomeProcess = null;
10376 }
10377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378 if (restart) {
10379 // We have components that still need to be running in the
10380 // process, so re-launch it.
10381 mProcessNames.put(app.processName, app.info.uid, app);
10382 startProcessLocked(app, "restart", app.processName);
10383 } else if (app.pid > 0 && app.pid != MY_PID) {
10384 // Goodbye!
10385 synchronized (mPidsSelfLocked) {
10386 mPidsSelfLocked.remove(app.pid);
10387 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10388 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010389 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010390 }
10391 }
10392
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010393 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10394 // Look through the content providers we are waiting to have launched,
10395 // and if any run in this process then either schedule a restart of
10396 // the process or kill the client waiting for it if this process has
10397 // gone bad.
10398 int NL = mLaunchingProviders.size();
10399 boolean restart = false;
10400 for (int i=0; i<NL; i++) {
10401 ContentProviderRecord cpr = (ContentProviderRecord)
10402 mLaunchingProviders.get(i);
10403 if (cpr.launchingApp == app) {
10404 if (!alwaysBad && !app.bad) {
10405 restart = true;
10406 } else {
10407 removeDyingProviderLocked(app, cpr);
10408 NL = mLaunchingProviders.size();
10409 }
10410 }
10411 }
10412 return restart;
10413 }
10414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010415 // =========================================================
10416 // SERVICES
10417 // =========================================================
10418
10419 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10420 ActivityManager.RunningServiceInfo info =
10421 new ActivityManager.RunningServiceInfo();
10422 info.service = r.name;
10423 if (r.app != null) {
10424 info.pid = r.app.pid;
10425 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010426 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 info.process = r.processName;
10428 info.foreground = r.isForeground;
10429 info.activeSince = r.createTime;
10430 info.started = r.startRequested;
10431 info.clientCount = r.connections.size();
10432 info.crashCount = r.crashCount;
10433 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010434 if (r.isForeground) {
10435 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10436 }
10437 if (r.startRequested) {
10438 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10439 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010440 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010441 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10442 }
10443 if (r.app != null && r.app.persistent) {
10444 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10445 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010446 for (ConnectionRecord conn : r.connections.values()) {
10447 if (conn.clientLabel != 0) {
10448 info.clientPackage = conn.binding.client.info.packageName;
10449 info.clientLabel = conn.clientLabel;
10450 break;
10451 }
10452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010453 return info;
10454 }
10455
10456 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10457 int flags) {
10458 synchronized (this) {
10459 ArrayList<ActivityManager.RunningServiceInfo> res
10460 = new ArrayList<ActivityManager.RunningServiceInfo>();
10461
10462 if (mServices.size() > 0) {
10463 Iterator<ServiceRecord> it = mServices.values().iterator();
10464 while (it.hasNext() && res.size() < maxNum) {
10465 res.add(makeRunningServiceInfoLocked(it.next()));
10466 }
10467 }
10468
10469 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10470 ServiceRecord r = mRestartingServices.get(i);
10471 ActivityManager.RunningServiceInfo info =
10472 makeRunningServiceInfoLocked(r);
10473 info.restarting = r.nextRestartTime;
10474 res.add(info);
10475 }
10476
10477 return res;
10478 }
10479 }
10480
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010481 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10482 synchronized (this) {
10483 ServiceRecord r = mServices.get(name);
10484 if (r != null) {
10485 for (ConnectionRecord conn : r.connections.values()) {
10486 if (conn.clientIntent != null) {
10487 return conn.clientIntent;
10488 }
10489 }
10490 }
10491 }
10492 return null;
10493 }
10494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010495 private final ServiceRecord findServiceLocked(ComponentName name,
10496 IBinder token) {
10497 ServiceRecord r = mServices.get(name);
10498 return r == token ? r : null;
10499 }
10500
10501 private final class ServiceLookupResult {
10502 final ServiceRecord record;
10503 final String permission;
10504
10505 ServiceLookupResult(ServiceRecord _record, String _permission) {
10506 record = _record;
10507 permission = _permission;
10508 }
10509 };
10510
10511 private ServiceLookupResult findServiceLocked(Intent service,
10512 String resolvedType) {
10513 ServiceRecord r = null;
10514 if (service.getComponent() != null) {
10515 r = mServices.get(service.getComponent());
10516 }
10517 if (r == null) {
10518 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10519 r = mServicesByIntent.get(filter);
10520 }
10521
10522 if (r == null) {
10523 try {
10524 ResolveInfo rInfo =
10525 ActivityThread.getPackageManager().resolveService(
10526 service, resolvedType, 0);
10527 ServiceInfo sInfo =
10528 rInfo != null ? rInfo.serviceInfo : null;
10529 if (sInfo == null) {
10530 return null;
10531 }
10532
10533 ComponentName name = new ComponentName(
10534 sInfo.applicationInfo.packageName, sInfo.name);
10535 r = mServices.get(name);
10536 } catch (RemoteException ex) {
10537 // pm is in same process, this will never happen.
10538 }
10539 }
10540 if (r != null) {
10541 int callingPid = Binder.getCallingPid();
10542 int callingUid = Binder.getCallingUid();
10543 if (checkComponentPermission(r.permission,
10544 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10545 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010546 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010547 + " from pid=" + callingPid
10548 + ", uid=" + callingUid
10549 + " requires " + r.permission);
10550 return new ServiceLookupResult(null, r.permission);
10551 }
10552 return new ServiceLookupResult(r, null);
10553 }
10554 return null;
10555 }
10556
10557 private class ServiceRestarter implements Runnable {
10558 private ServiceRecord mService;
10559
10560 void setService(ServiceRecord service) {
10561 mService = service;
10562 }
10563
10564 public void run() {
10565 synchronized(ActivityManagerService.this) {
10566 performServiceRestartLocked(mService);
10567 }
10568 }
10569 }
10570
10571 private ServiceLookupResult retrieveServiceLocked(Intent service,
10572 String resolvedType, int callingPid, int callingUid) {
10573 ServiceRecord r = null;
10574 if (service.getComponent() != null) {
10575 r = mServices.get(service.getComponent());
10576 }
10577 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10578 r = mServicesByIntent.get(filter);
10579 if (r == null) {
10580 try {
10581 ResolveInfo rInfo =
10582 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010583 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010584 ServiceInfo sInfo =
10585 rInfo != null ? rInfo.serviceInfo : null;
10586 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010587 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010588 ": not found");
10589 return null;
10590 }
10591
10592 ComponentName name = new ComponentName(
10593 sInfo.applicationInfo.packageName, sInfo.name);
10594 r = mServices.get(name);
10595 if (r == null) {
10596 filter = new Intent.FilterComparison(service.cloneFilter());
10597 ServiceRestarter res = new ServiceRestarter();
10598 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10599 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10600 synchronized (stats) {
10601 ss = stats.getServiceStatsLocked(
10602 sInfo.applicationInfo.uid, sInfo.packageName,
10603 sInfo.name);
10604 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010605 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010606 res.setService(r);
10607 mServices.put(name, r);
10608 mServicesByIntent.put(filter, r);
10609
10610 // Make sure this component isn't in the pending list.
10611 int N = mPendingServices.size();
10612 for (int i=0; i<N; i++) {
10613 ServiceRecord pr = mPendingServices.get(i);
10614 if (pr.name.equals(name)) {
10615 mPendingServices.remove(i);
10616 i--;
10617 N--;
10618 }
10619 }
10620 }
10621 } catch (RemoteException ex) {
10622 // pm is in same process, this will never happen.
10623 }
10624 }
10625 if (r != null) {
10626 if (checkComponentPermission(r.permission,
10627 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10628 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010629 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010630 + " from pid=" + Binder.getCallingPid()
10631 + ", uid=" + Binder.getCallingUid()
10632 + " requires " + r.permission);
10633 return new ServiceLookupResult(null, r.permission);
10634 }
10635 return new ServiceLookupResult(r, null);
10636 }
10637 return null;
10638 }
10639
10640 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10641 long now = SystemClock.uptimeMillis();
10642 if (r.executeNesting == 0 && r.app != null) {
10643 if (r.app.executingServices.size() == 0) {
10644 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10645 msg.obj = r.app;
10646 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10647 }
10648 r.app.executingServices.add(r);
10649 }
10650 r.executeNesting++;
10651 r.executingStart = now;
10652 }
10653
10654 private final void sendServiceArgsLocked(ServiceRecord r,
10655 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010656 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010657 if (N == 0) {
10658 return;
10659 }
10660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010661 int i = 0;
10662 while (i < N) {
10663 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010664 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010665 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010666 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010667 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010668 // If somehow we got a dummy start at the front, then
10669 // just drop it here.
10670 i++;
10671 continue;
10672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010673 bumpServiceExecutingLocked(r);
10674 if (!oomAdjusted) {
10675 oomAdjusted = true;
10676 updateOomAdjLocked(r.app);
10677 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010678 int flags = 0;
10679 if (si.deliveryCount > 0) {
10680 flags |= Service.START_FLAG_RETRY;
10681 }
10682 if (si.doneExecutingCount > 0) {
10683 flags |= Service.START_FLAG_REDELIVERY;
10684 }
10685 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10686 si.deliveredTime = SystemClock.uptimeMillis();
10687 r.deliveredStarts.add(si);
10688 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010689 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010690 } catch (RemoteException e) {
10691 // Remote process gone... we'll let the normal cleanup take
10692 // care of this.
10693 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010694 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010695 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010696 break;
10697 }
10698 }
10699 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010700 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010701 } else {
10702 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010703 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010704 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010705 }
10706 }
10707 }
10708
10709 private final boolean requestServiceBindingLocked(ServiceRecord r,
10710 IntentBindRecord i, boolean rebind) {
10711 if (r.app == null || r.app.thread == null) {
10712 // If service is not currently running, can't yet bind.
10713 return false;
10714 }
10715 if ((!i.requested || rebind) && i.apps.size() > 0) {
10716 try {
10717 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010718 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010719 + ": shouldUnbind=" + i.hasBound);
10720 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10721 if (!rebind) {
10722 i.requested = true;
10723 }
10724 i.hasBound = true;
10725 i.doRebind = false;
10726 } catch (RemoteException e) {
10727 return false;
10728 }
10729 }
10730 return true;
10731 }
10732
10733 private final void requestServiceBindingsLocked(ServiceRecord r) {
10734 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10735 while (bindings.hasNext()) {
10736 IntentBindRecord i = bindings.next();
10737 if (!requestServiceBindingLocked(r, i, false)) {
10738 break;
10739 }
10740 }
10741 }
10742
10743 private final void realStartServiceLocked(ServiceRecord r,
10744 ProcessRecord app) throws RemoteException {
10745 if (app.thread == null) {
10746 throw new RemoteException();
10747 }
10748
10749 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010750 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010751
10752 app.services.add(r);
10753 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010754 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755
10756 boolean created = false;
10757 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010758 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010759 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010760 mStringBuilder.setLength(0);
10761 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010762 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010763 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010764 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 synchronized (r.stats.getBatteryStats()) {
10766 r.stats.startLaunchedLocked();
10767 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010768 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010770 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010771 created = true;
10772 } finally {
10773 if (!created) {
10774 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010775 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010776 }
10777 }
10778
10779 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010780
10781 // If the service is in the started state, and there are no
10782 // pending arguments, then fake up one so its onStartCommand() will
10783 // be called.
10784 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
10785 r.lastStartId++;
10786 if (r.lastStartId < 1) {
10787 r.lastStartId = 1;
10788 }
10789 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
10790 }
10791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010792 sendServiceArgsLocked(r, true);
10793 }
10794
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010795 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10796 boolean allowCancel) {
10797 boolean canceled = false;
10798
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010799 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010800 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010801 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010802
10803 // Any delivered but not yet finished starts should be put back
10804 // on the pending list.
10805 final int N = r.deliveredStarts.size();
10806 if (N > 0) {
10807 for (int i=N-1; i>=0; i--) {
10808 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
10809 if (si.intent == null) {
10810 // We'll generate this again if needed.
10811 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10812 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10813 r.pendingStarts.add(0, si);
10814 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10815 dur *= 2;
10816 if (minDuration < dur) minDuration = dur;
10817 if (resetTime < dur) resetTime = dur;
10818 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010819 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010820 + r.name);
10821 canceled = true;
10822 }
10823 }
10824 r.deliveredStarts.clear();
10825 }
10826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 r.totalRestartCount++;
10828 if (r.restartDelay == 0) {
10829 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010830 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010831 } else {
10832 // If it has been a "reasonably long time" since the service
10833 // was started, then reset our restart duration back to
10834 // the beginning, so we don't infinitely increase the duration
10835 // on a service that just occasionally gets killed (which is
10836 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010837 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010838 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010839 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010840 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010841 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010842 if (r.restartDelay < minDuration) {
10843 r.restartDelay = minDuration;
10844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010845 }
10846 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010847
10848 r.nextRestartTime = now + r.restartDelay;
10849
10850 // Make sure that we don't end up restarting a bunch of services
10851 // all at the same time.
10852 boolean repeat;
10853 do {
10854 repeat = false;
10855 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10856 ServiceRecord r2 = mRestartingServices.get(i);
10857 if (r2 != r && r.nextRestartTime
10858 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10859 && r.nextRestartTime
10860 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10861 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10862 r.restartDelay = r.nextRestartTime - now;
10863 repeat = true;
10864 break;
10865 }
10866 }
10867 } while (repeat);
10868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010869 if (!mRestartingServices.contains(r)) {
10870 mRestartingServices.add(r);
10871 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010872
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010873 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010875 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010876 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010877 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010878 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010879 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010880 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010881 r.shortName, r.restartDelay);
10882
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010883 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010884 }
10885
10886 final void performServiceRestartLocked(ServiceRecord r) {
10887 if (!mRestartingServices.contains(r)) {
10888 return;
10889 }
10890 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10891 }
10892
10893 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10894 if (r.restartDelay == 0) {
10895 return false;
10896 }
10897 r.resetRestartCounter();
10898 mRestartingServices.remove(r);
10899 mHandler.removeCallbacks(r.restarter);
10900 return true;
10901 }
10902
10903 private final boolean bringUpServiceLocked(ServiceRecord r,
10904 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010905 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 //r.dump(" ");
10907
Dianne Hackborn36124872009-10-08 16:22:03 -070010908 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010909 sendServiceArgsLocked(r, false);
10910 return true;
10911 }
10912
10913 if (!whileRestarting && r.restartDelay > 0) {
10914 // If waiting for a restart, then do nothing.
10915 return true;
10916 }
10917
Joe Onorato8a9b2202010-02-26 18:56:32 -080010918 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010919 + " " + r.intent);
10920
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010921 // We are now bringing the service up, so no longer in the
10922 // restarting state.
10923 mRestartingServices.remove(r);
10924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010925 final String appName = r.processName;
10926 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10927 if (app != null && app.thread != null) {
10928 try {
10929 realStartServiceLocked(r, app);
10930 return true;
10931 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010932 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010933 }
10934
10935 // If a dead object exception was thrown -- fall through to
10936 // restart the application.
10937 }
10938
Dianne Hackborn36124872009-10-08 16:22:03 -070010939 // Not running -- get it started, and enqueue this service record
10940 // to be executed when the app comes up.
10941 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10942 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010943 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070010944 + r.appInfo.packageName + "/"
10945 + r.appInfo.uid + " for service "
10946 + r.intent.getIntent() + ": process is bad");
10947 bringDownServiceLocked(r, true);
10948 return false;
10949 }
10950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010952 mPendingServices.add(r);
10953 }
Dianne Hackborn36124872009-10-08 16:22:03 -070010954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010955 return true;
10956 }
10957
10958 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010959 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 //r.dump(" ");
10961
10962 // Does it still need to run?
10963 if (!force && r.startRequested) {
10964 return;
10965 }
10966 if (r.connections.size() > 0) {
10967 if (!force) {
10968 // XXX should probably keep a count of the number of auto-create
10969 // connections directly in the service.
10970 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10971 while (it.hasNext()) {
10972 ConnectionRecord cr = it.next();
10973 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10974 return;
10975 }
10976 }
10977 }
10978
10979 // Report to all of the connections that the service is no longer
10980 // available.
10981 Iterator<ConnectionRecord> it = r.connections.values().iterator();
10982 while (it.hasNext()) {
10983 ConnectionRecord c = it.next();
10984 try {
10985 // todo: shouldn't be a synchronous call!
10986 c.conn.connected(r.name, null);
10987 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010988 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 " to connection " + c.conn.asBinder() +
10990 " (in " + c.binding.client.processName + ")", e);
10991 }
10992 }
10993 }
10994
10995 // Tell the service that it has been unbound.
10996 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10997 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10998 while (it.hasNext()) {
10999 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011000 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 + ": hasBound=" + ibr.hasBound);
11002 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11003 try {
11004 bumpServiceExecutingLocked(r);
11005 updateOomAdjLocked(r.app);
11006 ibr.hasBound = false;
11007 r.app.thread.scheduleUnbindService(r,
11008 ibr.intent.getIntent());
11009 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011010 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 + r.shortName, e);
11012 serviceDoneExecutingLocked(r, true);
11013 }
11014 }
11015 }
11016 }
11017
Joe Onorato8a9b2202010-02-26 18:56:32 -080011018 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011019 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011020 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 System.identityHashCode(r), r.shortName,
11022 (r.app != null) ? r.app.pid : -1);
11023
11024 mServices.remove(r.name);
11025 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011026 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 r.totalRestartCount = 0;
11028 unscheduleServiceRestartLocked(r);
11029
11030 // Also make sure it is not on the pending list.
11031 int N = mPendingServices.size();
11032 for (int i=0; i<N; i++) {
11033 if (mPendingServices.get(i) == r) {
11034 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011035 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 TAG, "Removed pending service: " + r.shortName);
11037 i--;
11038 N--;
11039 }
11040 }
11041
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011042 r.cancelNotification();
11043 r.isForeground = false;
11044 r.foregroundId = 0;
11045 r.foregroundNoti = null;
11046
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011047 // Clear start entries.
11048 r.deliveredStarts.clear();
11049 r.pendingStarts.clear();
11050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011051 if (r.app != null) {
11052 synchronized (r.stats.getBatteryStats()) {
11053 r.stats.stopLaunchedLocked();
11054 }
11055 r.app.services.remove(r);
11056 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011058 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011059 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011060 bumpServiceExecutingLocked(r);
11061 mStoppingServices.add(r);
11062 updateOomAdjLocked(r.app);
11063 r.app.thread.scheduleStopService(r);
11064 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011065 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011066 + r.shortName, e);
11067 serviceDoneExecutingLocked(r, true);
11068 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011069 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011071 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072 TAG, "Removed service that has no process: " + r.shortName);
11073 }
11074 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011075 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011076 TAG, "Removed service that is not running: " + r.shortName);
11077 }
11078 }
11079
11080 ComponentName startServiceLocked(IApplicationThread caller,
11081 Intent service, String resolvedType,
11082 int callingPid, int callingUid) {
11083 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011084 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011085 + " type=" + resolvedType + " args=" + service.getExtras());
11086
11087 if (caller != null) {
11088 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11089 if (callerApp == null) {
11090 throw new SecurityException(
11091 "Unable to find app for caller " + caller
11092 + " (pid=" + Binder.getCallingPid()
11093 + ") when starting service " + service);
11094 }
11095 }
11096
11097 ServiceLookupResult res =
11098 retrieveServiceLocked(service, resolvedType,
11099 callingPid, callingUid);
11100 if (res == null) {
11101 return null;
11102 }
11103 if (res.record == null) {
11104 return new ComponentName("!", res.permission != null
11105 ? res.permission : "private to package");
11106 }
11107 ServiceRecord r = res.record;
11108 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011109 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 + r.shortName);
11111 }
11112 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011113 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 r.lastStartId++;
11115 if (r.lastStartId < 1) {
11116 r.lastStartId = 1;
11117 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011118 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011119 r.lastActivity = SystemClock.uptimeMillis();
11120 synchronized (r.stats.getBatteryStats()) {
11121 r.stats.startRunningLocked();
11122 }
11123 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11124 return new ComponentName("!", "Service process is bad");
11125 }
11126 return r.name;
11127 }
11128 }
11129
11130 public ComponentName startService(IApplicationThread caller, Intent service,
11131 String resolvedType) {
11132 // Refuse possible leaked file descriptors
11133 if (service != null && service.hasFileDescriptors() == true) {
11134 throw new IllegalArgumentException("File descriptors passed in Intent");
11135 }
11136
11137 synchronized(this) {
11138 final int callingPid = Binder.getCallingPid();
11139 final int callingUid = Binder.getCallingUid();
11140 final long origId = Binder.clearCallingIdentity();
11141 ComponentName res = startServiceLocked(caller, service,
11142 resolvedType, callingPid, callingUid);
11143 Binder.restoreCallingIdentity(origId);
11144 return res;
11145 }
11146 }
11147
11148 ComponentName startServiceInPackage(int uid,
11149 Intent service, String resolvedType) {
11150 synchronized(this) {
11151 final long origId = Binder.clearCallingIdentity();
11152 ComponentName res = startServiceLocked(null, service,
11153 resolvedType, -1, uid);
11154 Binder.restoreCallingIdentity(origId);
11155 return res;
11156 }
11157 }
11158
11159 public int stopService(IApplicationThread caller, Intent service,
11160 String resolvedType) {
11161 // Refuse possible leaked file descriptors
11162 if (service != null && service.hasFileDescriptors() == true) {
11163 throw new IllegalArgumentException("File descriptors passed in Intent");
11164 }
11165
11166 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011167 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011168 + " type=" + resolvedType);
11169
11170 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11171 if (caller != null && callerApp == null) {
11172 throw new SecurityException(
11173 "Unable to find app for caller " + caller
11174 + " (pid=" + Binder.getCallingPid()
11175 + ") when stopping service " + service);
11176 }
11177
11178 // If this service is active, make sure it is stopped.
11179 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11180 if (r != null) {
11181 if (r.record != null) {
11182 synchronized (r.record.stats.getBatteryStats()) {
11183 r.record.stats.stopRunningLocked();
11184 }
11185 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011186 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011187 final long origId = Binder.clearCallingIdentity();
11188 bringDownServiceLocked(r.record, false);
11189 Binder.restoreCallingIdentity(origId);
11190 return 1;
11191 }
11192 return -1;
11193 }
11194 }
11195
11196 return 0;
11197 }
11198
11199 public IBinder peekService(Intent service, String resolvedType) {
11200 // Refuse possible leaked file descriptors
11201 if (service != null && service.hasFileDescriptors() == true) {
11202 throw new IllegalArgumentException("File descriptors passed in Intent");
11203 }
11204
11205 IBinder ret = null;
11206
11207 synchronized(this) {
11208 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11209
11210 if (r != null) {
11211 // r.record is null if findServiceLocked() failed the caller permission check
11212 if (r.record == null) {
11213 throw new SecurityException(
11214 "Permission Denial: Accessing service " + r.record.name
11215 + " from pid=" + Binder.getCallingPid()
11216 + ", uid=" + Binder.getCallingUid()
11217 + " requires " + r.permission);
11218 }
11219 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11220 if (ib != null) {
11221 ret = ib.binder;
11222 }
11223 }
11224 }
11225
11226 return ret;
11227 }
11228
11229 public boolean stopServiceToken(ComponentName className, IBinder token,
11230 int startId) {
11231 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011232 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 + " " + token + " startId=" + startId);
11234 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011235 if (r != null) {
11236 if (startId >= 0) {
11237 // Asked to only stop if done with all work. Note that
11238 // to avoid leaks, we will take this as dropping all
11239 // start items up to and including this one.
11240 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11241 if (si != null) {
11242 while (r.deliveredStarts.size() > 0) {
11243 if (r.deliveredStarts.remove(0) == si) {
11244 break;
11245 }
11246 }
11247 }
11248
11249 if (r.lastStartId != startId) {
11250 return false;
11251 }
11252
11253 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011254 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011255 + " is last, but have " + r.deliveredStarts.size()
11256 + " remaining args");
11257 }
11258 }
11259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011260 synchronized (r.stats.getBatteryStats()) {
11261 r.stats.stopRunningLocked();
11262 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011263 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011264 }
11265 final long origId = Binder.clearCallingIdentity();
11266 bringDownServiceLocked(r, false);
11267 Binder.restoreCallingIdentity(origId);
11268 return true;
11269 }
11270 }
11271 return false;
11272 }
11273
11274 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011275 int id, Notification notification, boolean removeNotification) {
11276 final long origId = Binder.clearCallingIdentity();
11277 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 synchronized(this) {
11279 ServiceRecord r = findServiceLocked(className, token);
11280 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011281 if (id != 0) {
11282 if (notification == null) {
11283 throw new IllegalArgumentException("null notification");
11284 }
11285 if (r.foregroundId != id) {
11286 r.cancelNotification();
11287 r.foregroundId = id;
11288 }
11289 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11290 r.foregroundNoti = notification;
11291 r.isForeground = true;
11292 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011293 if (r.app != null) {
11294 updateServiceForegroundLocked(r.app, true);
11295 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011296 } else {
11297 if (r.isForeground) {
11298 r.isForeground = false;
11299 if (r.app != null) {
11300 updateServiceForegroundLocked(r.app, true);
11301 }
11302 }
11303 if (removeNotification) {
11304 r.cancelNotification();
11305 r.foregroundId = 0;
11306 r.foregroundNoti = null;
11307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011308 }
11309 }
11310 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011311 } finally {
11312 Binder.restoreCallingIdentity(origId);
11313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011314 }
11315
11316 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11317 boolean anyForeground = false;
11318 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11319 if (sr.isForeground) {
11320 anyForeground = true;
11321 break;
11322 }
11323 }
11324 if (anyForeground != proc.foregroundServices) {
11325 proc.foregroundServices = anyForeground;
11326 if (oomAdj) {
11327 updateOomAdjLocked();
11328 }
11329 }
11330 }
11331
11332 public int bindService(IApplicationThread caller, IBinder token,
11333 Intent service, String resolvedType,
11334 IServiceConnection connection, int flags) {
11335 // Refuse possible leaked file descriptors
11336 if (service != null && service.hasFileDescriptors() == true) {
11337 throw new IllegalArgumentException("File descriptors passed in Intent");
11338 }
11339
11340 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011341 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011342 + " type=" + resolvedType + " conn=" + connection.asBinder()
11343 + " flags=0x" + Integer.toHexString(flags));
11344 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11345 if (callerApp == null) {
11346 throw new SecurityException(
11347 "Unable to find app for caller " + caller
11348 + " (pid=" + Binder.getCallingPid()
11349 + ") when binding service " + service);
11350 }
11351
11352 HistoryRecord activity = null;
11353 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011354 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011355 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011356 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 return 0;
11358 }
11359 activity = (HistoryRecord)mHistory.get(aindex);
11360 }
11361
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011362 int clientLabel = 0;
11363 PendingIntent clientIntent = null;
11364
11365 if (callerApp.info.uid == Process.SYSTEM_UID) {
11366 // Hacky kind of thing -- allow system stuff to tell us
11367 // what they are, so we can report this elsewhere for
11368 // others to know why certain services are running.
11369 try {
11370 clientIntent = (PendingIntent)service.getParcelableExtra(
11371 Intent.EXTRA_CLIENT_INTENT);
11372 } catch (RuntimeException e) {
11373 }
11374 if (clientIntent != null) {
11375 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11376 if (clientLabel != 0) {
11377 // There are no useful extras in the intent, trash them.
11378 // System code calling with this stuff just needs to know
11379 // this will happen.
11380 service = service.cloneFilter();
11381 }
11382 }
11383 }
11384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011385 ServiceLookupResult res =
11386 retrieveServiceLocked(service, resolvedType,
11387 Binder.getCallingPid(), Binder.getCallingUid());
11388 if (res == null) {
11389 return 0;
11390 }
11391 if (res.record == null) {
11392 return -1;
11393 }
11394 ServiceRecord s = res.record;
11395
11396 final long origId = Binder.clearCallingIdentity();
11397
11398 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011399 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011400 + s.shortName);
11401 }
11402
11403 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11404 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011405 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011406
11407 IBinder binder = connection.asBinder();
11408 s.connections.put(binder, c);
11409 b.connections.add(c);
11410 if (activity != null) {
11411 if (activity.connections == null) {
11412 activity.connections = new HashSet<ConnectionRecord>();
11413 }
11414 activity.connections.add(c);
11415 }
11416 b.client.connections.add(c);
11417 mServiceConnections.put(binder, c);
11418
11419 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11420 s.lastActivity = SystemClock.uptimeMillis();
11421 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11422 return 0;
11423 }
11424 }
11425
11426 if (s.app != null) {
11427 // This could have made the service more important.
11428 updateOomAdjLocked(s.app);
11429 }
11430
Joe Onorato8a9b2202010-02-26 18:56:32 -080011431 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 + ": received=" + b.intent.received
11433 + " apps=" + b.intent.apps.size()
11434 + " doRebind=" + b.intent.doRebind);
11435
11436 if (s.app != null && b.intent.received) {
11437 // Service is already running, so we can immediately
11438 // publish the connection.
11439 try {
11440 c.conn.connected(s.name, b.intent.binder);
11441 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011442 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011443 + " to connection " + c.conn.asBinder()
11444 + " (in " + c.binding.client.processName + ")", e);
11445 }
11446
11447 // If this is the first app connected back to this binding,
11448 // and the service had previously asked to be told when
11449 // rebound, then do so.
11450 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11451 requestServiceBindingLocked(s, b.intent, true);
11452 }
11453 } else if (!b.intent.requested) {
11454 requestServiceBindingLocked(s, b.intent, false);
11455 }
11456
11457 Binder.restoreCallingIdentity(origId);
11458 }
11459
11460 return 1;
11461 }
11462
11463 private void removeConnectionLocked(
11464 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11465 IBinder binder = c.conn.asBinder();
11466 AppBindRecord b = c.binding;
11467 ServiceRecord s = b.service;
11468 s.connections.remove(binder);
11469 b.connections.remove(c);
11470 if (c.activity != null && c.activity != skipAct) {
11471 if (c.activity.connections != null) {
11472 c.activity.connections.remove(c);
11473 }
11474 }
11475 if (b.client != skipApp) {
11476 b.client.connections.remove(c);
11477 }
11478 mServiceConnections.remove(binder);
11479
11480 if (b.connections.size() == 0) {
11481 b.intent.apps.remove(b.client);
11482 }
11483
Joe Onorato8a9b2202010-02-26 18:56:32 -080011484 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 + ": shouldUnbind=" + b.intent.hasBound);
11486 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11487 && b.intent.hasBound) {
11488 try {
11489 bumpServiceExecutingLocked(s);
11490 updateOomAdjLocked(s.app);
11491 b.intent.hasBound = false;
11492 // Assume the client doesn't want to know about a rebind;
11493 // we will deal with that later if it asks for one.
11494 b.intent.doRebind = false;
11495 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11496 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011497 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011498 serviceDoneExecutingLocked(s, true);
11499 }
11500 }
11501
11502 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11503 bringDownServiceLocked(s, false);
11504 }
11505 }
11506
11507 public boolean unbindService(IServiceConnection connection) {
11508 synchronized (this) {
11509 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011510 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 ConnectionRecord r = mServiceConnections.get(binder);
11512 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011513 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011514 + connection.asBinder());
11515 return false;
11516 }
11517
11518 final long origId = Binder.clearCallingIdentity();
11519
11520 removeConnectionLocked(r, null, null);
11521
11522 if (r.binding.service.app != null) {
11523 // This could have made the service less important.
11524 updateOomAdjLocked(r.binding.service.app);
11525 }
11526
11527 Binder.restoreCallingIdentity(origId);
11528 }
11529
11530 return true;
11531 }
11532
11533 public void publishService(IBinder token, Intent intent, IBinder service) {
11534 // Refuse possible leaked file descriptors
11535 if (intent != null && intent.hasFileDescriptors() == true) {
11536 throw new IllegalArgumentException("File descriptors passed in Intent");
11537 }
11538
11539 synchronized(this) {
11540 if (!(token instanceof ServiceRecord)) {
11541 throw new IllegalArgumentException("Invalid service token");
11542 }
11543 ServiceRecord r = (ServiceRecord)token;
11544
11545 final long origId = Binder.clearCallingIdentity();
11546
Joe Onorato8a9b2202010-02-26 18:56:32 -080011547 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011548 + " " + intent + ": " + service);
11549 if (r != null) {
11550 Intent.FilterComparison filter
11551 = new Intent.FilterComparison(intent);
11552 IntentBindRecord b = r.bindings.get(filter);
11553 if (b != null && !b.received) {
11554 b.binder = service;
11555 b.requested = true;
11556 b.received = true;
11557 if (r.connections.size() > 0) {
11558 Iterator<ConnectionRecord> it
11559 = r.connections.values().iterator();
11560 while (it.hasNext()) {
11561 ConnectionRecord c = it.next();
11562 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011563 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011564 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011565 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011567 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011568 TAG, "Published intent: " + intent);
11569 continue;
11570 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011571 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572 try {
11573 c.conn.connected(r.name, service);
11574 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011575 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576 " to connection " + c.conn.asBinder() +
11577 " (in " + c.binding.client.processName + ")", e);
11578 }
11579 }
11580 }
11581 }
11582
11583 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11584
11585 Binder.restoreCallingIdentity(origId);
11586 }
11587 }
11588 }
11589
11590 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11591 // Refuse possible leaked file descriptors
11592 if (intent != null && intent.hasFileDescriptors() == true) {
11593 throw new IllegalArgumentException("File descriptors passed in Intent");
11594 }
11595
11596 synchronized(this) {
11597 if (!(token instanceof ServiceRecord)) {
11598 throw new IllegalArgumentException("Invalid service token");
11599 }
11600 ServiceRecord r = (ServiceRecord)token;
11601
11602 final long origId = Binder.clearCallingIdentity();
11603
11604 if (r != null) {
11605 Intent.FilterComparison filter
11606 = new Intent.FilterComparison(intent);
11607 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011608 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011609 + " at " + b + ": apps="
11610 + (b != null ? b.apps.size() : 0));
11611 if (b != null) {
11612 if (b.apps.size() > 0) {
11613 // Applications have already bound since the last
11614 // unbind, so just rebind right here.
11615 requestServiceBindingLocked(r, b, true);
11616 } else {
11617 // Note to tell the service the next time there is
11618 // a new client.
11619 b.doRebind = true;
11620 }
11621 }
11622
11623 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11624
11625 Binder.restoreCallingIdentity(origId);
11626 }
11627 }
11628 }
11629
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011630 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011631 synchronized(this) {
11632 if (!(token instanceof ServiceRecord)) {
11633 throw new IllegalArgumentException("Invalid service token");
11634 }
11635 ServiceRecord r = (ServiceRecord)token;
11636 boolean inStopping = mStoppingServices.contains(token);
11637 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011638 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011639 + ": nesting=" + r.executeNesting
11640 + ", inStopping=" + inStopping);
11641 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011642 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 + " with incorrect token: given " + token
11644 + ", expected " + r);
11645 return;
11646 }
11647
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011648 if (type == 1) {
11649 // This is a call from a service start... take care of
11650 // book-keeping.
11651 r.callStart = true;
11652 switch (res) {
11653 case Service.START_STICKY_COMPATIBILITY:
11654 case Service.START_STICKY: {
11655 // We are done with the associated start arguments.
11656 r.findDeliveredStart(startId, true);
11657 // Don't stop if killed.
11658 r.stopIfKilled = false;
11659 break;
11660 }
11661 case Service.START_NOT_STICKY: {
11662 // We are done with the associated start arguments.
11663 r.findDeliveredStart(startId, true);
11664 if (r.lastStartId == startId) {
11665 // There is no more work, and this service
11666 // doesn't want to hang around if killed.
11667 r.stopIfKilled = true;
11668 }
11669 break;
11670 }
11671 case Service.START_REDELIVER_INTENT: {
11672 // We'll keep this item until they explicitly
11673 // call stop for it, but keep track of the fact
11674 // that it was delivered.
11675 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11676 if (si != null) {
11677 si.deliveryCount = 0;
11678 si.doneExecutingCount++;
11679 // Don't stop if killed.
11680 r.stopIfKilled = true;
11681 }
11682 break;
11683 }
11684 default:
11685 throw new IllegalArgumentException(
11686 "Unknown service start result: " + res);
11687 }
11688 if (res == Service.START_STICKY_COMPATIBILITY) {
11689 r.callStart = false;
11690 }
11691 }
11692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011693 final long origId = Binder.clearCallingIdentity();
11694 serviceDoneExecutingLocked(r, inStopping);
11695 Binder.restoreCallingIdentity(origId);
11696 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011697 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011698 + " with token " + token);
11699 }
11700 }
11701 }
11702
11703 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11704 r.executeNesting--;
11705 if (r.executeNesting <= 0 && r.app != null) {
11706 r.app.executingServices.remove(r);
11707 if (r.app.executingServices.size() == 0) {
11708 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11709 }
11710 if (inStopping) {
11711 mStoppingServices.remove(r);
11712 }
11713 updateOomAdjLocked(r.app);
11714 }
11715 }
11716
11717 void serviceTimeout(ProcessRecord proc) {
11718 synchronized(this) {
11719 if (proc.executingServices.size() == 0 || proc.thread == null) {
11720 return;
11721 }
11722 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11723 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11724 ServiceRecord timeout = null;
11725 long nextTime = 0;
11726 while (it.hasNext()) {
11727 ServiceRecord sr = it.next();
11728 if (sr.executingStart < maxTime) {
11729 timeout = sr;
11730 break;
11731 }
11732 if (sr.executingStart > nextTime) {
11733 nextTime = sr.executingStart;
11734 }
11735 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011736 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011737 Slog.w(TAG, "Timeout executing service: " + timeout);
Dan Egnor42471dd2010-01-07 17:25:22 -080011738 appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011739 } else {
11740 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11741 msg.obj = proc;
11742 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11743 }
11744 }
11745 }
11746
11747 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011748 // BACKUP AND RESTORE
11749 // =========================================================
11750
11751 // Cause the target app to be launched if necessary and its backup agent
11752 // instantiated. The backup agent will invoke backupAgentCreated() on the
11753 // activity manager to announce its creation.
11754 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011755 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011756 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11757
11758 synchronized(this) {
11759 // !!! TODO: currently no check here that we're already bound
11760 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11761 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11762 synchronized (stats) {
11763 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11764 }
11765
11766 BackupRecord r = new BackupRecord(ss, app, backupMode);
11767 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
11768 // startProcessLocked() returns existing proc's record if it's already running
11769 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011770 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011771 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011772 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011773 return false;
11774 }
11775
11776 r.app = proc;
11777 mBackupTarget = r;
11778 mBackupAppName = app.packageName;
11779
Christopher Tate6fa95972009-06-05 18:43:55 -070011780 // Try not to kill the process during backup
11781 updateOomAdjLocked(proc);
11782
Christopher Tate181fafa2009-05-14 11:12:14 -070011783 // If the process is already attached, schedule the creation of the backup agent now.
11784 // If it is not yet live, this will be done when it attaches to the framework.
11785 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011786 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011787 try {
11788 proc.thread.scheduleCreateBackupAgent(app, backupMode);
11789 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011790 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011791 }
11792 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011793 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011794 }
11795 // Invariants: at this point, the target app process exists and the application
11796 // is either already running or in the process of coming up. mBackupTarget and
11797 // mBackupAppName describe the app, so that when it binds back to the AM we
11798 // know that it's scheduled for a backup-agent operation.
11799 }
11800
11801 return true;
11802 }
11803
11804 // A backup agent has just come up
11805 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011806 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011807 + " = " + agent);
11808
11809 synchronized(this) {
11810 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011811 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011812 return;
11813 }
11814
Christopher Tate043dadc2009-06-02 16:11:00 -070011815 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070011816 try {
11817 IBackupManager bm = IBackupManager.Stub.asInterface(
11818 ServiceManager.getService(Context.BACKUP_SERVICE));
11819 bm.agentConnected(agentPackageName, agent);
11820 } catch (RemoteException e) {
11821 // can't happen; the backup manager service is local
11822 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011823 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070011824 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070011825 } finally {
11826 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011827 }
11828 }
11829 }
11830
11831 // done with this agent
11832 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011833 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011834 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011835 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011836 return;
11837 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011838
11839 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011840 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011841 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011842 return;
11843 }
11844
Christopher Tate181fafa2009-05-14 11:12:14 -070011845 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011846 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011847 return;
11848 }
11849
Christopher Tate6fa95972009-06-05 18:43:55 -070011850 ProcessRecord proc = mBackupTarget.app;
11851 mBackupTarget = null;
11852 mBackupAppName = null;
11853
11854 // Not backing this app up any more; reset its OOM adjustment
11855 updateOomAdjLocked(proc);
11856
Christopher Tatec7b31e32009-06-10 15:49:30 -070011857 // If the app crashed during backup, 'thread' will be null here
11858 if (proc.thread != null) {
11859 try {
11860 proc.thread.scheduleDestroyBackupAgent(appInfo);
11861 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011862 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070011863 e.printStackTrace();
11864 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011865 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011866 }
11867 }
11868 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011869 // BROADCASTS
11870 // =========================================================
11871
11872 private final List getStickies(String action, IntentFilter filter,
11873 List cur) {
11874 final ContentResolver resolver = mContext.getContentResolver();
11875 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11876 if (list == null) {
11877 return cur;
11878 }
11879 int N = list.size();
11880 for (int i=0; i<N; i++) {
11881 Intent intent = list.get(i);
11882 if (filter.match(resolver, intent, true, TAG) >= 0) {
11883 if (cur == null) {
11884 cur = new ArrayList<Intent>();
11885 }
11886 cur.add(intent);
11887 }
11888 }
11889 return cur;
11890 }
11891
11892 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011893 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011894 + mBroadcastsScheduled);
11895
11896 if (mBroadcastsScheduled) {
11897 return;
11898 }
11899 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11900 mBroadcastsScheduled = true;
11901 }
11902
11903 public Intent registerReceiver(IApplicationThread caller,
11904 IIntentReceiver receiver, IntentFilter filter, String permission) {
11905 synchronized(this) {
11906 ProcessRecord callerApp = null;
11907 if (caller != null) {
11908 callerApp = getRecordForAppLocked(caller);
11909 if (callerApp == null) {
11910 throw new SecurityException(
11911 "Unable to find app for caller " + caller
11912 + " (pid=" + Binder.getCallingPid()
11913 + ") when registering receiver " + receiver);
11914 }
11915 }
11916
11917 List allSticky = null;
11918
11919 // Look for any matching sticky broadcasts...
11920 Iterator actions = filter.actionsIterator();
11921 if (actions != null) {
11922 while (actions.hasNext()) {
11923 String action = (String)actions.next();
11924 allSticky = getStickies(action, filter, allSticky);
11925 }
11926 } else {
11927 allSticky = getStickies(null, filter, allSticky);
11928 }
11929
11930 // The first sticky in the list is returned directly back to
11931 // the client.
11932 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11933
Joe Onorato8a9b2202010-02-26 18:56:32 -080011934 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011935 + ": " + sticky);
11936
11937 if (receiver == null) {
11938 return sticky;
11939 }
11940
11941 ReceiverList rl
11942 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11943 if (rl == null) {
11944 rl = new ReceiverList(this, callerApp,
11945 Binder.getCallingPid(),
11946 Binder.getCallingUid(), receiver);
11947 if (rl.app != null) {
11948 rl.app.receivers.add(rl);
11949 } else {
11950 try {
11951 receiver.asBinder().linkToDeath(rl, 0);
11952 } catch (RemoteException e) {
11953 return sticky;
11954 }
11955 rl.linkedToDeath = true;
11956 }
11957 mRegisteredReceivers.put(receiver.asBinder(), rl);
11958 }
11959 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
11960 rl.add(bf);
11961 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011962 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011963 }
11964 mReceiverResolver.addFilter(bf);
11965
11966 // Enqueue broadcasts for all existing stickies that match
11967 // this filter.
11968 if (allSticky != null) {
11969 ArrayList receivers = new ArrayList();
11970 receivers.add(bf);
11971
11972 int N = allSticky.size();
11973 for (int i=0; i<N; i++) {
11974 Intent intent = (Intent)allSticky.get(i);
11975 BroadcastRecord r = new BroadcastRecord(intent, null,
11976 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011977 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011978 if (mParallelBroadcasts.size() == 0) {
11979 scheduleBroadcastsLocked();
11980 }
11981 mParallelBroadcasts.add(r);
11982 }
11983 }
11984
11985 return sticky;
11986 }
11987 }
11988
11989 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011990 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011991
11992 boolean doNext = false;
11993
11994 synchronized(this) {
11995 ReceiverList rl
11996 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11997 if (rl != null) {
11998 if (rl.curBroadcast != null) {
11999 BroadcastRecord r = rl.curBroadcast;
12000 doNext = finishReceiverLocked(
12001 receiver.asBinder(), r.resultCode, r.resultData,
12002 r.resultExtras, r.resultAbort, true);
12003 }
12004
12005 if (rl.app != null) {
12006 rl.app.receivers.remove(rl);
12007 }
12008 removeReceiverLocked(rl);
12009 if (rl.linkedToDeath) {
12010 rl.linkedToDeath = false;
12011 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12012 }
12013 }
12014 }
12015
12016 if (!doNext) {
12017 return;
12018 }
12019
12020 final long origId = Binder.clearCallingIdentity();
12021 processNextBroadcast(false);
12022 trimApplications();
12023 Binder.restoreCallingIdentity(origId);
12024 }
12025
12026 void removeReceiverLocked(ReceiverList rl) {
12027 mRegisteredReceivers.remove(rl.receiver.asBinder());
12028 int N = rl.size();
12029 for (int i=0; i<N; i++) {
12030 mReceiverResolver.removeFilter(rl.get(i));
12031 }
12032 }
12033
12034 private final int broadcastIntentLocked(ProcessRecord callerApp,
12035 String callerPackage, Intent intent, String resolvedType,
12036 IIntentReceiver resultTo, int resultCode, String resultData,
12037 Bundle map, String requiredPermission,
12038 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12039 intent = new Intent(intent);
12040
Joe Onorato8a9b2202010-02-26 18:56:32 -080012041 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012042 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12043 + " ordered=" + ordered);
12044 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012045 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012046 }
12047
12048 // Handle special intents: if this broadcast is from the package
12049 // manager about a package being removed, we need to remove all of
12050 // its activities from the history stack.
12051 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12052 intent.getAction());
12053 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12054 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012055 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012056 || uidRemoved) {
12057 if (checkComponentPermission(
12058 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12059 callingPid, callingUid, -1)
12060 == PackageManager.PERMISSION_GRANTED) {
12061 if (uidRemoved) {
12062 final Bundle intentExtras = intent.getExtras();
12063 final int uid = intentExtras != null
12064 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12065 if (uid >= 0) {
12066 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12067 synchronized (bs) {
12068 bs.removeUidStatsLocked(uid);
12069 }
12070 }
12071 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012072 // If resources are unvailble just force stop all
12073 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012074 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012075 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12076 if (list != null && (list.length > 0)) {
12077 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012078 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012079 }
12080 }
12081 } else {
12082 Uri data = intent.getData();
12083 String ssp;
12084 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12085 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12086 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012087 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 }
12090 }
12091 }
12092 } else {
12093 String msg = "Permission Denial: " + intent.getAction()
12094 + " broadcast from " + callerPackage + " (pid=" + callingPid
12095 + ", uid=" + callingUid + ")"
12096 + " requires "
12097 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012098 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012099 throw new SecurityException(msg);
12100 }
12101 }
12102
12103 /*
12104 * If this is the time zone changed action, queue up a message that will reset the timezone
12105 * of all currently running processes. This message will get queued up before the broadcast
12106 * happens.
12107 */
12108 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12109 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12110 }
12111
Dianne Hackborn854060af2009-07-09 18:14:31 -070012112 /*
12113 * Prevent non-system code (defined here to be non-persistent
12114 * processes) from sending protected broadcasts.
12115 */
12116 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12117 || callingUid == Process.SHELL_UID || callingUid == 0) {
12118 // Always okay.
12119 } else if (callerApp == null || !callerApp.persistent) {
12120 try {
12121 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12122 intent.getAction())) {
12123 String msg = "Permission Denial: not allowed to send broadcast "
12124 + intent.getAction() + " from pid="
12125 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012126 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012127 throw new SecurityException(msg);
12128 }
12129 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012130 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012131 return BROADCAST_SUCCESS;
12132 }
12133 }
12134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012135 // Add to the sticky list if requested.
12136 if (sticky) {
12137 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12138 callingPid, callingUid)
12139 != PackageManager.PERMISSION_GRANTED) {
12140 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12141 + callingPid + ", uid=" + callingUid
12142 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012143 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012144 throw new SecurityException(msg);
12145 }
12146 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012147 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012148 + " and enforce permission " + requiredPermission);
12149 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12150 }
12151 if (intent.getComponent() != null) {
12152 throw new SecurityException(
12153 "Sticky broadcasts can't target a specific component");
12154 }
12155 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12156 if (list == null) {
12157 list = new ArrayList<Intent>();
12158 mStickyBroadcasts.put(intent.getAction(), list);
12159 }
12160 int N = list.size();
12161 int i;
12162 for (i=0; i<N; i++) {
12163 if (intent.filterEquals(list.get(i))) {
12164 // This sticky already exists, replace it.
12165 list.set(i, new Intent(intent));
12166 break;
12167 }
12168 }
12169 if (i >= N) {
12170 list.add(new Intent(intent));
12171 }
12172 }
12173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012174 // Figure out who all will receive this broadcast.
12175 List receivers = null;
12176 List<BroadcastFilter> registeredReceivers = null;
12177 try {
12178 if (intent.getComponent() != null) {
12179 // Broadcast is going to one specific receiver class...
12180 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012181 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012182 if (ai != null) {
12183 receivers = new ArrayList();
12184 ResolveInfo ri = new ResolveInfo();
12185 ri.activityInfo = ai;
12186 receivers.add(ri);
12187 }
12188 } else {
12189 // Need to resolve the intent to interested receivers...
12190 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12191 == 0) {
12192 receivers =
12193 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012194 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012195 }
Mihai Preda074edef2009-05-18 17:13:31 +020012196 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012197 }
12198 } catch (RemoteException ex) {
12199 // pm is in same process, this will never happen.
12200 }
12201
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012202 final boolean replacePending =
12203 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12204
Joe Onorato8a9b2202010-02-26 18:56:32 -080012205 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012206 + " replacePending=" + replacePending);
12207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012208 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12209 if (!ordered && NR > 0) {
12210 // If we are not serializing this broadcast, then send the
12211 // registered receivers separately so they don't wait for the
12212 // components to be launched.
12213 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12214 callerPackage, callingPid, callingUid, requiredPermission,
12215 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012216 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012217 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012218 TAG, "Enqueueing parallel broadcast " + r
12219 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012220 boolean replaced = false;
12221 if (replacePending) {
12222 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12223 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012224 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012225 "***** DROPPING PARALLEL: " + intent);
12226 mParallelBroadcasts.set(i, r);
12227 replaced = true;
12228 break;
12229 }
12230 }
12231 }
12232 if (!replaced) {
12233 mParallelBroadcasts.add(r);
12234 scheduleBroadcastsLocked();
12235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012236 registeredReceivers = null;
12237 NR = 0;
12238 }
12239
12240 // Merge into one list.
12241 int ir = 0;
12242 if (receivers != null) {
12243 // A special case for PACKAGE_ADDED: do not allow the package
12244 // being added to see this broadcast. This prevents them from
12245 // using this as a back door to get run as soon as they are
12246 // installed. Maybe in the future we want to have a special install
12247 // broadcast or such for apps, but we'd like to deliberately make
12248 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012249 String skipPackages[] = null;
12250 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12251 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12252 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12253 Uri data = intent.getData();
12254 if (data != null) {
12255 String pkgName = data.getSchemeSpecificPart();
12256 if (pkgName != null) {
12257 skipPackages = new String[] { pkgName };
12258 }
12259 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012260 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012261 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012262 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012263 if (skipPackages != null && (skipPackages.length > 0)) {
12264 for (String skipPackage : skipPackages) {
12265 if (skipPackage != null) {
12266 int NT = receivers.size();
12267 for (int it=0; it<NT; it++) {
12268 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12269 if (curt.activityInfo.packageName.equals(skipPackage)) {
12270 receivers.remove(it);
12271 it--;
12272 NT--;
12273 }
12274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012275 }
12276 }
12277 }
12278
12279 int NT = receivers != null ? receivers.size() : 0;
12280 int it = 0;
12281 ResolveInfo curt = null;
12282 BroadcastFilter curr = null;
12283 while (it < NT && ir < NR) {
12284 if (curt == null) {
12285 curt = (ResolveInfo)receivers.get(it);
12286 }
12287 if (curr == null) {
12288 curr = registeredReceivers.get(ir);
12289 }
12290 if (curr.getPriority() >= curt.priority) {
12291 // Insert this broadcast record into the final list.
12292 receivers.add(it, curr);
12293 ir++;
12294 curr = null;
12295 it++;
12296 NT++;
12297 } else {
12298 // Skip to the next ResolveInfo in the final list.
12299 it++;
12300 curt = null;
12301 }
12302 }
12303 }
12304 while (ir < NR) {
12305 if (receivers == null) {
12306 receivers = new ArrayList();
12307 }
12308 receivers.add(registeredReceivers.get(ir));
12309 ir++;
12310 }
12311
12312 if ((receivers != null && receivers.size() > 0)
12313 || resultTo != null) {
12314 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12315 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012316 receivers, resultTo, resultCode, resultData, map, ordered,
12317 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012318 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012319 TAG, "Enqueueing ordered broadcast " + r
12320 + ": prev had " + mOrderedBroadcasts.size());
12321 if (DEBUG_BROADCAST) {
12322 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012323 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012324 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012325 boolean replaced = false;
12326 if (replacePending) {
12327 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12328 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012329 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012330 "***** DROPPING ORDERED: " + intent);
12331 mOrderedBroadcasts.set(i, r);
12332 replaced = true;
12333 break;
12334 }
12335 }
12336 }
12337 if (!replaced) {
12338 mOrderedBroadcasts.add(r);
12339 scheduleBroadcastsLocked();
12340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012341 }
12342
12343 return BROADCAST_SUCCESS;
12344 }
12345
12346 public final int broadcastIntent(IApplicationThread caller,
12347 Intent intent, String resolvedType, IIntentReceiver resultTo,
12348 int resultCode, String resultData, Bundle map,
12349 String requiredPermission, boolean serialized, boolean sticky) {
12350 // Refuse possible leaked file descriptors
12351 if (intent != null && intent.hasFileDescriptors() == true) {
12352 throw new IllegalArgumentException("File descriptors passed in Intent");
12353 }
12354
12355 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012356 int flags = intent.getFlags();
12357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012358 if (!mSystemReady) {
12359 // if the caller really truly claims to know what they're doing, go
12360 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012361 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12362 intent = new Intent(intent);
12363 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12364 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012365 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012366 + " before boot completion");
12367 throw new IllegalStateException("Cannot broadcast before boot completed");
12368 }
12369 }
12370
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012371 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12372 throw new IllegalArgumentException(
12373 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12374 }
12375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012376 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12377 final int callingPid = Binder.getCallingPid();
12378 final int callingUid = Binder.getCallingUid();
12379 final long origId = Binder.clearCallingIdentity();
12380 int res = broadcastIntentLocked(callerApp,
12381 callerApp != null ? callerApp.info.packageName : null,
12382 intent, resolvedType, resultTo,
12383 resultCode, resultData, map, requiredPermission, serialized,
12384 sticky, callingPid, callingUid);
12385 Binder.restoreCallingIdentity(origId);
12386 return res;
12387 }
12388 }
12389
12390 int broadcastIntentInPackage(String packageName, int uid,
12391 Intent intent, String resolvedType, IIntentReceiver resultTo,
12392 int resultCode, String resultData, Bundle map,
12393 String requiredPermission, boolean serialized, boolean sticky) {
12394 synchronized(this) {
12395 final long origId = Binder.clearCallingIdentity();
12396 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12397 resultTo, resultCode, resultData, map, requiredPermission,
12398 serialized, sticky, -1, uid);
12399 Binder.restoreCallingIdentity(origId);
12400 return res;
12401 }
12402 }
12403
12404 public final void unbroadcastIntent(IApplicationThread caller,
12405 Intent intent) {
12406 // Refuse possible leaked file descriptors
12407 if (intent != null && intent.hasFileDescriptors() == true) {
12408 throw new IllegalArgumentException("File descriptors passed in Intent");
12409 }
12410
12411 synchronized(this) {
12412 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12413 != PackageManager.PERMISSION_GRANTED) {
12414 String msg = "Permission Denial: unbroadcastIntent() from pid="
12415 + Binder.getCallingPid()
12416 + ", uid=" + Binder.getCallingUid()
12417 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012418 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012419 throw new SecurityException(msg);
12420 }
12421 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12422 if (list != null) {
12423 int N = list.size();
12424 int i;
12425 for (i=0; i<N; i++) {
12426 if (intent.filterEquals(list.get(i))) {
12427 list.remove(i);
12428 break;
12429 }
12430 }
12431 }
12432 }
12433 }
12434
12435 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12436 String resultData, Bundle resultExtras, boolean resultAbort,
12437 boolean explicit) {
12438 if (mOrderedBroadcasts.size() == 0) {
12439 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012440 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012441 }
12442 return false;
12443 }
12444 BroadcastRecord r = mOrderedBroadcasts.get(0);
12445 if (r.receiver == null) {
12446 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012447 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012448 }
12449 return false;
12450 }
12451 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012452 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012453 return false;
12454 }
12455 int state = r.state;
12456 r.state = r.IDLE;
12457 if (state == r.IDLE) {
12458 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012459 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012460 }
12461 }
12462 r.receiver = null;
12463 r.intent.setComponent(null);
12464 if (r.curApp != null) {
12465 r.curApp.curReceiver = null;
12466 }
12467 if (r.curFilter != null) {
12468 r.curFilter.receiverList.curBroadcast = null;
12469 }
12470 r.curFilter = null;
12471 r.curApp = null;
12472 r.curComponent = null;
12473 r.curReceiver = null;
12474 mPendingBroadcast = null;
12475
12476 r.resultCode = resultCode;
12477 r.resultData = resultData;
12478 r.resultExtras = resultExtras;
12479 r.resultAbort = resultAbort;
12480
12481 // We will process the next receiver right now if this is finishing
12482 // an app receiver (which is always asynchronous) or after we have
12483 // come back from calling a receiver.
12484 return state == BroadcastRecord.APP_RECEIVE
12485 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12486 }
12487
12488 public void finishReceiver(IBinder who, int resultCode, String resultData,
12489 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012490 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012491
12492 // Refuse possible leaked file descriptors
12493 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12494 throw new IllegalArgumentException("File descriptors passed in Bundle");
12495 }
12496
12497 boolean doNext;
12498
12499 final long origId = Binder.clearCallingIdentity();
12500
12501 synchronized(this) {
12502 doNext = finishReceiverLocked(
12503 who, resultCode, resultData, resultExtras, resultAbort, true);
12504 }
12505
12506 if (doNext) {
12507 processNextBroadcast(false);
12508 }
12509 trimApplications();
12510
12511 Binder.restoreCallingIdentity(origId);
12512 }
12513
12514 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12515 if (r.nextReceiver > 0) {
12516 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12517 if (curReceiver instanceof BroadcastFilter) {
12518 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012519 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012520 System.identityHashCode(r),
12521 r.intent.getAction(),
12522 r.nextReceiver - 1,
12523 System.identityHashCode(bf));
12524 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012525 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012526 System.identityHashCode(r),
12527 r.intent.getAction(),
12528 r.nextReceiver - 1,
12529 ((ResolveInfo)curReceiver).toString());
12530 }
12531 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012532 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012533 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012534 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012535 System.identityHashCode(r),
12536 r.intent.getAction(),
12537 r.nextReceiver,
12538 "NONE");
12539 }
12540 }
12541
12542 private final void broadcastTimeout() {
12543 synchronized (this) {
12544 if (mOrderedBroadcasts.size() == 0) {
12545 return;
12546 }
12547 long now = SystemClock.uptimeMillis();
12548 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012549 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012550 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012551 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012552 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012553 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012554 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012555 return;
12556 }
12557
Joe Onorato8a9b2202010-02-26 18:56:32 -080012558 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012559 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012560 r.anrCount++;
12561
12562 // Current receiver has passed its expiration date.
12563 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012564 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012565 return;
12566 }
12567
12568 ProcessRecord app = null;
12569
12570 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012571 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012572 logBroadcastReceiverDiscard(r);
12573 if (curReceiver instanceof BroadcastFilter) {
12574 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12575 if (bf.receiverList.pid != 0
12576 && bf.receiverList.pid != MY_PID) {
12577 synchronized (this.mPidsSelfLocked) {
12578 app = this.mPidsSelfLocked.get(
12579 bf.receiverList.pid);
12580 }
12581 }
12582 } else {
12583 app = r.curApp;
12584 }
12585
12586 if (app != null) {
Dan Egnorb7f03672009-12-09 16:22:32 -080012587 appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012588 }
12589
12590 if (mPendingBroadcast == r) {
12591 mPendingBroadcast = null;
12592 }
12593
12594 // Move on to the next receiver.
12595 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12596 r.resultExtras, r.resultAbort, true);
12597 scheduleBroadcastsLocked();
12598 }
12599 }
12600
12601 private final void processCurBroadcastLocked(BroadcastRecord r,
12602 ProcessRecord app) throws RemoteException {
12603 if (app.thread == null) {
12604 throw new RemoteException();
12605 }
12606 r.receiver = app.thread.asBinder();
12607 r.curApp = app;
12608 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012609 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012610
12611 // Tell the application to launch this receiver.
12612 r.intent.setComponent(r.curComponent);
12613
12614 boolean started = false;
12615 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012616 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012617 "Delivering to component " + r.curComponent
12618 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012619 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012620 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12621 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12622 started = true;
12623 } finally {
12624 if (!started) {
12625 r.receiver = null;
12626 r.curApp = null;
12627 app.curReceiver = null;
12628 }
12629 }
12630
12631 }
12632
12633 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012634 Intent intent, int resultCode, String data, Bundle extras,
12635 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012636 if (app != null && app.thread != null) {
12637 // If we have an app thread, do the call through that so it is
12638 // correctly ordered with other one-way calls.
12639 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012640 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012641 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012642 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012643 }
12644 }
12645
12646 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12647 BroadcastFilter filter, boolean ordered) {
12648 boolean skip = false;
12649 if (filter.requiredPermission != null) {
12650 int perm = checkComponentPermission(filter.requiredPermission,
12651 r.callingPid, r.callingUid, -1);
12652 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012653 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654 + r.intent.toString()
12655 + " from " + r.callerPackage + " (pid="
12656 + r.callingPid + ", uid=" + r.callingUid + ")"
12657 + " requires " + filter.requiredPermission
12658 + " due to registered receiver " + filter);
12659 skip = true;
12660 }
12661 }
12662 if (r.requiredPermission != null) {
12663 int perm = checkComponentPermission(r.requiredPermission,
12664 filter.receiverList.pid, filter.receiverList.uid, -1);
12665 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012666 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012667 + r.intent.toString()
12668 + " to " + filter.receiverList.app
12669 + " (pid=" + filter.receiverList.pid
12670 + ", uid=" + filter.receiverList.uid + ")"
12671 + " requires " + r.requiredPermission
12672 + " due to sender " + r.callerPackage
12673 + " (uid " + r.callingUid + ")");
12674 skip = true;
12675 }
12676 }
12677
12678 if (!skip) {
12679 // If this is not being sent as an ordered broadcast, then we
12680 // don't want to touch the fields that keep track of the current
12681 // state of ordered broadcasts.
12682 if (ordered) {
12683 r.receiver = filter.receiverList.receiver.asBinder();
12684 r.curFilter = filter;
12685 filter.receiverList.curBroadcast = r;
12686 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012687 if (filter.receiverList.app != null) {
12688 // Bump hosting application to no longer be in background
12689 // scheduling class. Note that we can't do that if there
12690 // isn't an app... but we can only be in that case for
12691 // things that directly call the IActivityManager API, which
12692 // are already core system stuff so don't matter for this.
12693 r.curApp = filter.receiverList.app;
12694 filter.receiverList.app.curReceiver = r;
12695 updateOomAdjLocked();
12696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012697 }
12698 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012699 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012700 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012701 Slog.i(TAG, "Delivering to " + filter.receiverList.app
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012702 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012703 }
12704 performReceive(filter.receiverList.app, filter.receiverList.receiver,
12705 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012706 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012707 if (ordered) {
12708 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12709 }
12710 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012711 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012712 if (ordered) {
12713 r.receiver = null;
12714 r.curFilter = null;
12715 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012716 if (filter.receiverList.app != null) {
12717 filter.receiverList.app.curReceiver = null;
12718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012719 }
12720 }
12721 }
12722 }
12723
Dianne Hackborn12527f92009-11-11 17:39:50 -080012724 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12725 if (r.callingUid < 0) {
12726 // This was from a registerReceiver() call; ignore it.
12727 return;
12728 }
12729 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12730 MAX_BROADCAST_HISTORY-1);
12731 r.finishTime = SystemClock.uptimeMillis();
12732 mBroadcastHistory[0] = r;
12733 }
12734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012735 private final void processNextBroadcast(boolean fromMsg) {
12736 synchronized(this) {
12737 BroadcastRecord r;
12738
Joe Onorato8a9b2202010-02-26 18:56:32 -080012739 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012740 + mParallelBroadcasts.size() + " broadcasts, "
12741 + mOrderedBroadcasts.size() + " serialized broadcasts");
12742
12743 updateCpuStats();
12744
12745 if (fromMsg) {
12746 mBroadcastsScheduled = false;
12747 }
12748
12749 // First, deliver any non-serialized broadcasts right away.
12750 while (mParallelBroadcasts.size() > 0) {
12751 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012752 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012753 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012754 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012755 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012756 for (int i=0; i<N; i++) {
12757 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012758 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012759 "Delivering non-serialized to registered "
12760 + target + ": " + r);
12761 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
12762 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012763 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012764 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012765 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012766 }
12767
12768 // Now take care of the next serialized one...
12769
12770 // If we are waiting for a process to come up to handle the next
12771 // broadcast, then do nothing at this point. Just in case, we
12772 // check that the process we're waiting for still exists.
12773 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012774 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012775 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012776 + mPendingBroadcast.curApp);
12777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012778
12779 boolean isDead;
12780 synchronized (mPidsSelfLocked) {
12781 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12782 }
12783 if (!isDead) {
12784 // It's still alive, so keep waiting
12785 return;
12786 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012787 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012788 + " died before responding to broadcast");
12789 mPendingBroadcast = null;
12790 }
12791 }
12792
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012793 boolean looped = false;
12794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012795 do {
12796 if (mOrderedBroadcasts.size() == 0) {
12797 // No more broadcasts pending, so all done!
12798 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012799 if (looped) {
12800 // If we had finished the last ordered broadcast, then
12801 // make sure all processes have correct oom and sched
12802 // adjustments.
12803 updateOomAdjLocked();
12804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012805 return;
12806 }
12807 r = mOrderedBroadcasts.get(0);
12808 boolean forceReceive = false;
12809
12810 // Ensure that even if something goes awry with the timeout
12811 // detection, we catch "hung" broadcasts here, discard them,
12812 // and continue to make progress.
12813 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
12814 long now = SystemClock.uptimeMillis();
12815 if (r.dispatchTime > 0) {
12816 if ((numReceivers > 0) &&
12817 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012818 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012819 + " now=" + now
12820 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012821 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012822 + " intent=" + r.intent
12823 + " numReceivers=" + numReceivers
12824 + " nextReceiver=" + r.nextReceiver
12825 + " state=" + r.state);
12826 broadcastTimeout(); // forcibly finish this broadcast
12827 forceReceive = true;
12828 r.state = BroadcastRecord.IDLE;
12829 }
12830 }
12831
12832 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012833 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012834 "processNextBroadcast() called when not idle (state="
12835 + r.state + ")");
12836 return;
12837 }
12838
12839 if (r.receivers == null || r.nextReceiver >= numReceivers
12840 || r.resultAbort || forceReceive) {
12841 // No more receivers for this broadcast! Send the final
12842 // result if requested...
12843 if (r.resultTo != null) {
12844 try {
12845 if (DEBUG_BROADCAST) {
12846 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012847 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012848 + " seq=" + seq + " app=" + r.callerApp);
12849 }
12850 performReceive(r.callerApp, r.resultTo,
12851 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012852 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012853 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012854 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012855 }
12856 }
12857
Joe Onorato8a9b2202010-02-26 18:56:32 -080012858 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012859 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12860
Joe Onorato8a9b2202010-02-26 18:56:32 -080012861 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012862 + r);
12863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012864 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012865 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012866 mOrderedBroadcasts.remove(0);
12867 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012868 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012869 continue;
12870 }
12871 } while (r == null);
12872
12873 // Get the next receiver...
12874 int recIdx = r.nextReceiver++;
12875
12876 // Keep track of when this receiver started, and make sure there
12877 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012878 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012879 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012880 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012881
Joe Onorato8a9b2202010-02-26 18:56:32 -080012882 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012883 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012884 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012885 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012886 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012887 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012888 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012889 }
12890
12891 Object nextReceiver = r.receivers.get(recIdx);
12892 if (nextReceiver instanceof BroadcastFilter) {
12893 // Simple case: this is a registered receiver who gets
12894 // a direct call.
12895 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012896 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012897 "Delivering serialized to registered "
12898 + filter + ": " + r);
12899 deliverToRegisteredReceiver(r, filter, r.ordered);
12900 if (r.receiver == null || !r.ordered) {
12901 // The receiver has already finished, so schedule to
12902 // process the next one.
12903 r.state = BroadcastRecord.IDLE;
12904 scheduleBroadcastsLocked();
12905 }
12906 return;
12907 }
12908
12909 // Hard case: need to instantiate the receiver, possibly
12910 // starting its application process to host it.
12911
12912 ResolveInfo info =
12913 (ResolveInfo)nextReceiver;
12914
12915 boolean skip = false;
12916 int perm = checkComponentPermission(info.activityInfo.permission,
12917 r.callingPid, r.callingUid,
12918 info.activityInfo.exported
12919 ? -1 : info.activityInfo.applicationInfo.uid);
12920 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012921 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012922 + r.intent.toString()
12923 + " from " + r.callerPackage + " (pid=" + r.callingPid
12924 + ", uid=" + r.callingUid + ")"
12925 + " requires " + info.activityInfo.permission
12926 + " due to receiver " + info.activityInfo.packageName
12927 + "/" + info.activityInfo.name);
12928 skip = true;
12929 }
12930 if (r.callingUid != Process.SYSTEM_UID &&
12931 r.requiredPermission != null) {
12932 try {
12933 perm = ActivityThread.getPackageManager().
12934 checkPermission(r.requiredPermission,
12935 info.activityInfo.applicationInfo.packageName);
12936 } catch (RemoteException e) {
12937 perm = PackageManager.PERMISSION_DENIED;
12938 }
12939 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012940 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012941 + r.intent + " to "
12942 + info.activityInfo.applicationInfo.packageName
12943 + " requires " + r.requiredPermission
12944 + " due to sender " + r.callerPackage
12945 + " (uid " + r.callingUid + ")");
12946 skip = true;
12947 }
12948 }
12949 if (r.curApp != null && r.curApp.crashing) {
12950 // If the target process is crashing, just skip it.
12951 skip = true;
12952 }
12953
12954 if (skip) {
12955 r.receiver = null;
12956 r.curFilter = null;
12957 r.state = BroadcastRecord.IDLE;
12958 scheduleBroadcastsLocked();
12959 return;
12960 }
12961
12962 r.state = BroadcastRecord.APP_RECEIVE;
12963 String targetProcess = info.activityInfo.processName;
12964 r.curComponent = new ComponentName(
12965 info.activityInfo.applicationInfo.packageName,
12966 info.activityInfo.name);
12967 r.curReceiver = info.activityInfo;
12968
12969 // Is this receiver's application already running?
12970 ProcessRecord app = getProcessRecordLocked(targetProcess,
12971 info.activityInfo.applicationInfo.uid);
12972 if (app != null && app.thread != null) {
12973 try {
12974 processCurBroadcastLocked(r, app);
12975 return;
12976 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012977 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012978 + r.curComponent, e);
12979 }
12980
12981 // If a dead object exception was thrown -- fall through to
12982 // restart the application.
12983 }
12984
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012985 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012986 if ((r.curApp=startProcessLocked(targetProcess,
12987 info.activityInfo.applicationInfo, true,
12988 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012989 "broadcast", r.curComponent,
12990 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12991 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012992 // Ah, this recipient is unavailable. Finish it if necessary,
12993 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012994 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012995 + info.activityInfo.applicationInfo.packageName + "/"
12996 + info.activityInfo.applicationInfo.uid + " for broadcast "
12997 + r.intent + ": process is bad");
12998 logBroadcastReceiverDiscard(r);
12999 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13000 r.resultExtras, r.resultAbort, true);
13001 scheduleBroadcastsLocked();
13002 r.state = BroadcastRecord.IDLE;
13003 return;
13004 }
13005
13006 mPendingBroadcast = r;
13007 }
13008 }
13009
13010 // =========================================================
13011 // INSTRUMENTATION
13012 // =========================================================
13013
13014 public boolean startInstrumentation(ComponentName className,
13015 String profileFile, int flags, Bundle arguments,
13016 IInstrumentationWatcher watcher) {
13017 // Refuse possible leaked file descriptors
13018 if (arguments != null && arguments.hasFileDescriptors()) {
13019 throw new IllegalArgumentException("File descriptors passed in Bundle");
13020 }
13021
13022 synchronized(this) {
13023 InstrumentationInfo ii = null;
13024 ApplicationInfo ai = null;
13025 try {
13026 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013027 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013028 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013029 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013030 } catch (PackageManager.NameNotFoundException e) {
13031 }
13032 if (ii == null) {
13033 reportStartInstrumentationFailure(watcher, className,
13034 "Unable to find instrumentation info for: " + className);
13035 return false;
13036 }
13037 if (ai == null) {
13038 reportStartInstrumentationFailure(watcher, className,
13039 "Unable to find instrumentation target package: " + ii.targetPackage);
13040 return false;
13041 }
13042
13043 int match = mContext.getPackageManager().checkSignatures(
13044 ii.targetPackage, ii.packageName);
13045 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13046 String msg = "Permission Denial: starting instrumentation "
13047 + className + " from pid="
13048 + Binder.getCallingPid()
13049 + ", uid=" + Binder.getCallingPid()
13050 + " not allowed because package " + ii.packageName
13051 + " does not have a signature matching the target "
13052 + ii.targetPackage;
13053 reportStartInstrumentationFailure(watcher, className, msg);
13054 throw new SecurityException(msg);
13055 }
13056
13057 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013058 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013059 ProcessRecord app = addAppLocked(ai);
13060 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013061 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013062 app.instrumentationProfileFile = profileFile;
13063 app.instrumentationArguments = arguments;
13064 app.instrumentationWatcher = watcher;
13065 app.instrumentationResultClass = className;
13066 Binder.restoreCallingIdentity(origId);
13067 }
13068
13069 return true;
13070 }
13071
13072 /**
13073 * Report errors that occur while attempting to start Instrumentation. Always writes the
13074 * error to the logs, but if somebody is watching, send the report there too. This enables
13075 * the "am" command to report errors with more information.
13076 *
13077 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13078 * @param cn The component name of the instrumentation.
13079 * @param report The error report.
13080 */
13081 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13082 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013083 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013084 try {
13085 if (watcher != null) {
13086 Bundle results = new Bundle();
13087 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13088 results.putString("Error", report);
13089 watcher.instrumentationStatus(cn, -1, results);
13090 }
13091 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013092 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013093 }
13094 }
13095
13096 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13097 if (app.instrumentationWatcher != null) {
13098 try {
13099 // NOTE: IInstrumentationWatcher *must* be oneway here
13100 app.instrumentationWatcher.instrumentationFinished(
13101 app.instrumentationClass,
13102 resultCode,
13103 results);
13104 } catch (RemoteException e) {
13105 }
13106 }
13107 app.instrumentationWatcher = null;
13108 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013109 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013110 app.instrumentationProfileFile = null;
13111 app.instrumentationArguments = null;
13112
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013113 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013114 }
13115
13116 public void finishInstrumentation(IApplicationThread target,
13117 int resultCode, Bundle results) {
13118 // Refuse possible leaked file descriptors
13119 if (results != null && results.hasFileDescriptors()) {
13120 throw new IllegalArgumentException("File descriptors passed in Intent");
13121 }
13122
13123 synchronized(this) {
13124 ProcessRecord app = getRecordForAppLocked(target);
13125 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013126 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013127 return;
13128 }
13129 final long origId = Binder.clearCallingIdentity();
13130 finishInstrumentationLocked(app, resultCode, results);
13131 Binder.restoreCallingIdentity(origId);
13132 }
13133 }
13134
13135 // =========================================================
13136 // CONFIGURATION
13137 // =========================================================
13138
13139 public ConfigurationInfo getDeviceConfigurationInfo() {
13140 ConfigurationInfo config = new ConfigurationInfo();
13141 synchronized (this) {
13142 config.reqTouchScreen = mConfiguration.touchscreen;
13143 config.reqKeyboardType = mConfiguration.keyboard;
13144 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013145 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13146 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013147 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13148 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013149 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13150 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013151 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13152 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013153 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013154 }
13155 return config;
13156 }
13157
13158 public Configuration getConfiguration() {
13159 Configuration ci;
13160 synchronized(this) {
13161 ci = new Configuration(mConfiguration);
13162 }
13163 return ci;
13164 }
13165
13166 public void updateConfiguration(Configuration values) {
13167 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13168 "updateConfiguration()");
13169
13170 synchronized(this) {
13171 if (values == null && mWindowManager != null) {
13172 // sentinel: fetch the current configuration from the window manager
13173 values = mWindowManager.computeNewConfiguration();
13174 }
13175
13176 final long origId = Binder.clearCallingIdentity();
13177 updateConfigurationLocked(values, null);
13178 Binder.restoreCallingIdentity(origId);
13179 }
13180 }
13181
13182 /**
13183 * Do either or both things: (1) change the current configuration, and (2)
13184 * make sure the given activity is running with the (now) current
13185 * configuration. Returns true if the activity has been left running, or
13186 * false if <var>starting</var> is being destroyed to match the new
13187 * configuration.
13188 */
13189 public boolean updateConfigurationLocked(Configuration values,
13190 HistoryRecord starting) {
13191 int changes = 0;
13192
13193 boolean kept = true;
13194
13195 if (values != null) {
13196 Configuration newConfig = new Configuration(mConfiguration);
13197 changes = newConfig.updateFrom(values);
13198 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013199 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013200 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013201 }
13202
Doug Zongker2bec3d42009-12-04 12:52:44 -080013203 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013204
13205 if (values.locale != null) {
13206 saveLocaleLocked(values.locale,
13207 !values.locale.equals(mConfiguration.locale),
13208 values.userSetLocale);
13209 }
13210
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013211 mConfigurationSeq++;
13212 if (mConfigurationSeq <= 0) {
13213 mConfigurationSeq = 1;
13214 }
13215 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013216 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013217 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013218
13219 AttributeCache ac = AttributeCache.instance();
13220 if (ac != null) {
13221 ac.updateConfiguration(mConfiguration);
13222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013223
13224 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13225 msg.obj = new Configuration(mConfiguration);
13226 mHandler.sendMessage(msg);
13227
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013228 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13229 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013230 try {
13231 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013232 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013233 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013234 app.thread.scheduleConfigurationChanged(mConfiguration);
13235 }
13236 } catch (Exception e) {
13237 }
13238 }
13239 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013240 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13241 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013242 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13243 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013244 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13245 broadcastIntentLocked(null, null,
13246 new Intent(Intent.ACTION_LOCALE_CHANGED),
13247 null, null, 0, null, null,
13248 null, false, false, MY_PID, Process.SYSTEM_UID);
13249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013250 }
13251 }
13252
13253 if (changes != 0 && starting == null) {
13254 // If the configuration changed, and the caller is not already
13255 // in the process of starting an activity, then find the top
13256 // activity to check if its configuration needs to change.
13257 starting = topRunningActivityLocked(null);
13258 }
13259
13260 if (starting != null) {
13261 kept = ensureActivityConfigurationLocked(starting, changes);
13262 if (kept) {
13263 // If this didn't result in the starting activity being
13264 // destroyed, then we need to make sure at this point that all
13265 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013266 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013267 + ", ensuring others are correct.");
13268 ensureActivitiesVisibleLocked(starting, changes);
13269 }
13270 }
13271
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013272 if (values != null && mWindowManager != null) {
13273 mWindowManager.setNewConfiguration(mConfiguration);
13274 }
13275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013276 return kept;
13277 }
13278
13279 private final boolean relaunchActivityLocked(HistoryRecord r,
13280 int changes, boolean andResume) {
13281 List<ResultInfo> results = null;
13282 List<Intent> newIntents = null;
13283 if (andResume) {
13284 results = r.results;
13285 newIntents = r.newIntents;
13286 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013287 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013288 + " with results=" + results + " newIntents=" + newIntents
13289 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013290 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13291 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013292 r.task.taskId, r.shortComponentName);
13293
13294 r.startFreezingScreenLocked(r.app, 0);
13295
13296 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013297 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013298 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013299 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013300 // Note: don't need to call pauseIfSleepingLocked() here, because
13301 // the caller will only pass in 'andResume' if this activity is
13302 // currently resumed, which implies we aren't sleeping.
13303 } catch (RemoteException e) {
13304 return false;
13305 }
13306
13307 if (andResume) {
13308 r.results = null;
13309 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013310 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013311 }
13312
13313 return true;
13314 }
13315
13316 /**
13317 * Make sure the given activity matches the current configuration. Returns
13318 * false if the activity had to be destroyed. Returns true if the
13319 * configuration is the same, or the activity will remain running as-is
13320 * for whatever reason. Ensures the HistoryRecord is updated with the
13321 * correct configuration and all other bookkeeping is handled.
13322 */
13323 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13324 int globalChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013325 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013326 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013327
13328 // Short circuit: if the two configurations are the exact same
13329 // object (the common case), then there is nothing to do.
13330 Configuration newConfig = mConfiguration;
13331 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013332 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013333 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013334 return true;
13335 }
13336
13337 // We don't worry about activities that are finishing.
13338 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013339 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013340 "Configuration doesn't matter in finishing " + r);
13341 r.stopFreezingScreenLocked(false);
13342 return true;
13343 }
13344
13345 // Okay we now are going to make this activity have the new config.
13346 // But then we need to figure out how it needs to deal with that.
13347 Configuration oldConfig = r.configuration;
13348 r.configuration = newConfig;
13349
13350 // If the activity isn't currently running, just leave the new
13351 // configuration and it will pick that up next time it starts.
13352 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013353 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013354 "Configuration doesn't matter not running " + r);
13355 r.stopFreezingScreenLocked(false);
13356 return true;
13357 }
13358
13359 // If the activity isn't persistent, there is a chance we will
13360 // need to restart it.
13361 if (!r.persistent) {
13362
13363 // Figure out what has changed between the two configurations.
13364 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013365 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013366 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013367 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013368 + Integer.toHexString(r.info.configChanges)
13369 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013370 }
13371 if ((changes&(~r.info.configChanges)) != 0) {
13372 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13373 r.configChangeFlags |= changes;
13374 r.startFreezingScreenLocked(r.app, globalChanges);
13375 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013376 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013377 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013378 destroyActivityLocked(r, true);
13379 } else if (r.state == ActivityState.PAUSING) {
13380 // A little annoying: we are waiting for this activity to
13381 // finish pausing. Let's not do anything now, but just
13382 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013383 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013384 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013385 r.configDestroy = true;
13386 return true;
13387 } else if (r.state == ActivityState.RESUMED) {
13388 // Try to optimize this case: the configuration is changing
13389 // and we need to restart the top, resumed activity.
13390 // Instead of doing the normal handshaking, just say
13391 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013392 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013393 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013394 relaunchActivityLocked(r, r.configChangeFlags, true);
13395 r.configChangeFlags = 0;
13396 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013397 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013398 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013399 relaunchActivityLocked(r, r.configChangeFlags, false);
13400 r.configChangeFlags = 0;
13401 }
13402
13403 // All done... tell the caller we weren't able to keep this
13404 // activity around.
13405 return false;
13406 }
13407 }
13408
13409 // Default case: the activity can handle this new configuration, so
13410 // hand it over. Note that we don't need to give it the new
13411 // configuration, since we always send configuration changes to all
13412 // process when they happen so it can just use whatever configuration
13413 // it last got.
13414 if (r.app != null && r.app.thread != null) {
13415 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013416 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013417 r.app.thread.scheduleActivityConfigurationChanged(r);
13418 } catch (RemoteException e) {
13419 // If process died, whatever.
13420 }
13421 }
13422 r.stopFreezingScreenLocked(false);
13423
13424 return true;
13425 }
13426
13427 /**
13428 * Save the locale. You must be inside a synchronized (this) block.
13429 */
13430 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13431 if(isDiff) {
13432 SystemProperties.set("user.language", l.getLanguage());
13433 SystemProperties.set("user.region", l.getCountry());
13434 }
13435
13436 if(isPersist) {
13437 SystemProperties.set("persist.sys.language", l.getLanguage());
13438 SystemProperties.set("persist.sys.country", l.getCountry());
13439 SystemProperties.set("persist.sys.localevar", l.getVariant());
13440 }
13441 }
13442
13443 // =========================================================
13444 // LIFETIME MANAGEMENT
13445 // =========================================================
13446
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013447 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13448 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013449 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013450 // This adjustment has already been computed. If we are calling
13451 // from the top, we may have already computed our adjustment with
13452 // an earlier hidden adjustment that isn't really for us... if
13453 // so, use the new hidden adjustment.
13454 if (!recursed && app.hidden) {
13455 app.curAdj = hiddenAdj;
13456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013457 return app.curAdj;
13458 }
13459
13460 if (app.thread == null) {
13461 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013462 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013463 return (app.curAdj=EMPTY_APP_ADJ);
13464 }
13465
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013466 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13467 // The max adjustment doesn't allow this app to be anything
13468 // below foreground, so it is not worth doing work for it.
13469 app.adjType = "fixed";
13470 app.adjSeq = mAdjSeq;
13471 app.curRawAdj = app.maxAdj;
13472 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13473 return (app.curAdj=app.maxAdj);
13474 }
13475
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013476 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013477 app.adjSource = null;
13478 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013479 app.empty = false;
13480 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013481
The Android Open Source Project4df24232009-03-05 14:34:35 -080013482 // Determine the importance of the process, starting with most
13483 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013484 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013485 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013486 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013487 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013488 // The last app on the list is the foreground app.
13489 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013490 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013491 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013492 } else if (app.instrumentationClass != null) {
13493 // Don't want to kill running instrumentation.
13494 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013495 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013496 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013497 } else if (app.persistentActivities > 0) {
13498 // Special persistent activities... shouldn't be used these days.
13499 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013500 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013501 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013502 } else if (app.curReceiver != null ||
13503 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13504 // An app that is currently receiving a broadcast also
13505 // counts as being in the foreground.
13506 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013507 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013508 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013509 } else if (app.executingServices.size() > 0) {
13510 // An app that is currently executing a service callback also
13511 // counts as being in the foreground.
13512 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013513 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013514 app.adjType = "exec-service";
13515 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013516 // The user is aware of this app, so make it visible.
13517 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013518 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013519 app.adjType = "foreground-service";
13520 } else if (app.forcingToForeground != null) {
13521 // The user is aware of this app, so make it visible.
13522 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013523 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013524 app.adjType = "force-foreground";
13525 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013526 } else if (app == mHomeProcess) {
13527 // This process is hosting what we currently consider to be the
13528 // home app, so we don't want to let it go into the background.
13529 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013530 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013531 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013532 } else if ((N=app.activities.size()) != 0) {
13533 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013534 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013535 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013536 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013537 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013538 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013539 for (int j=0; j<N; j++) {
13540 if (((HistoryRecord)app.activities.get(j)).visible) {
13541 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013542 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013543 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013544 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013545 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013546 break;
13547 }
13548 }
13549 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013550 // A very not-needed process. If this is lower in the lru list,
13551 // we will push it in to the empty bucket.
13552 app.hidden = true;
13553 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013554 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013555 adj = hiddenAdj;
13556 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013557 }
13558
Joe Onorato8a9b2202010-02-26 18:56:32 -080013559 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013560
The Android Open Source Project4df24232009-03-05 14:34:35 -080013561 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013562 // there are applications dependent on our services or providers, but
13563 // this gives us a baseline and makes sure we don't get into an
13564 // infinite recursion.
13565 app.adjSeq = mAdjSeq;
13566 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013567
Christopher Tate6fa95972009-06-05 18:43:55 -070013568 if (mBackupTarget != null && app == mBackupTarget.app) {
13569 // If possible we want to avoid killing apps while they're being backed up
13570 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013571 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013572 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013573 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013574 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013575 }
13576 }
13577
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013578 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13579 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013580 final long now = SystemClock.uptimeMillis();
13581 // This process is more important if the top activity is
13582 // bound to the service.
13583 Iterator jt = app.services.iterator();
13584 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13585 ServiceRecord s = (ServiceRecord)jt.next();
13586 if (s.startRequested) {
13587 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13588 // This service has seen some activity within
13589 // recent memory, so we will keep its process ahead
13590 // of the background processes.
13591 if (adj > SECONDARY_SERVER_ADJ) {
13592 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013593 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013594 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013595 }
13596 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013597 // If we have let the service slide into the background
13598 // state, still have some text describing what it is doing
13599 // even though the service no longer has an impact.
13600 if (adj > SECONDARY_SERVER_ADJ) {
13601 app.adjType = "started-bg-services";
13602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013603 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013604 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13605 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013606 Iterator<ConnectionRecord> kt
13607 = s.connections.values().iterator();
13608 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13609 // XXX should compute this based on the max of
13610 // all connected clients.
13611 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013612 if (cr.binding.client == app) {
13613 // Binding to ourself is not interesting.
13614 continue;
13615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013616 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13617 ProcessRecord client = cr.binding.client;
13618 int myHiddenAdj = hiddenAdj;
13619 if (myHiddenAdj > client.hiddenAdj) {
13620 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13621 myHiddenAdj = client.hiddenAdj;
13622 } else {
13623 myHiddenAdj = VISIBLE_APP_ADJ;
13624 }
13625 }
13626 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013627 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013628 if (adj > clientAdj) {
13629 adj = clientAdj > VISIBLE_APP_ADJ
13630 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013631 if (!client.hidden) {
13632 app.hidden = false;
13633 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013634 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013635 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13636 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013637 app.adjSource = cr.binding.client;
13638 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013639 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013640 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13641 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13642 schedGroup = Process.THREAD_GROUP_DEFAULT;
13643 }
13644 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013645 }
13646 HistoryRecord a = cr.activity;
13647 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013648 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013649 //}
13650 if (a != null && adj > FOREGROUND_APP_ADJ &&
13651 (a.state == ActivityState.RESUMED
13652 || a.state == ActivityState.PAUSING)) {
13653 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013654 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013655 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013656 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013657 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13658 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013659 app.adjSource = a;
13660 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013661 }
13662 }
13663 }
13664 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013665
13666 // Finally, f this process has active services running in it, we
13667 // would like to avoid killing it unless it would prevent the current
13668 // application from running. By default we put the process in
13669 // with the rest of the background processes; as we scan through
13670 // its services we may bump it up from there.
13671 if (adj > hiddenAdj) {
13672 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013673 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013674 app.adjType = "bg-services";
13675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013676 }
13677
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013678 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13679 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013680 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013681 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13682 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013683 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
13684 if (cpr.clients.size() != 0) {
13685 Iterator<ProcessRecord> kt = cpr.clients.iterator();
13686 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13687 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013688 if (client == app) {
13689 // Being our own client is not interesting.
13690 continue;
13691 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013692 int myHiddenAdj = hiddenAdj;
13693 if (myHiddenAdj > client.hiddenAdj) {
13694 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
13695 myHiddenAdj = client.hiddenAdj;
13696 } else {
13697 myHiddenAdj = FOREGROUND_APP_ADJ;
13698 }
13699 }
13700 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013701 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013702 if (adj > clientAdj) {
13703 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013704 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013705 if (!client.hidden) {
13706 app.hidden = false;
13707 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013708 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013709 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13710 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013711 app.adjSource = client;
13712 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013713 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013714 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13715 schedGroup = Process.THREAD_GROUP_DEFAULT;
13716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013717 }
13718 }
13719 // If the provider has external (non-framework) process
13720 // dependencies, ensure that its adjustment is at least
13721 // FOREGROUND_APP_ADJ.
13722 if (cpr.externals != 0) {
13723 if (adj > FOREGROUND_APP_ADJ) {
13724 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013725 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013726 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013727 app.adjType = "provider";
13728 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013729 }
13730 }
13731 }
13732 }
13733
13734 app.curRawAdj = adj;
13735
Joe Onorato8a9b2202010-02-26 18:56:32 -080013736 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013737 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13738 if (adj > app.maxAdj) {
13739 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013740 if (app.maxAdj <= VISIBLE_APP_ADJ) {
13741 schedGroup = Process.THREAD_GROUP_DEFAULT;
13742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013743 }
13744
13745 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013746 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013748 return adj;
13749 }
13750
13751 /**
13752 * Ask a given process to GC right now.
13753 */
13754 final void performAppGcLocked(ProcessRecord app) {
13755 try {
13756 app.lastRequestedGc = SystemClock.uptimeMillis();
13757 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013758 if (app.reportLowMemory) {
13759 app.reportLowMemory = false;
13760 app.thread.scheduleLowMemory();
13761 } else {
13762 app.thread.processInBackground();
13763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013764 }
13765 } catch (Exception e) {
13766 // whatever.
13767 }
13768 }
13769
13770 /**
13771 * Returns true if things are idle enough to perform GCs.
13772 */
13773 private final boolean canGcNow() {
13774 return mParallelBroadcasts.size() == 0
13775 && mOrderedBroadcasts.size() == 0
13776 && (mSleeping || (mResumedActivity != null &&
13777 mResumedActivity.idle));
13778 }
13779
13780 /**
13781 * Perform GCs on all processes that are waiting for it, but only
13782 * if things are idle.
13783 */
13784 final void performAppGcsLocked() {
13785 final int N = mProcessesToGc.size();
13786 if (N <= 0) {
13787 return;
13788 }
13789 if (canGcNow()) {
13790 while (mProcessesToGc.size() > 0) {
13791 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013792 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
13793 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13794 <= SystemClock.uptimeMillis()) {
13795 // To avoid spamming the system, we will GC processes one
13796 // at a time, waiting a few seconds between each.
13797 performAppGcLocked(proc);
13798 scheduleAppGcsLocked();
13799 return;
13800 } else {
13801 // It hasn't been long enough since we last GCed this
13802 // process... put it in the list to wait for its time.
13803 addProcessToGcListLocked(proc);
13804 break;
13805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013806 }
13807 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013808
13809 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013810 }
13811 }
13812
13813 /**
13814 * If all looks good, perform GCs on all processes waiting for them.
13815 */
13816 final void performAppGcsIfAppropriateLocked() {
13817 if (canGcNow()) {
13818 performAppGcsLocked();
13819 return;
13820 }
13821 // Still not idle, wait some more.
13822 scheduleAppGcsLocked();
13823 }
13824
13825 /**
13826 * Schedule the execution of all pending app GCs.
13827 */
13828 final void scheduleAppGcsLocked() {
13829 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013830
13831 if (mProcessesToGc.size() > 0) {
13832 // Schedule a GC for the time to the next process.
13833 ProcessRecord proc = mProcessesToGc.get(0);
13834 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13835
13836 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
13837 long now = SystemClock.uptimeMillis();
13838 if (when < (now+GC_TIMEOUT)) {
13839 when = now + GC_TIMEOUT;
13840 }
13841 mHandler.sendMessageAtTime(msg, when);
13842 }
13843 }
13844
13845 /**
13846 * Add a process to the array of processes waiting to be GCed. Keeps the
13847 * list in sorted order by the last GC time. The process can't already be
13848 * on the list.
13849 */
13850 final void addProcessToGcListLocked(ProcessRecord proc) {
13851 boolean added = false;
13852 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13853 if (mProcessesToGc.get(i).lastRequestedGc <
13854 proc.lastRequestedGc) {
13855 added = true;
13856 mProcessesToGc.add(i+1, proc);
13857 break;
13858 }
13859 }
13860 if (!added) {
13861 mProcessesToGc.add(0, proc);
13862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013863 }
13864
13865 /**
13866 * Set up to ask a process to GC itself. This will either do it
13867 * immediately, or put it on the list of processes to gc the next
13868 * time things are idle.
13869 */
13870 final void scheduleAppGcLocked(ProcessRecord app) {
13871 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013872 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013873 return;
13874 }
13875 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013876 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013877 scheduleAppGcsLocked();
13878 }
13879 }
13880
13881 private final boolean updateOomAdjLocked(
13882 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
13883 app.hiddenAdj = hiddenAdj;
13884
13885 if (app.thread == null) {
13886 return true;
13887 }
13888
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013889 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013890
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013891 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013892 if (app.curRawAdj != app.setRawAdj) {
13893 if (app.curRawAdj > FOREGROUND_APP_ADJ
13894 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13895 // If this app is transitioning from foreground to
13896 // non-foreground, have it do a gc.
13897 scheduleAppGcLocked(app);
13898 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13899 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13900 // Likewise do a gc when an app is moving in to the
13901 // background (such as a service stopping).
13902 scheduleAppGcLocked(app);
13903 }
13904 app.setRawAdj = app.curRawAdj;
13905 }
13906 if (adj != app.setAdj) {
13907 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013908 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013909 TAG, "Set app " + app.processName +
13910 " oom adj to " + adj);
13911 app.setAdj = adj;
13912 } else {
13913 return false;
13914 }
13915 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013916 if (app.setSchedGroup != app.curSchedGroup) {
13917 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013918 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013919 "Setting process group of " + app.processName
13920 + " to " + app.curSchedGroup);
13921 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070013922 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013923 try {
13924 Process.setProcessGroup(app.pid, app.curSchedGroup);
13925 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013926 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013927 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070013928 e.printStackTrace();
13929 } finally {
13930 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013931 }
13932 }
13933 if (false) {
13934 if (app.thread != null) {
13935 try {
13936 app.thread.setSchedulingGroup(app.curSchedGroup);
13937 } catch (RemoteException e) {
13938 }
13939 }
13940 }
13941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013942 }
13943
13944 return true;
13945 }
13946
13947 private final HistoryRecord resumedAppLocked() {
13948 HistoryRecord resumedActivity = mResumedActivity;
13949 if (resumedActivity == null || resumedActivity.app == null) {
13950 resumedActivity = mPausingActivity;
13951 if (resumedActivity == null || resumedActivity.app == null) {
13952 resumedActivity = topRunningActivityLocked(null);
13953 }
13954 }
13955 return resumedActivity;
13956 }
13957
13958 private final boolean updateOomAdjLocked(ProcessRecord app) {
13959 final HistoryRecord TOP_ACT = resumedAppLocked();
13960 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13961 int curAdj = app.curAdj;
13962 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13963 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13964
13965 mAdjSeq++;
13966
13967 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13968 if (res) {
13969 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13970 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13971 if (nowHidden != wasHidden) {
13972 // Changed to/from hidden state, so apps after it in the LRU
13973 // list may also be changed.
13974 updateOomAdjLocked();
13975 }
13976 }
13977 return res;
13978 }
13979
13980 private final boolean updateOomAdjLocked() {
13981 boolean didOomAdj = true;
13982 final HistoryRecord TOP_ACT = resumedAppLocked();
13983 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13984
13985 if (false) {
13986 RuntimeException e = new RuntimeException();
13987 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013988 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013989 }
13990
13991 mAdjSeq++;
13992
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013993 // Let's determine how many processes we have running vs.
13994 // how many slots we have for background processes; we may want
13995 // to put multiple processes in a slot of there are enough of
13996 // them.
13997 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13998 int factor = (mLruProcesses.size()-4)/numSlots;
13999 if (factor < 1) factor = 1;
14000 int step = 0;
14001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014002 // First try updating the OOM adjustment for each of the
14003 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014004 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014005 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14006 while (i > 0) {
14007 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014008 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014009 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014010 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014011 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014012 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014013 step++;
14014 if (step >= factor) {
14015 step = 0;
14016 curHiddenAdj++;
14017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014018 }
14019 } else {
14020 didOomAdj = false;
14021 }
14022 }
14023
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014024 // If we return false, we will fall back on killing processes to
14025 // have a fixed limit. Do this if a limit has been requested; else
14026 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014027 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14028 }
14029
14030 private final void trimApplications() {
14031 synchronized (this) {
14032 int i;
14033
14034 // First remove any unused application processes whose package
14035 // has been removed.
14036 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14037 final ProcessRecord app = mRemovedProcesses.get(i);
14038 if (app.activities.size() == 0
14039 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014040 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014041 TAG, "Exiting empty application process "
14042 + app.processName + " ("
14043 + (app.thread != null ? app.thread.asBinder() : null)
14044 + ")\n");
14045 if (app.pid > 0 && app.pid != MY_PID) {
14046 Process.killProcess(app.pid);
14047 } else {
14048 try {
14049 app.thread.scheduleExit();
14050 } catch (Exception e) {
14051 // Ignore exceptions.
14052 }
14053 }
14054 cleanUpApplicationRecordLocked(app, false, -1);
14055 mRemovedProcesses.remove(i);
14056
14057 if (app.persistent) {
14058 if (app.persistent) {
14059 addAppLocked(app.info);
14060 }
14061 }
14062 }
14063 }
14064
14065 // Now try updating the OOM adjustment for each of the
14066 // application processes based on their current state.
14067 // If the setOomAdj() API is not supported, then go with our
14068 // back-up plan...
14069 if (!updateOomAdjLocked()) {
14070
14071 // Count how many processes are running services.
14072 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014073 for (i=mLruProcesses.size()-1; i>=0; i--) {
14074 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014075
14076 if (app.persistent || app.services.size() != 0
14077 || app.curReceiver != null
14078 || app.persistentActivities > 0) {
14079 // Don't count processes holding services against our
14080 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014081 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014082 TAG, "Not trimming app " + app + " with services: "
14083 + app.services);
14084 numServiceProcs++;
14085 }
14086 }
14087
14088 int curMaxProcs = mProcessLimit;
14089 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14090 if (mAlwaysFinishActivities) {
14091 curMaxProcs = 1;
14092 }
14093 curMaxProcs += numServiceProcs;
14094
14095 // Quit as many processes as we can to get down to the desired
14096 // process count. First remove any processes that no longer
14097 // have activites running in them.
14098 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014099 i<mLruProcesses.size()
14100 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014101 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014102 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014103 // Quit an application only if it is not currently
14104 // running any activities.
14105 if (!app.persistent && app.activities.size() == 0
14106 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014107 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014108 TAG, "Exiting empty application process "
14109 + app.processName + " ("
14110 + (app.thread != null ? app.thread.asBinder() : null)
14111 + ")\n");
14112 if (app.pid > 0 && app.pid != MY_PID) {
14113 Process.killProcess(app.pid);
14114 } else {
14115 try {
14116 app.thread.scheduleExit();
14117 } catch (Exception e) {
14118 // Ignore exceptions.
14119 }
14120 }
14121 // todo: For now we assume the application is not buggy
14122 // or evil, and will quit as a result of our request.
14123 // Eventually we need to drive this off of the death
14124 // notification, and kill the process if it takes too long.
14125 cleanUpApplicationRecordLocked(app, false, i);
14126 i--;
14127 }
14128 }
14129
14130 // If we still have too many processes, now from the least
14131 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014132 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014133 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014134 " of " + curMaxProcs + " processes");
14135 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014136 i<mLruProcesses.size()
14137 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014138 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014139 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014140 // Quit the application only if we have a state saved for
14141 // all of its activities.
14142 boolean canQuit = !app.persistent && app.curReceiver == null
14143 && app.services.size() == 0
14144 && app.persistentActivities == 0;
14145 int NUMA = app.activities.size();
14146 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014147 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014148 TAG, "Looking to quit " + app.processName);
14149 for (j=0; j<NUMA && canQuit; j++) {
14150 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014151 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014152 TAG, " " + r.intent.getComponent().flattenToShortString()
14153 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14154 canQuit = (r.haveState || !r.stateNotNeeded)
14155 && !r.visible && r.stopped;
14156 }
14157 if (canQuit) {
14158 // Finish all of the activities, and then the app itself.
14159 for (j=0; j<NUMA; j++) {
14160 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14161 if (!r.finishing) {
14162 destroyActivityLocked(r, false);
14163 }
14164 r.resultTo = null;
14165 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014166 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014167 + app.processName + " ("
14168 + (app.thread != null ? app.thread.asBinder() : null)
14169 + ")\n");
14170 if (app.pid > 0 && app.pid != MY_PID) {
14171 Process.killProcess(app.pid);
14172 } else {
14173 try {
14174 app.thread.scheduleExit();
14175 } catch (Exception e) {
14176 // Ignore exceptions.
14177 }
14178 }
14179 // todo: For now we assume the application is not buggy
14180 // or evil, and will quit as a result of our request.
14181 // Eventually we need to drive this off of the death
14182 // notification, and kill the process if it takes too long.
14183 cleanUpApplicationRecordLocked(app, false, i);
14184 i--;
14185 //dump();
14186 }
14187 }
14188
14189 }
14190
14191 int curMaxActivities = MAX_ACTIVITIES;
14192 if (mAlwaysFinishActivities) {
14193 curMaxActivities = 1;
14194 }
14195
14196 // Finally, if there are too many activities now running, try to
14197 // finish as many as we can to get back down to the limit.
14198 for ( i=0;
14199 i<mLRUActivities.size()
14200 && mLRUActivities.size() > curMaxActivities;
14201 i++) {
14202 final HistoryRecord r
14203 = (HistoryRecord)mLRUActivities.get(i);
14204
14205 // We can finish this one if we have its icicle saved and
14206 // it is not persistent.
14207 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14208 && r.stopped && !r.persistent && !r.finishing) {
14209 final int origSize = mLRUActivities.size();
14210 destroyActivityLocked(r, true);
14211
14212 // This will remove it from the LRU list, so keep
14213 // our index at the same value. Note that this check to
14214 // see if the size changes is just paranoia -- if
14215 // something unexpected happens, we don't want to end up
14216 // in an infinite loop.
14217 if (origSize > mLRUActivities.size()) {
14218 i--;
14219 }
14220 }
14221 }
14222 }
14223 }
14224
14225 /** This method sends the specified signal to each of the persistent apps */
14226 public void signalPersistentProcesses(int sig) throws RemoteException {
14227 if (sig != Process.SIGNAL_USR1) {
14228 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14229 }
14230
14231 synchronized (this) {
14232 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14233 != PackageManager.PERMISSION_GRANTED) {
14234 throw new SecurityException("Requires permission "
14235 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14236 }
14237
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014238 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14239 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014240 if (r.thread != null && r.persistent) {
14241 Process.sendSignal(r.pid, sig);
14242 }
14243 }
14244 }
14245 }
14246
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014247 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014248 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014249
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014250 try {
14251 synchronized (this) {
14252 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14253 // its own permission.
14254 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14255 != PackageManager.PERMISSION_GRANTED) {
14256 throw new SecurityException("Requires permission "
14257 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014258 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014259
14260 if (start && fd == null) {
14261 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014262 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014263
14264 ProcessRecord proc = null;
14265 try {
14266 int pid = Integer.parseInt(process);
14267 synchronized (mPidsSelfLocked) {
14268 proc = mPidsSelfLocked.get(pid);
14269 }
14270 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014271 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014272
14273 if (proc == null) {
14274 HashMap<String, SparseArray<ProcessRecord>> all
14275 = mProcessNames.getMap();
14276 SparseArray<ProcessRecord> procs = all.get(process);
14277 if (procs != null && procs.size() > 0) {
14278 proc = procs.valueAt(0);
14279 }
14280 }
14281
14282 if (proc == null || proc.thread == null) {
14283 throw new IllegalArgumentException("Unknown process: " + process);
14284 }
14285
14286 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14287 if (isSecure) {
14288 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14289 throw new SecurityException("Process not debuggable: " + proc);
14290 }
14291 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014292
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014293 proc.thread.profilerControl(start, path, fd);
14294 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014295 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014296 }
14297 } catch (RemoteException e) {
14298 throw new IllegalStateException("Process disappeared");
14299 } finally {
14300 if (fd != null) {
14301 try {
14302 fd.close();
14303 } catch (IOException e) {
14304 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014305 }
14306 }
14307 }
14308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014309 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14310 public void monitor() {
14311 synchronized (this) { }
14312 }
14313}