blob: 0c11940b1b83f34b0d3a29e19c9ffa373b06440b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070020import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.server.IntentResolver;
22import com.android.server.ProcessMap;
23import com.android.server.ProcessStats;
24import com.android.server.SystemServer;
25import com.android.server.Watchdog;
26import com.android.server.WindowManagerService;
27
Dianne Hackborndd71fc82009-12-16 19:24:32 -080028import dalvik.system.Zygote;
29
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.app.Activity;
31import android.app.ActivityManager;
32import android.app.ActivityManagerNative;
33import android.app.ActivityThread;
34import android.app.AlertDialog;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020035import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070037import android.app.IActivityController;
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -080038import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.IActivityWatcher;
40import android.app.IApplicationThread;
41import android.app.IInstrumentationWatcher;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.app.IServiceConnection;
43import android.app.IThumbnailReceiver;
44import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070045import android.app.Notification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.PendingIntent;
47import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070048import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080049import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020050import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080051import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.ComponentName;
53import android.content.ContentResolver;
54import android.content.Context;
55import android.content.Intent;
56import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070057import android.content.IIntentReceiver;
58import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070059import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.content.pm.ActivityInfo;
61import android.content.pm.ApplicationInfo;
62import android.content.pm.ConfigurationInfo;
63import android.content.pm.IPackageDataObserver;
64import android.content.pm.IPackageManager;
65import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080066import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070068import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.content.pm.ProviderInfo;
70import android.content.pm.ResolveInfo;
71import android.content.pm.ServiceInfo;
72import android.content.res.Configuration;
73import android.graphics.Bitmap;
74import android.net.Uri;
75import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080076import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080077import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070078import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080079import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.FileUtils;
83import android.os.Handler;
84import android.os.IBinder;
85import android.os.IPermissionController;
86import android.os.Looper;
87import android.os.Message;
88import android.os.Parcel;
89import android.os.ParcelFileDescriptor;
90import android.os.PowerManager;
91import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070092import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.os.RemoteException;
94import android.os.ServiceManager;
95import android.os.SystemClock;
96import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.util.Config;
99import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800100import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800101import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.PrintWriterPrinter;
103import android.util.SparseArray;
104import android.view.Gravity;
105import android.view.LayoutInflater;
106import android.view.View;
107import android.view.WindowManager;
108import android.view.WindowManagerPolicy;
109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import java.io.File;
111import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200113import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800114import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import java.io.PrintWriter;
116import java.lang.IllegalStateException;
117import java.lang.ref.WeakReference;
118import java.util.ArrayList;
119import java.util.HashMap;
120import java.util.HashSet;
121import java.util.Iterator;
122import java.util.List;
123import java.util.Locale;
124import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700125import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700126import java.util.concurrent.atomic.AtomicBoolean;
127import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128
129public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
130 static final String TAG = "ActivityManager";
131 static final boolean DEBUG = false;
132 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
133 static final boolean DEBUG_SWITCH = localLOGV || false;
134 static final boolean DEBUG_TASKS = localLOGV || false;
135 static final boolean DEBUG_PAUSE = localLOGV || false;
136 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
137 static final boolean DEBUG_TRANSITION = localLOGV || false;
138 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700139 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 static final boolean DEBUG_SERVICE = localLOGV || false;
141 static final boolean DEBUG_VISBILITY = localLOGV || false;
142 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700143 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800144 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700146 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700147 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700148 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 static final boolean VALIDATE_TOKENS = false;
150 static final boolean SHOW_ACTIVITY_START_TIME = true;
151
152 // Control over CPU and battery monitoring.
153 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
154 static final boolean MONITOR_CPU_USAGE = true;
155 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
156 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
157 static final boolean MONITOR_THREAD_CPU_USAGE = false;
158
Dianne Hackborn1655be42009-05-08 14:29:01 -0700159 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700160 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 private static final String SYSTEM_SECURE = "ro.secure";
163
164 // This is the maximum number of application processes we would like
165 // to have running. Due to the asynchronous nature of things, we can
166 // temporarily go beyond this limit.
167 static final int MAX_PROCESSES = 2;
168
169 // Set to false to leave processes running indefinitely, relying on
170 // the kernel killing them as resources are required.
171 static final boolean ENFORCE_PROCESS_LIMIT = false;
172
173 // This is the maximum number of activities that we would like to have
174 // running at a given time.
175 static final int MAX_ACTIVITIES = 20;
176
177 // Maximum number of recent tasks that we can remember.
178 static final int MAX_RECENT_TASKS = 20;
179
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700180 // Amount of time after a call to stopAppSwitches() during which we will
181 // prevent further untrusted switches from happening.
182 static final long APP_SWITCH_DELAY_TIME = 5*1000;
183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 // How long until we reset a task when the user returns to it. Currently
185 // 30 minutes.
186 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
187
188 // Set to true to disable the icon that is shown while a new activity
189 // is being started.
190 static final boolean SHOW_APP_STARTING_ICON = true;
191
192 // How long we wait until giving up on the last activity to pause. This
193 // is short because it directly impacts the responsiveness of starting the
194 // next activity.
195 static final int PAUSE_TIMEOUT = 500;
196
197 /**
198 * How long we can hold the launch wake lock before giving up.
199 */
200 static final int LAUNCH_TIMEOUT = 10*1000;
201
202 // How long we wait for a launched process to attach to the activity manager
203 // before we decide it's never going to come up for real.
204 static final int PROC_START_TIMEOUT = 10*1000;
205
206 // How long we wait until giving up on the last activity telling us it
207 // is idle.
208 static final int IDLE_TIMEOUT = 10*1000;
209
210 // How long to wait after going idle before forcing apps to GC.
211 static final int GC_TIMEOUT = 5*1000;
212
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700213 // The minimum amount of time between successive GC requests for a process.
214 static final int GC_MIN_INTERVAL = 60*1000;
215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 // How long we wait until giving up on an activity telling us it has
217 // finished destroying itself.
218 static final int DESTROY_TIMEOUT = 10*1000;
219
220 // How long we allow a receiver to run before giving up on it.
221 static final int BROADCAST_TIMEOUT = 10*1000;
222
223 // How long we wait for a service to finish executing.
224 static final int SERVICE_TIMEOUT = 20*1000;
225
226 // How long a service needs to be running until restarting its process
227 // is no longer considered to be a relaunch of the service.
228 static final int SERVICE_RESTART_DURATION = 5*1000;
229
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700230 // How long a service needs to be running until it will start back at
231 // SERVICE_RESTART_DURATION after being killed.
232 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
233
234 // Multiplying factor to increase restart duration time by, for each time
235 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
236 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
237
238 // The minimum amount of time between restarting services that we allow.
239 // That is, when multiple services are restarting, we won't allow each
240 // to restart less than this amount of time from the last one.
241 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 // Maximum amount of time for there to be no activity on a service before
244 // we consider it non-essential and allow its process to go on the
245 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700246 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 // How long we wait until we timeout on key dispatching.
249 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
250
251 // The minimum time we allow between crashes, for us to consider this
252 // application to be bad and stop and its services and reject broadcasts.
253 static final int MIN_CRASH_INTERVAL = 60*1000;
254
255 // How long we wait until we timeout on key dispatching during instrumentation.
256 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
257
258 // OOM adjustments for processes in various states:
259
260 // This is a process without anything currently running in it. Definitely
261 // the first to go! Value set in system/rootdir/init.rc on startup.
262 // This value is initalized in the constructor, careful when refering to
263 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800264 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
266 // This is a process only hosting activities that are not visible,
267 // so it can be killed without any disruption. Value set in
268 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 static int HIDDEN_APP_MIN_ADJ;
271
The Android Open Source Project4df24232009-03-05 14:34:35 -0800272 // This is a process holding the home application -- we want to try
273 // avoiding killing it, even if it would normally be in the background,
274 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800276
Christopher Tate6fa95972009-06-05 18:43:55 -0700277 // This is a process currently hosting a backup operation. Killing it
278 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800279 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 // This is a process holding a secondary server -- killing it will not
282 // have much of an impact as far as the user is concerned. Value set in
283 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
286 // This is a process only hosting activities that are visible to the
287 // user, so we'd prefer they don't disappear. Value set in
288 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
291 // This is the process running the current foreground app. We'd really
292 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800293 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294
295 // This is a process running a core server, such as telephony. Definitely
296 // don't want to kill it, but doing so is not completely fatal.
297 static final int CORE_SERVER_ADJ = -12;
298
299 // The system process runs at the default adjustment.
300 static final int SYSTEM_ADJ = -16;
301
302 // Memory pages are 4K.
303 static final int PAGE_SIZE = 4*1024;
304
305 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int EMPTY_APP_MEM;
307 static final int HIDDEN_APP_MEM;
308 static final int HOME_APP_MEM;
309 static final int BACKUP_APP_MEM;
310 static final int SECONDARY_SERVER_MEM;
311 static final int VISIBLE_APP_MEM;
312 static final int FOREGROUND_APP_MEM;
313
314 // The minimum number of hidden apps we want to be able to keep around,
315 // without empty apps being able to push them out of memory.
316 static final int MIN_HIDDEN_APPS = 2;
317
Dianne Hackborn8633e682010-04-22 16:03:41 -0700318 // The maximum number of hidden processes we will keep around before
319 // killing them; this is just a control to not let us go too crazy with
320 // keeping around processes on devices with large amounts of RAM.
321 static final int MAX_HIDDEN_APPS = 15;
322
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800323 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700324 // been idle for less than 15 seconds.
325 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800326
327 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700328 // been idle for less than 120 seconds.
329 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800330
331 static {
332 // These values are set in system/rootdir/init.rc on startup.
333 FOREGROUND_APP_ADJ =
334 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
335 VISIBLE_APP_ADJ =
336 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
337 SECONDARY_SERVER_ADJ =
338 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
339 BACKUP_APP_ADJ =
340 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
341 HOME_APP_ADJ =
342 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
343 HIDDEN_APP_MIN_ADJ =
344 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
345 EMPTY_APP_ADJ =
346 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
347 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
348 FOREGROUND_APP_MEM =
349 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
350 VISIBLE_APP_MEM =
351 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
352 SECONDARY_SERVER_MEM =
353 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
354 BACKUP_APP_MEM =
355 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
356 HOME_APP_MEM =
357 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
358 HIDDEN_APP_MEM =
359 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
360 EMPTY_APP_MEM =
361 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
Dan Egnor42471dd2010-01-07 17:25:22 -0800364 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
366 static final String[] EMPTY_STRING_ARRAY = new String[0];
367
368 enum ActivityState {
369 INITIALIZING,
370 RESUMED,
371 PAUSING,
372 PAUSED,
373 STOPPING,
374 STOPPED,
375 FINISHING,
376 DESTROYING,
377 DESTROYED
378 }
379
380 /**
381 * The back history of all previous (and possibly still
382 * running) activities. It contains HistoryRecord objects.
383 */
384 final ArrayList mHistory = new ArrayList();
385
386 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700387 * Description of a request to start a new activity, which has been held
388 * due to app switches being disabled.
389 */
390 class PendingActivityLaunch {
391 HistoryRecord r;
392 HistoryRecord sourceRecord;
393 Uri[] grantedUriPermissions;
394 int grantedMode;
395 boolean onlyIfNeeded;
396 }
397
398 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
399 = new ArrayList<PendingActivityLaunch>();
400
401 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800402 * List of people waiting to find out about the next launched activity.
403 */
404 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
405 = new ArrayList<IActivityManager.WaitResult>();
406
407 /**
408 * List of people waiting to find out about the next visible activity.
409 */
410 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
411 = new ArrayList<IActivityManager.WaitResult>();
412
413 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 * List of all active broadcasts that are to be executed immediately
415 * (without waiting for another broadcast to finish). Currently this only
416 * contains broadcasts to registered receivers, to avoid spinning up
417 * a bunch of processes to execute IntentReceiver components.
418 */
419 final ArrayList<BroadcastRecord> mParallelBroadcasts
420 = new ArrayList<BroadcastRecord>();
421
422 /**
423 * List of all active broadcasts that are to be executed one at a time.
424 * The object at the top of the list is the currently activity broadcasts;
425 * those after it are waiting for the top to finish..
426 */
427 final ArrayList<BroadcastRecord> mOrderedBroadcasts
428 = new ArrayList<BroadcastRecord>();
429
430 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800431 * Historical data of past broadcasts, for debugging.
432 */
433 static final int MAX_BROADCAST_HISTORY = 100;
434 final BroadcastRecord[] mBroadcastHistory
435 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
436
437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * Set when we current have a BROADCAST_INTENT_MSG in flight.
439 */
440 boolean mBroadcastsScheduled = false;
441
442 /**
443 * Set to indicate whether to issue an onUserLeaving callback when a
444 * newly launched activity is being brought in front of us.
445 */
446 boolean mUserLeaving = false;
447
448 /**
449 * When we are in the process of pausing an activity, before starting the
450 * next one, this variable holds the activity that is currently being paused.
451 */
452 HistoryRecord mPausingActivity = null;
453
454 /**
455 * Current activity that is resumed, or null if there is none.
456 */
457 HistoryRecord mResumedActivity = null;
458
459 /**
460 * Activity we have told the window manager to have key focus.
461 */
462 HistoryRecord mFocusedActivity = null;
463
464 /**
465 * This is the last activity that we put into the paused state. This is
466 * used to determine if we need to do an activity transition while sleeping,
467 * when we normally hold the top activity paused.
468 */
469 HistoryRecord mLastPausedActivity = null;
470
471 /**
472 * List of activities that are waiting for a new activity
473 * to become visible before completing whatever operation they are
474 * supposed to do.
475 */
476 final ArrayList mWaitingVisibleActivities = new ArrayList();
477
478 /**
479 * List of activities that are ready to be stopped, but waiting
480 * for the next activity to settle down before doing so. It contains
481 * HistoryRecord objects.
482 */
483 final ArrayList<HistoryRecord> mStoppingActivities
484 = new ArrayList<HistoryRecord>();
485
486 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700487 * Animations that for the current transition have requested not to
488 * be considered for the transition animation.
489 */
490 final ArrayList<HistoryRecord> mNoAnimActivities
491 = new ArrayList<HistoryRecord>();
492
493 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 * List of intents that were used to start the most recent tasks.
495 */
496 final ArrayList<TaskRecord> mRecentTasks
497 = new ArrayList<TaskRecord>();
498
499 /**
500 * List of activities that are ready to be finished, but waiting
501 * for the previous activity to settle down before doing so. It contains
502 * HistoryRecord objects.
503 */
504 final ArrayList mFinishingActivities = new ArrayList();
505
506 /**
507 * All of the applications we currently have running organized by name.
508 * The keys are strings of the application package name (as
509 * returned by the package manager), and the keys are ApplicationRecord
510 * objects.
511 */
512 final ProcessMap<ProcessRecord> mProcessNames
513 = new ProcessMap<ProcessRecord>();
514
515 /**
516 * The last time that various processes have crashed.
517 */
518 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
519
520 /**
521 * Set of applications that we consider to be bad, and will reject
522 * incoming broadcasts from (which the user has no control over).
523 * Processes are added to this set when they have crashed twice within
524 * a minimum amount of time; they are removed from it when they are
525 * later restarted (hopefully due to some user action). The value is the
526 * time it was added to the list.
527 */
528 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
529
530 /**
531 * All of the processes we currently have running organized by pid.
532 * The keys are the pid running the application.
533 *
534 * <p>NOTE: This object is protected by its own lock, NOT the global
535 * activity manager lock!
536 */
537 final SparseArray<ProcessRecord> mPidsSelfLocked
538 = new SparseArray<ProcessRecord>();
539
540 /**
541 * All of the processes that have been forced to be foreground. The key
542 * is the pid of the caller who requested it (we hold a death
543 * link on it).
544 */
545 abstract class ForegroundToken implements IBinder.DeathRecipient {
546 int pid;
547 IBinder token;
548 }
549 final SparseArray<ForegroundToken> mForegroundProcesses
550 = new SparseArray<ForegroundToken>();
551
552 /**
553 * List of records for processes that someone had tried to start before the
554 * system was ready. We don't start them at that point, but ensure they
555 * are started by the time booting is complete.
556 */
557 final ArrayList<ProcessRecord> mProcessesOnHold
558 = new ArrayList<ProcessRecord>();
559
560 /**
561 * List of records for processes that we have started and are waiting
562 * for them to call back. This is really only needed when running in
563 * single processes mode, in which case we do not have a unique pid for
564 * each process.
565 */
566 final ArrayList<ProcessRecord> mStartingProcesses
567 = new ArrayList<ProcessRecord>();
568
569 /**
570 * List of persistent applications that are in the process
571 * of being started.
572 */
573 final ArrayList<ProcessRecord> mPersistentStartingProcesses
574 = new ArrayList<ProcessRecord>();
575
576 /**
577 * Processes that are being forcibly torn down.
578 */
579 final ArrayList<ProcessRecord> mRemovedProcesses
580 = new ArrayList<ProcessRecord>();
581
582 /**
583 * List of running applications, sorted by recent usage.
584 * The first entry in the list is the least recently used.
585 * It contains ApplicationRecord objects. This list does NOT include
586 * any persistent application records (since we never want to exit them).
587 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800588 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 = new ArrayList<ProcessRecord>();
590
591 /**
592 * List of processes that should gc as soon as things are idle.
593 */
594 final ArrayList<ProcessRecord> mProcessesToGc
595 = new ArrayList<ProcessRecord>();
596
597 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800598 * This is the process holding what we currently consider to be
599 * the "home" activity.
600 */
601 private ProcessRecord mHomeProcess;
602
603 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 * List of running activities, sorted by recent usage.
605 * The first entry in the list is the least recently used.
606 * It contains HistoryRecord objects.
607 */
608 private final ArrayList mLRUActivities = new ArrayList();
609
610 /**
611 * Set of PendingResultRecord objects that are currently active.
612 */
613 final HashSet mPendingResultRecords = new HashSet();
614
615 /**
616 * Set of IntentSenderRecord objects that are currently active.
617 */
618 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
619 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
620
621 /**
622 * Intent broadcast that we have tried to start, but are
623 * waiting for its application's process to be created. We only
624 * need one (instead of a list) because we always process broadcasts
625 * one at a time, so no others can be started while waiting for this
626 * one.
627 */
628 BroadcastRecord mPendingBroadcast = null;
629
630 /**
631 * Keeps track of all IIntentReceivers that have been registered for
632 * broadcasts. Hash keys are the receiver IBinder, hash value is
633 * a ReceiverList.
634 */
635 final HashMap mRegisteredReceivers = new HashMap();
636
637 /**
638 * Resolver for broadcast intents to registered receivers.
639 * Holds BroadcastFilter (subclass of IntentFilter).
640 */
641 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
642 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
643 @Override
644 protected boolean allowFilterResult(
645 BroadcastFilter filter, List<BroadcastFilter> dest) {
646 IBinder target = filter.receiverList.receiver.asBinder();
647 for (int i=dest.size()-1; i>=0; i--) {
648 if (dest.get(i).receiverList.receiver.asBinder() == target) {
649 return false;
650 }
651 }
652 return true;
653 }
654 };
655
656 /**
657 * State of all active sticky broadcasts. Keys are the action of the
658 * sticky Intent, values are an ArrayList of all broadcasted intents with
659 * that action (which should usually be one).
660 */
661 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
662 new HashMap<String, ArrayList<Intent>>();
663
664 /**
665 * All currently running services.
666 */
667 final HashMap<ComponentName, ServiceRecord> mServices =
668 new HashMap<ComponentName, ServiceRecord>();
669
670 /**
671 * All currently running services indexed by the Intent used to start them.
672 */
673 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
674 new HashMap<Intent.FilterComparison, ServiceRecord>();
675
676 /**
677 * All currently bound service connections. Keys are the IBinder of
678 * the client's IServiceConnection.
679 */
680 final HashMap<IBinder, ConnectionRecord> mServiceConnections
681 = new HashMap<IBinder, ConnectionRecord>();
682
683 /**
684 * List of services that we have been asked to start,
685 * but haven't yet been able to. It is used to hold start requests
686 * while waiting for their corresponding application thread to get
687 * going.
688 */
689 final ArrayList<ServiceRecord> mPendingServices
690 = new ArrayList<ServiceRecord>();
691
692 /**
693 * List of services that are scheduled to restart following a crash.
694 */
695 final ArrayList<ServiceRecord> mRestartingServices
696 = new ArrayList<ServiceRecord>();
697
698 /**
699 * List of services that are in the process of being stopped.
700 */
701 final ArrayList<ServiceRecord> mStoppingServices
702 = new ArrayList<ServiceRecord>();
703
704 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700705 * Backup/restore process management
706 */
707 String mBackupAppName = null;
708 BackupRecord mBackupTarget = null;
709
710 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 * List of PendingThumbnailsRecord objects of clients who are still
712 * waiting to receive all of the thumbnails for a task.
713 */
714 final ArrayList mPendingThumbnails = new ArrayList();
715
716 /**
717 * List of HistoryRecord objects that have been finished and must
718 * still report back to a pending thumbnail receiver.
719 */
720 final ArrayList mCancelledThumbnails = new ArrayList();
721
722 /**
723 * All of the currently running global content providers. Keys are a
724 * string containing the provider name and values are a
725 * ContentProviderRecord object containing the data about it. Note
726 * that a single provider may be published under multiple names, so
727 * there may be multiple entries here for a single one in mProvidersByClass.
728 */
729 final HashMap mProvidersByName = new HashMap();
730
731 /**
732 * All of the currently running global content providers. Keys are a
733 * string containing the provider's implementation class and values are a
734 * ContentProviderRecord object containing the data about it.
735 */
736 final HashMap mProvidersByClass = new HashMap();
737
738 /**
739 * List of content providers who have clients waiting for them. The
740 * application is currently being launched and the provider will be
741 * removed from this list once it is published.
742 */
743 final ArrayList mLaunchingProviders = new ArrayList();
744
745 /**
746 * Global set of specific Uri permissions that have been granted.
747 */
748 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
749 = new SparseArray<HashMap<Uri, UriPermission>>();
750
751 /**
752 * Thread-local storage used to carry caller permissions over through
753 * indirect content-provider access.
754 * @see #ActivityManagerService.openContentUri()
755 */
756 private class Identity {
757 public int pid;
758 public int uid;
759
760 Identity(int _pid, int _uid) {
761 pid = _pid;
762 uid = _uid;
763 }
764 }
765 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
766
767 /**
768 * All information we have collected about the runtime performance of
769 * any user id that can impact battery performance.
770 */
771 final BatteryStatsService mBatteryStatsService;
772
773 /**
774 * information about component usage
775 */
776 final UsageStatsService mUsageStatsService;
777
778 /**
779 * Current configuration information. HistoryRecord objects are given
780 * a reference to this object to indicate which configuration they are
781 * currently running in, so this object must be kept immutable.
782 */
783 Configuration mConfiguration = new Configuration();
784
785 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800786 * Current sequencing integer of the configuration, for skipping old
787 * configurations.
788 */
789 int mConfigurationSeq = 0;
790
791 /**
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700792 * Set when we know we are going to be calling updateConfiguration()
793 * soon, so want to skip intermediate config checks.
794 */
795 boolean mConfigWillChange;
796
797 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700798 * Hardware-reported OpenGLES version.
799 */
800 final int GL_ES_VERSION;
801
802 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 * List of initialization arguments to pass to all processes when binding applications to them.
804 * For example, references to the commonly used services.
805 */
806 HashMap<String, IBinder> mAppBindArgs;
807
808 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700809 * Temporary to avoid allocations. Protected by main lock.
810 */
811 final StringBuilder mStringBuilder = new StringBuilder(256);
812
813 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 * Used to control how we initialize the service.
815 */
816 boolean mStartRunning = false;
817 ComponentName mTopComponent;
818 String mTopAction;
819 String mTopData;
820 boolean mSystemReady = false;
821 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700822 boolean mWaitingUpdate = false;
823 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824
825 Context mContext;
826
827 int mFactoryTest;
828
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700829 boolean mCheckedForSetup;
830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700832 * The time at which we will allow normal application switches again,
833 * after a call to {@link #stopAppSwitches()}.
834 */
835 long mAppSwitchesAllowedTime;
836
837 /**
838 * This is set to true after the first switch after mAppSwitchesAllowedTime
839 * is set; any switches after that will clear the time.
840 */
841 boolean mDidAppSwitch;
842
843 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 * Set while we are wanting to sleep, to prevent any
845 * activities from being started/resumed.
846 */
847 boolean mSleeping = false;
848
849 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700850 * Set if we are shutting down the system, similar to sleeping.
851 */
852 boolean mShuttingDown = false;
853
854 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 * Set when the system is going to sleep, until we have
856 * successfully paused the current activity and released our wake lock.
857 * At that point the system is allowed to actually sleep.
858 */
859 PowerManager.WakeLock mGoingToSleep;
860
861 /**
862 * We don't want to allow the device to go to sleep while in the process
863 * of launching an activity. This is primarily to allow alarm intent
864 * receivers to launch an activity and get that to run before the device
865 * goes back to sleep.
866 */
867 PowerManager.WakeLock mLaunchingActivity;
868
869 /**
870 * Task identifier that activities are currently being started
871 * in. Incremented each time a new task is created.
872 * todo: Replace this with a TokenSpace class that generates non-repeating
873 * integers that won't wrap.
874 */
875 int mCurTask = 1;
876
877 /**
878 * Current sequence id for oom_adj computation traversal.
879 */
880 int mAdjSeq = 0;
881
882 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700883 * Current sequence id for process LRU updating.
884 */
885 int mLruSeq = 0;
886
887 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
889 * is set, indicating the user wants processes started in such a way
890 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
891 * running in each process (thus no pre-initialized process, etc).
892 */
893 boolean mSimpleProcessManagement = false;
894
895 /**
896 * System monitoring: number of processes that died since the last
897 * N procs were started.
898 */
899 int[] mProcDeaths = new int[20];
900
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700901 /**
902 * This is set if we had to do a delayed dexopt of an app before launching
903 * it, to increasing the ANR timeouts in that case.
904 */
905 boolean mDidDexOpt;
906
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 String mDebugApp = null;
908 boolean mWaitForDebugger = false;
909 boolean mDebugTransient = false;
910 String mOrigDebugApp = null;
911 boolean mOrigWaitForDebugger = false;
912 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700913 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700915 final RemoteCallbackList<IActivityWatcher> mWatchers
916 = new RemoteCallbackList<IActivityWatcher>();
917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 /**
919 * Callback of last caller to {@link #requestPss}.
920 */
921 Runnable mRequestPssCallback;
922
923 /**
924 * Remaining processes for which we are waiting results from the last
925 * call to {@link #requestPss}.
926 */
927 final ArrayList<ProcessRecord> mRequestPssList
928 = new ArrayList<ProcessRecord>();
929
930 /**
931 * Runtime statistics collection thread. This object's lock is used to
932 * protect all related state.
933 */
934 final Thread mProcessStatsThread;
935
936 /**
937 * Used to collect process stats when showing not responding dialog.
938 * Protected by mProcessStatsThread.
939 */
940 final ProcessStats mProcessStats = new ProcessStats(
941 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700942 final AtomicLong mLastCpuTime = new AtomicLong(0);
943 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 long mLastWriteTime = 0;
946
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700947 long mInitialStartTime = 0;
948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 /**
950 * Set to true after the system has finished booting.
951 */
952 boolean mBooted = false;
953
954 int mProcessLimit = 0;
955
956 WindowManagerService mWindowManager;
957
958 static ActivityManagerService mSelf;
959 static ActivityThread mSystemThread;
960
961 private final class AppDeathRecipient implements IBinder.DeathRecipient {
962 final ProcessRecord mApp;
963 final int mPid;
964 final IApplicationThread mAppThread;
965
966 AppDeathRecipient(ProcessRecord app, int pid,
967 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800968 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 TAG, "New death recipient " + this
970 + " for thread " + thread.asBinder());
971 mApp = app;
972 mPid = pid;
973 mAppThread = thread;
974 }
975
976 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800977 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 TAG, "Death received in " + this
979 + " for thread " + mAppThread.asBinder());
980 removeRequestedPss(mApp);
981 synchronized(ActivityManagerService.this) {
982 appDiedLocked(mApp, mPid, mAppThread);
983 }
984 }
985 }
986
987 static final int SHOW_ERROR_MSG = 1;
988 static final int SHOW_NOT_RESPONDING_MSG = 2;
989 static final int SHOW_FACTORY_ERROR_MSG = 3;
990 static final int UPDATE_CONFIGURATION_MSG = 4;
991 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
992 static final int WAIT_FOR_DEBUGGER_MSG = 6;
993 static final int BROADCAST_INTENT_MSG = 7;
994 static final int BROADCAST_TIMEOUT_MSG = 8;
995 static final int PAUSE_TIMEOUT_MSG = 9;
996 static final int IDLE_TIMEOUT_MSG = 10;
997 static final int IDLE_NOW_MSG = 11;
998 static final int SERVICE_TIMEOUT_MSG = 12;
999 static final int UPDATE_TIME_ZONE = 13;
1000 static final int SHOW_UID_ERROR_MSG = 14;
1001 static final int IM_FEELING_LUCKY_MSG = 15;
1002 static final int LAUNCH_TIMEOUT_MSG = 16;
1003 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 static final int RESUME_TOP_ACTIVITY_MSG = 19;
1005 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001006 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001007 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001008 static final int FINALIZE_PENDING_INTENT_MSG = 23;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009
1010 AlertDialog mUidAlert;
1011
1012 final Handler mHandler = new Handler() {
1013 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001014 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 //}
1016
1017 public void handleMessage(Message msg) {
1018 switch (msg.what) {
1019 case SHOW_ERROR_MSG: {
1020 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 synchronized (ActivityManagerService.this) {
1022 ProcessRecord proc = (ProcessRecord)data.get("app");
1023 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001024 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 return;
1026 }
1027 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001028 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001029 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 d.show();
1031 proc.crashDialog = d;
1032 } else {
1033 // The device is asleep, so just pretend that the user
1034 // saw a crash dialog and hit "force quit".
1035 res.set(0);
1036 }
1037 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001038
1039 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 } break;
1041 case SHOW_NOT_RESPONDING_MSG: {
1042 synchronized (ActivityManagerService.this) {
1043 HashMap data = (HashMap) msg.obj;
1044 ProcessRecord proc = (ProcessRecord)data.get("app");
1045 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001046 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 return;
1048 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001049
1050 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1051 null, null, 0, null, null, null,
1052 false, false, MY_PID, Process.SYSTEM_UID);
1053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1055 mContext, proc, (HistoryRecord)data.get("activity"));
1056 d.show();
1057 proc.anrDialog = d;
1058 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001059
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001060 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 } break;
1062 case SHOW_FACTORY_ERROR_MSG: {
1063 Dialog d = new FactoryErrorDialog(
1064 mContext, msg.getData().getCharSequence("msg"));
1065 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001066 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 } break;
1068 case UPDATE_CONFIGURATION_MSG: {
1069 final ContentResolver resolver = mContext.getContentResolver();
1070 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1071 } break;
1072 case GC_BACKGROUND_PROCESSES_MSG: {
1073 synchronized (ActivityManagerService.this) {
1074 performAppGcsIfAppropriateLocked();
1075 }
1076 } break;
1077 case WAIT_FOR_DEBUGGER_MSG: {
1078 synchronized (ActivityManagerService.this) {
1079 ProcessRecord app = (ProcessRecord)msg.obj;
1080 if (msg.arg1 != 0) {
1081 if (!app.waitedForDebugger) {
1082 Dialog d = new AppWaitingForDebuggerDialog(
1083 ActivityManagerService.this,
1084 mContext, app);
1085 app.waitDialog = d;
1086 app.waitedForDebugger = true;
1087 d.show();
1088 }
1089 } else {
1090 if (app.waitDialog != null) {
1091 app.waitDialog.dismiss();
1092 app.waitDialog = null;
1093 }
1094 }
1095 }
1096 } break;
1097 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001098 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 TAG, "Received BROADCAST_INTENT_MSG");
1100 processNextBroadcast(true);
1101 } break;
1102 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001103 if (mDidDexOpt) {
1104 mDidDexOpt = false;
1105 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1106 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1107 return;
1108 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001109 // Only process broadcast timeouts if the system is ready. That way
1110 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1111 // to do heavy lifting for system up
1112 if (mSystemReady) {
1113 broadcastTimeout();
1114 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 } break;
1116 case PAUSE_TIMEOUT_MSG: {
1117 IBinder token = (IBinder)msg.obj;
1118 // We don't at this point know if the activity is fullscreen,
1119 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001120 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 activityPaused(token, null, true);
1122 } break;
1123 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001124 if (mDidDexOpt) {
1125 mDidDexOpt = false;
1126 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1127 nmsg.obj = msg.obj;
1128 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1129 return;
1130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 // We don't at this point know if the activity is fullscreen,
1132 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001133 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001134 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001135 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 } break;
1137 case DESTROY_TIMEOUT_MSG: {
1138 IBinder token = (IBinder)msg.obj;
1139 // We don't at this point know if the activity is fullscreen,
1140 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001141 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 activityDestroyed(token);
1143 } break;
1144 case IDLE_NOW_MSG: {
1145 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001146 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 } break;
1148 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001149 if (mDidDexOpt) {
1150 mDidDexOpt = false;
1151 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1152 nmsg.obj = msg.obj;
1153 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1154 return;
1155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 serviceTimeout((ProcessRecord)msg.obj);
1157 } break;
1158 case UPDATE_TIME_ZONE: {
1159 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001160 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1161 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 if (r.thread != null) {
1163 try {
1164 r.thread.updateTimeZone();
1165 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001166 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 }
1168 }
1169 }
1170 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001171 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 case SHOW_UID_ERROR_MSG: {
1173 // XXX This is a temporary dialog, no need to localize.
1174 AlertDialog d = new BaseErrorDialog(mContext);
1175 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1176 d.setCancelable(false);
1177 d.setTitle("System UIDs Inconsistent");
1178 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1179 d.setButton("I'm Feeling Lucky",
1180 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1181 mUidAlert = d;
1182 d.show();
1183 } break;
1184 case IM_FEELING_LUCKY_MSG: {
1185 if (mUidAlert != null) {
1186 mUidAlert.dismiss();
1187 mUidAlert = null;
1188 }
1189 } break;
1190 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001191 if (mDidDexOpt) {
1192 mDidDexOpt = false;
1193 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1194 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1195 return;
1196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 synchronized (ActivityManagerService.this) {
1198 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001199 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 mLaunchingActivity.release();
1201 }
1202 }
1203 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204 case RESUME_TOP_ACTIVITY_MSG: {
1205 synchronized (ActivityManagerService.this) {
1206 resumeTopActivityLocked(null);
1207 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001208 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001210 if (mDidDexOpt) {
1211 mDidDexOpt = false;
1212 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1213 nmsg.obj = msg.obj;
1214 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1215 return;
1216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 ProcessRecord app = (ProcessRecord)msg.obj;
1218 synchronized (ActivityManagerService.this) {
1219 processStartTimedOutLocked(app);
1220 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001221 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001222 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1223 synchronized (ActivityManagerService.this) {
1224 doPendingActivityLaunchesLocked(true);
1225 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001226 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001227 case KILL_APPLICATION_MSG: {
1228 synchronized (ActivityManagerService.this) {
1229 int uid = msg.arg1;
1230 boolean restart = (msg.arg2 == 1);
1231 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001232 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001233 }
1234 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001235 case FINALIZE_PENDING_INTENT_MSG: {
1236 ((PendingIntentRecord)msg.obj).completeFinalize();
1237 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 }
1239 }
1240 };
1241
1242 public static void setSystemProcess() {
1243 try {
1244 ActivityManagerService m = mSelf;
1245
1246 ServiceManager.addService("activity", m);
1247 ServiceManager.addService("meminfo", new MemBinder(m));
1248 if (MONITOR_CPU_USAGE) {
1249 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 ServiceManager.addService("permission", new PermissionController(m));
1252
1253 ApplicationInfo info =
1254 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001255 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001256 mSystemThread.installSystemApplicationInfo(info);
1257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 synchronized (mSelf) {
1259 ProcessRecord app = mSelf.newProcessRecordLocked(
1260 mSystemThread.getApplicationThread(), info,
1261 info.processName);
1262 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001263 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 app.maxAdj = SYSTEM_ADJ;
1265 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1266 synchronized (mSelf.mPidsSelfLocked) {
1267 mSelf.mPidsSelfLocked.put(app.pid, app);
1268 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001269 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 }
1271 } catch (PackageManager.NameNotFoundException e) {
1272 throw new RuntimeException(
1273 "Unable to find android system package", e);
1274 }
1275 }
1276
1277 public void setWindowManager(WindowManagerService wm) {
1278 mWindowManager = wm;
1279 }
1280
1281 public static final Context main(int factoryTest) {
1282 AThread thr = new AThread();
1283 thr.start();
1284
1285 synchronized (thr) {
1286 while (thr.mService == null) {
1287 try {
1288 thr.wait();
1289 } catch (InterruptedException e) {
1290 }
1291 }
1292 }
1293
1294 ActivityManagerService m = thr.mService;
1295 mSelf = m;
1296 ActivityThread at = ActivityThread.systemMain();
1297 mSystemThread = at;
1298 Context context = at.getSystemContext();
1299 m.mContext = context;
1300 m.mFactoryTest = factoryTest;
1301 PowerManager pm =
1302 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1303 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1304 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1305 m.mLaunchingActivity.setReferenceCounted(false);
1306
1307 m.mBatteryStatsService.publish(context);
1308 m.mUsageStatsService.publish(context);
1309
1310 synchronized (thr) {
1311 thr.mReady = true;
1312 thr.notifyAll();
1313 }
1314
1315 m.startRunning(null, null, null, null);
1316
1317 return context;
1318 }
1319
1320 public static ActivityManagerService self() {
1321 return mSelf;
1322 }
1323
1324 static class AThread extends Thread {
1325 ActivityManagerService mService;
1326 boolean mReady = false;
1327
1328 public AThread() {
1329 super("ActivityManager");
1330 }
1331
1332 public void run() {
1333 Looper.prepare();
1334
1335 android.os.Process.setThreadPriority(
1336 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1337
1338 ActivityManagerService m = new ActivityManagerService();
1339
1340 synchronized (this) {
1341 mService = m;
1342 notifyAll();
1343 }
1344
1345 synchronized (this) {
1346 while (!mReady) {
1347 try {
1348 wait();
1349 } catch (InterruptedException e) {
1350 }
1351 }
1352 }
1353
1354 Looper.loop();
1355 }
1356 }
1357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 static class MemBinder extends Binder {
1359 ActivityManagerService mActivityManagerService;
1360 MemBinder(ActivityManagerService activityManagerService) {
1361 mActivityManagerService = activityManagerService;
1362 }
1363
1364 @Override
1365 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1366 ActivityManagerService service = mActivityManagerService;
1367 ArrayList<ProcessRecord> procs;
1368 synchronized (mActivityManagerService) {
1369 if (args != null && args.length > 0
1370 && args[0].charAt(0) != '-') {
1371 procs = new ArrayList<ProcessRecord>();
1372 int pid = -1;
1373 try {
1374 pid = Integer.parseInt(args[0]);
1375 } catch (NumberFormatException e) {
1376
1377 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001378 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1379 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 if (proc.pid == pid) {
1381 procs.add(proc);
1382 } else if (proc.processName.equals(args[0])) {
1383 procs.add(proc);
1384 }
1385 }
1386 if (procs.size() <= 0) {
1387 pw.println("No process found for: " + args[0]);
1388 return;
1389 }
1390 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001391 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 }
1393 }
1394 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1395 }
1396 }
1397
1398 static class CpuBinder extends Binder {
1399 ActivityManagerService mActivityManagerService;
1400 CpuBinder(ActivityManagerService activityManagerService) {
1401 mActivityManagerService = activityManagerService;
1402 }
1403
1404 @Override
1405 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1406 synchronized (mActivityManagerService.mProcessStatsThread) {
1407 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1408 }
1409 }
1410 }
1411
1412 private ActivityManagerService() {
1413 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1414 if (v != null && Integer.getInteger(v) != 0) {
1415 mSimpleProcessManagement = true;
1416 }
1417 v = System.getenv("ANDROID_DEBUG_APP");
1418 if (v != null) {
1419 mSimpleProcessManagement = true;
1420 }
1421
Joe Onorato8a9b2202010-02-26 18:56:32 -08001422 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 File dataDir = Environment.getDataDirectory();
1425 File systemDir = new File(dataDir, "system");
1426 systemDir.mkdirs();
1427 mBatteryStatsService = new BatteryStatsService(new File(
1428 systemDir, "batterystats.bin").toString());
1429 mBatteryStatsService.getActiveStatistics().readLocked();
1430 mBatteryStatsService.getActiveStatistics().writeLocked();
1431
1432 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001433 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434
Jack Palevichb90d28c2009-07-22 15:35:24 -07001435 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1436 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1437
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001438 mConfiguration.setToDefaults();
1439 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 mProcessStats.init();
1441
1442 // Add ourself to the Watchdog monitors.
1443 Watchdog.getInstance().addMonitor(this);
1444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 mProcessStatsThread = new Thread("ProcessStats") {
1446 public void run() {
1447 while (true) {
1448 try {
1449 try {
1450 synchronized(this) {
1451 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001452 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001454 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 // + ", write delay=" + nextWriteDelay);
1456 if (nextWriteDelay < nextCpuDelay) {
1457 nextCpuDelay = nextWriteDelay;
1458 }
1459 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001460 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 this.wait(nextCpuDelay);
1462 }
1463 }
1464 } catch (InterruptedException e) {
1465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 updateCpuStatsNow();
1467 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001468 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 }
1470 }
1471 }
1472 };
1473 mProcessStatsThread.start();
1474 }
1475
1476 @Override
1477 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1478 throws RemoteException {
1479 try {
1480 return super.onTransact(code, data, reply, flags);
1481 } catch (RuntimeException e) {
1482 // The activity manager only throws security exceptions, so let's
1483 // log all others.
1484 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001485 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 }
1487 throw e;
1488 }
1489 }
1490
1491 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001492 final long now = SystemClock.uptimeMillis();
1493 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1494 return;
1495 }
1496 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1497 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 mProcessStatsThread.notify();
1499 }
1500 }
1501 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 void updateCpuStatsNow() {
1504 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001505 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 final long now = SystemClock.uptimeMillis();
1507 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001510 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1511 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 haveNewCpuStats = true;
1513 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001514 //Slog.i(TAG, mProcessStats.printCurrentState());
1515 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 // + mProcessStats.getTotalCpuPercent() + "%");
1517
Joe Onorato8a9b2202010-02-26 18:56:32 -08001518 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 if ("true".equals(SystemProperties.get("events.cpu"))) {
1520 int user = mProcessStats.getLastUserTime();
1521 int system = mProcessStats.getLastSystemTime();
1522 int iowait = mProcessStats.getLastIoWaitTime();
1523 int irq = mProcessStats.getLastIrqTime();
1524 int softIrq = mProcessStats.getLastSoftIrqTime();
1525 int idle = mProcessStats.getLastIdleTime();
1526
1527 int total = user + system + iowait + irq + softIrq + idle;
1528 if (total == 0) total = 1;
1529
Doug Zongker2bec3d42009-12-04 12:52:44 -08001530 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 ((user+system+iowait+irq+softIrq) * 100) / total,
1532 (user * 100) / total,
1533 (system * 100) / total,
1534 (iowait * 100) / total,
1535 (irq * 100) / total,
1536 (softIrq * 100) / total);
1537 }
1538 }
1539
Amith Yamasanie43530a2009-08-21 13:11:37 -07001540 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001541 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001542 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 synchronized(mPidsSelfLocked) {
1544 if (haveNewCpuStats) {
1545 if (mBatteryStatsService.isOnBattery()) {
1546 final int N = mProcessStats.countWorkingStats();
1547 for (int i=0; i<N; i++) {
1548 ProcessStats.Stats st
1549 = mProcessStats.getWorkingStats(i);
1550 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1551 if (pr != null) {
1552 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1553 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001554 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001555 } else {
1556 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001557 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001558 if (ps != null) {
1559 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001560 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 }
1563 }
1564 }
1565 }
1566 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1569 mLastWriteTime = now;
1570 mBatteryStatsService.getActiveStatistics().writeLocked();
1571 }
1572 }
1573 }
1574 }
1575
1576 /**
1577 * Initialize the application bind args. These are passed to each
1578 * process when the bindApplication() IPC is sent to the process. They're
1579 * lazily setup to make sure the services are running when they're asked for.
1580 */
1581 private HashMap<String, IBinder> getCommonServicesLocked() {
1582 if (mAppBindArgs == null) {
1583 mAppBindArgs = new HashMap<String, IBinder>();
1584
1585 // Setup the application init args
1586 mAppBindArgs.put("package", ServiceManager.getService("package"));
1587 mAppBindArgs.put("window", ServiceManager.getService("window"));
1588 mAppBindArgs.put(Context.ALARM_SERVICE,
1589 ServiceManager.getService(Context.ALARM_SERVICE));
1590 }
1591 return mAppBindArgs;
1592 }
1593
1594 private final void setFocusedActivityLocked(HistoryRecord r) {
1595 if (mFocusedActivity != r) {
1596 mFocusedActivity = r;
1597 mWindowManager.setFocusedApp(r, true);
1598 }
1599 }
1600
Dianne Hackborn906497c2010-05-10 15:57:38 -07001601 private final void updateLruProcessInternalLocked(ProcessRecord app,
1602 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001603 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001604 int lrui = mLruProcesses.indexOf(app);
1605 if (lrui >= 0) mLruProcesses.remove(lrui);
1606
1607 int i = mLruProcesses.size()-1;
1608 int skipTop = 0;
1609
Dianne Hackborn906497c2010-05-10 15:57:38 -07001610 app.lruSeq = mLruSeq;
1611
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001612 // compute the new weight for this process.
1613 if (updateActivityTime) {
1614 app.lastActivityTime = SystemClock.uptimeMillis();
1615 }
1616 if (app.activities.size() > 0) {
1617 // If this process has activities, we more strongly want to keep
1618 // it around.
1619 app.lruWeight = app.lastActivityTime;
1620 } else if (app.pubProviders.size() > 0) {
1621 // If this process contains content providers, we want to keep
1622 // it a little more strongly.
1623 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1624 // Also don't let it kick out the first few "real" hidden processes.
1625 skipTop = MIN_HIDDEN_APPS;
1626 } else {
1627 // If this process doesn't have activities, we less strongly
1628 // want to keep it around, and generally want to avoid getting
1629 // in front of any very recently used activities.
1630 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1631 // Also don't let it kick out the first few "real" hidden processes.
1632 skipTop = MIN_HIDDEN_APPS;
1633 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001634
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001635 while (i >= 0) {
1636 ProcessRecord p = mLruProcesses.get(i);
1637 // If this app shouldn't be in front of the first N background
1638 // apps, then skip over that many that are currently hidden.
1639 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1640 skipTop--;
1641 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001642 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001643 mLruProcesses.add(i+1, app);
1644 break;
1645 }
1646 i--;
1647 }
1648 if (i < 0) {
1649 mLruProcesses.add(0, app);
1650 }
1651
Dianne Hackborn906497c2010-05-10 15:57:38 -07001652 // If the app is currently using a content provider or service,
1653 // bump those processes as well.
1654 if (app.connections.size() > 0) {
1655 for (ConnectionRecord cr : app.connections) {
1656 if (cr.binding != null && cr.binding.service != null
1657 && cr.binding.service.app != null
1658 && cr.binding.service.app.lruSeq != mLruSeq) {
1659 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1660 updateActivityTime, i+1);
1661 }
1662 }
1663 }
1664 if (app.conProviders.size() > 0) {
1665 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1666 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1667 updateLruProcessInternalLocked(cpr.app, oomAdj,
1668 updateActivityTime, i+1);
1669 }
1670 }
1671 }
1672
Joe Onorato8a9b2202010-02-26 18:56:32 -08001673 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 if (oomAdj) {
1675 updateOomAdjLocked();
1676 }
1677 }
1678
Dianne Hackborn906497c2010-05-10 15:57:38 -07001679 private final void updateLruProcessLocked(ProcessRecord app,
1680 boolean oomAdj, boolean updateActivityTime) {
1681 mLruSeq++;
1682 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1683 }
1684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 private final boolean updateLRUListLocked(HistoryRecord r) {
1686 final boolean hadit = mLRUActivities.remove(r);
1687 mLRUActivities.add(r);
1688 return hadit;
1689 }
1690
1691 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1692 int i = mHistory.size()-1;
1693 while (i >= 0) {
1694 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1695 if (!r.finishing && r != notTop) {
1696 return r;
1697 }
1698 i--;
1699 }
1700 return null;
1701 }
1702
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001703 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1704 int i = mHistory.size()-1;
1705 while (i >= 0) {
1706 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1707 if (!r.finishing && !r.delayedResume && r != notTop) {
1708 return r;
1709 }
1710 i--;
1711 }
1712 return null;
1713 }
1714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 /**
1716 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001717 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 *
1719 * @param token If non-null, any history records matching this token will be skipped.
1720 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1721 *
1722 * @return Returns the HistoryRecord of the next activity on the stack.
1723 */
1724 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1725 int i = mHistory.size()-1;
1726 while (i >= 0) {
1727 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1728 // Note: the taskId check depends on real taskId fields being non-zero
1729 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1730 return r;
1731 }
1732 i--;
1733 }
1734 return null;
1735 }
1736
1737 private final ProcessRecord getProcessRecordLocked(
1738 String processName, int uid) {
1739 if (uid == Process.SYSTEM_UID) {
1740 // The system gets to run in any process. If there are multiple
1741 // processes with the same uid, just pick the first (this
1742 // should never happen).
1743 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1744 processName);
1745 return procs != null ? procs.valueAt(0) : null;
1746 }
1747 ProcessRecord proc = mProcessNames.get(processName, uid);
1748 return proc;
1749 }
1750
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001751 private void ensurePackageDexOpt(String packageName) {
1752 IPackageManager pm = ActivityThread.getPackageManager();
1753 try {
1754 if (pm.performDexOpt(packageName)) {
1755 mDidDexOpt = true;
1756 }
1757 } catch (RemoteException e) {
1758 }
1759 }
1760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 private boolean isNextTransitionForward() {
1762 int transit = mWindowManager.getPendingAppTransition();
1763 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1764 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1765 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1766 }
1767
1768 private final boolean realStartActivityLocked(HistoryRecord r,
1769 ProcessRecord app, boolean andResume, boolean checkConfig)
1770 throws RemoteException {
1771
1772 r.startFreezingScreenLocked(app, 0);
1773 mWindowManager.setAppVisibility(r, true);
1774
1775 // Have the window manager re-evaluate the orientation of
1776 // the screen based on the new activity order. Note that
1777 // as a result of this, it can call back into the activity
1778 // manager with a new orientation. We don't care about that,
1779 // because the activity is not currently running so we are
1780 // just restarting it anyway.
1781 if (checkConfig) {
1782 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001783 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 r.mayFreezeScreenLocked(app) ? r : null);
1785 updateConfigurationLocked(config, r);
1786 }
1787
1788 r.app = app;
1789
Joe Onorato8a9b2202010-02-26 18:56:32 -08001790 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791
1792 int idx = app.activities.indexOf(r);
1793 if (idx < 0) {
1794 app.activities.add(r);
1795 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001796 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797
1798 try {
1799 if (app.thread == null) {
1800 throw new RemoteException();
1801 }
1802 List<ResultInfo> results = null;
1803 List<Intent> newIntents = null;
1804 if (andResume) {
1805 results = r.results;
1806 newIntents = r.newIntents;
1807 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001808 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 + " icicle=" + r.icicle
1810 + " with results=" + results + " newIntents=" + newIntents
1811 + " andResume=" + andResume);
1812 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001813 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 System.identityHashCode(r),
1815 r.task.taskId, r.shortComponentName);
1816 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001817 if (r.isHomeActivity) {
1818 mHomeProcess = app;
1819 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001820 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001822 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 r.info, r.icicle, results, newIntents, !andResume,
1824 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 } catch (RemoteException e) {
1826 if (r.launchFailed) {
1827 // This is the second time we failed -- finish activity
1828 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001829 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 + r.intent.getComponent().flattenToShortString()
1831 + ", giving up", e);
1832 appDiedLocked(app, app.pid, app.thread);
1833 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1834 "2nd-crash");
1835 return false;
1836 }
1837
1838 // This is the first time we failed -- restart process and
1839 // retry.
1840 app.activities.remove(r);
1841 throw e;
1842 }
1843
1844 r.launchFailed = false;
1845 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001846 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 + " being launched, but already in LRU list");
1848 }
1849
1850 if (andResume) {
1851 // As part of the process of launching, ActivityThread also performs
1852 // a resume.
1853 r.state = ActivityState.RESUMED;
1854 r.icicle = null;
1855 r.haveState = false;
1856 r.stopped = false;
1857 mResumedActivity = r;
1858 r.task.touchActiveTime();
1859 completeResumeLocked(r);
1860 pauseIfSleepingLocked();
1861 } else {
1862 // This activity is not starting in the resumed state... which
1863 // should look like we asked it to pause+stop (but remain visible),
1864 // and it has done so and reported back the current icicle and
1865 // other state.
1866 r.state = ActivityState.STOPPED;
1867 r.stopped = true;
1868 }
1869
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001870 // Launch the new version setup screen if needed. We do this -after-
1871 // launching the initial activity (that is, home), so that it can have
1872 // a chance to initialize itself while in the background, making the
1873 // switch back to it faster and look better.
1874 startSetupActivityLocked();
1875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 return true;
1877 }
1878
1879 private final void startSpecificActivityLocked(HistoryRecord r,
1880 boolean andResume, boolean checkConfig) {
1881 // Is this activity's application already running?
1882 ProcessRecord app = getProcessRecordLocked(r.processName,
1883 r.info.applicationInfo.uid);
1884
1885 if (r.startTime == 0) {
1886 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001887 if (mInitialStartTime == 0) {
1888 mInitialStartTime = r.startTime;
1889 }
1890 } else if (mInitialStartTime == 0) {
1891 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 }
1893
1894 if (app != null && app.thread != null) {
1895 try {
1896 realStartActivityLocked(r, app, andResume, checkConfig);
1897 return;
1898 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001899 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001900 + r.intent.getComponent().flattenToShortString(), e);
1901 }
1902
1903 // If a dead object exception was thrown -- fall through to
1904 // restart the application.
1905 }
1906
1907 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001908 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 }
1910
1911 private final ProcessRecord startProcessLocked(String processName,
1912 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001913 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1915 // We don't have to do anything more if:
1916 // (1) There is an existing application record; and
1917 // (2) The caller doesn't think it is dead, OR there is no thread
1918 // object attached to it so we know it couldn't have crashed; and
1919 // (3) There is a pid assigned to it, so it is either starting or
1920 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001921 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 + " app=" + app + " knownToBeDead=" + knownToBeDead
1923 + " thread=" + (app != null ? app.thread : null)
1924 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001925 if (app != null && app.pid > 0) {
1926 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001927 // We already have the app running, or are waiting for it to
1928 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001929 return app;
1930 } else {
1931 // An application record is attached to a previous process,
1932 // clean it up now.
1933 handleAppDiedLocked(app, true);
1934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 String hostingNameStr = hostingName != null
1938 ? hostingName.flattenToShortString() : null;
1939
1940 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1941 // If we are in the background, then check to see if this process
1942 // is bad. If so, we will just silently fail.
1943 if (mBadProcesses.get(info.processName, info.uid) != null) {
1944 return null;
1945 }
1946 } else {
1947 // When the user is explicitly starting a process, then clear its
1948 // crash count so that we won't make it bad until they see at
1949 // least one crash dialog again, and make the process good again
1950 // if it had been bad.
1951 mProcessCrashTimes.remove(info.processName, info.uid);
1952 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001953 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001954 info.processName);
1955 mBadProcesses.remove(info.processName, info.uid);
1956 if (app != null) {
1957 app.bad = false;
1958 }
1959 }
1960 }
1961
1962 if (app == null) {
1963 app = newProcessRecordLocked(null, info, processName);
1964 mProcessNames.put(processName, info.uid, app);
1965 } else {
1966 // If this is a new package in the process, add the package to the list
1967 app.addPackage(info.packageName);
1968 }
1969
1970 // If the system is not ready yet, then hold off on starting this
1971 // process until it is.
1972 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001973 && !isAllowedWhileBooting(info)
1974 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 if (!mProcessesOnHold.contains(app)) {
1976 mProcessesOnHold.add(app);
1977 }
1978 return app;
1979 }
1980
1981 startProcessLocked(app, hostingType, hostingNameStr);
1982 return (app.pid != 0) ? app : null;
1983 }
1984
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001985 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1986 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1987 }
1988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001989 private final void startProcessLocked(ProcessRecord app,
1990 String hostingType, String hostingNameStr) {
1991 if (app.pid > 0 && app.pid != MY_PID) {
1992 synchronized (mPidsSelfLocked) {
1993 mPidsSelfLocked.remove(app.pid);
1994 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1995 }
1996 app.pid = 0;
1997 }
1998
1999 mProcessesOnHold.remove(app);
2000
2001 updateCpuStats();
2002
2003 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
2004 mProcDeaths[0] = 0;
2005
2006 try {
2007 int uid = app.info.uid;
2008 int[] gids = null;
2009 try {
2010 gids = mContext.getPackageManager().getPackageGids(
2011 app.info.packageName);
2012 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002013 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002014 }
2015 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2016 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2017 && mTopComponent != null
2018 && app.processName.equals(mTopComponent.getPackageName())) {
2019 uid = 0;
2020 }
2021 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2022 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2023 uid = 0;
2024 }
2025 }
2026 int debugFlags = 0;
2027 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2028 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
2029 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002030 // Run the app in safe mode if its manifest requests so or the
2031 // system is booted in safe mode.
2032 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2033 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002034 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002036 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2037 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2038 }
2039 if ("1".equals(SystemProperties.get("debug.assert"))) {
2040 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2041 }
2042 int pid = Process.start("android.app.ActivityThread",
2043 mSimpleProcessManagement ? app.processName : null, uid, uid,
2044 gids, debugFlags, null);
2045 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2046 synchronized (bs) {
2047 if (bs.isOnBattery()) {
2048 app.batteryStats.incStartsLocked();
2049 }
2050 }
2051
Doug Zongker2bec3d42009-12-04 12:52:44 -08002052 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 app.processName, hostingType,
2054 hostingNameStr != null ? hostingNameStr : "");
2055
2056 if (app.persistent) {
2057 Watchdog.getInstance().processStarted(app, app.processName, pid);
2058 }
2059
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002060 StringBuilder buf = mStringBuilder;
2061 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 buf.append("Start proc ");
2063 buf.append(app.processName);
2064 buf.append(" for ");
2065 buf.append(hostingType);
2066 if (hostingNameStr != null) {
2067 buf.append(" ");
2068 buf.append(hostingNameStr);
2069 }
2070 buf.append(": pid=");
2071 buf.append(pid);
2072 buf.append(" uid=");
2073 buf.append(uid);
2074 buf.append(" gids={");
2075 if (gids != null) {
2076 for (int gi=0; gi<gids.length; gi++) {
2077 if (gi != 0) buf.append(", ");
2078 buf.append(gids[gi]);
2079
2080 }
2081 }
2082 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002083 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002084 if (pid == 0 || pid == MY_PID) {
2085 // Processes are being emulated with threads.
2086 app.pid = MY_PID;
2087 app.removed = false;
2088 mStartingProcesses.add(app);
2089 } else if (pid > 0) {
2090 app.pid = pid;
2091 app.removed = false;
2092 synchronized (mPidsSelfLocked) {
2093 this.mPidsSelfLocked.put(pid, app);
2094 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2095 msg.obj = app;
2096 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2097 }
2098 } else {
2099 app.pid = 0;
2100 RuntimeException e = new RuntimeException(
2101 "Failure starting process " + app.processName
2102 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002103 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002104 }
2105 } catch (RuntimeException e) {
2106 // XXX do better error recovery.
2107 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002108 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 }
2110 }
2111
2112 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2113 if (mPausingActivity != null) {
2114 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002115 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116 + mPausingActivity, e);
2117 }
2118 HistoryRecord prev = mResumedActivity;
2119 if (prev == null) {
2120 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002121 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 resumeTopActivityLocked(null);
2123 return;
2124 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002125 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 mResumedActivity = null;
2127 mPausingActivity = prev;
2128 mLastPausedActivity = prev;
2129 prev.state = ActivityState.PAUSING;
2130 prev.task.touchActiveTime();
2131
2132 updateCpuStats();
2133
2134 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002135 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002137 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 System.identityHashCode(prev),
2139 prev.shortComponentName);
2140 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2141 prev.configChangeFlags);
2142 updateUsageStats(prev, false);
2143 } catch (Exception e) {
2144 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002145 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 mPausingActivity = null;
2147 mLastPausedActivity = null;
2148 }
2149 } else {
2150 mPausingActivity = null;
2151 mLastPausedActivity = null;
2152 }
2153
2154 // If we are not going to sleep, we want to ensure the device is
2155 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002156 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 mLaunchingActivity.acquire();
2158 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2159 // To be safe, don't allow the wake lock to be held for too long.
2160 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2161 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2162 }
2163 }
2164
2165
2166 if (mPausingActivity != null) {
2167 // Have the window manager pause its key dispatching until the new
2168 // activity has started. If we're pausing the activity just because
2169 // the screen is being turned off and the UI is sleeping, don't interrupt
2170 // key dispatch; the same activity will pick it up again on wakeup.
2171 if (!uiSleeping) {
2172 prev.pauseKeyDispatchingLocked();
2173 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002174 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 }
2176
2177 // Schedule a pause timeout in case the app doesn't respond.
2178 // We don't give it much time because this directly impacts the
2179 // responsiveness seen by the user.
2180 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2181 msg.obj = prev;
2182 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002183 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184 } else {
2185 // This activity failed to schedule the
2186 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002187 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 resumeTopActivityLocked(null);
2189 }
2190 }
2191
2192 private final void completePauseLocked() {
2193 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002194 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195
2196 if (prev != null) {
2197 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002198 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002199 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2200 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002201 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002202 if (prev.waitingVisible) {
2203 prev.waitingVisible = false;
2204 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002205 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 TAG, "Complete pause, no longer waiting: " + prev);
2207 }
2208 if (prev.configDestroy) {
2209 // The previous is being paused because the configuration
2210 // is changing, which means it is actually stopping...
2211 // To juggle the fact that we are also starting a new
2212 // instance right now, we need to first completely stop
2213 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002214 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 destroyActivityLocked(prev, true);
2216 } else {
2217 mStoppingActivities.add(prev);
2218 if (mStoppingActivities.size() > 3) {
2219 // If we already have a few activities waiting to stop,
2220 // then give up on things going idle and start clearing
2221 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002222 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 Message msg = Message.obtain();
2224 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2225 mHandler.sendMessage(msg);
2226 }
2227 }
2228 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002229 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002230 prev = null;
2231 }
2232 mPausingActivity = null;
2233 }
2234
Dianne Hackborn55280a92009-05-07 15:53:46 -07002235 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 resumeTopActivityLocked(prev);
2237 } else {
2238 if (mGoingToSleep.isHeld()) {
2239 mGoingToSleep.release();
2240 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002241 if (mShuttingDown) {
2242 notifyAll();
2243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 }
2245
2246 if (prev != null) {
2247 prev.resumeKeyDispatchingLocked();
2248 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002249
2250 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2251 long diff = 0;
2252 synchronized (mProcessStatsThread) {
2253 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2254 }
2255 if (diff > 0) {
2256 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2257 synchronized (bsi) {
2258 BatteryStatsImpl.Uid.Proc ps =
2259 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2260 prev.info.packageName);
2261 if (ps != null) {
2262 ps.addForegroundTimeLocked(diff);
2263 }
2264 }
2265 }
2266 }
2267 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 }
2269
2270 /**
2271 * Once we know that we have asked an application to put an activity in
2272 * the resumed state (either by launching it or explicitly telling it),
2273 * this function updates the rest of our state to match that fact.
2274 */
2275 private final void completeResumeLocked(HistoryRecord next) {
2276 next.idle = false;
2277 next.results = null;
2278 next.newIntents = null;
2279
2280 // schedule an idle timeout in case the app doesn't do it for us.
2281 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2282 msg.obj = next;
2283 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2284
2285 if (false) {
2286 // The activity was never told to pause, so just keep
2287 // things going as-is. To maintain our own state,
2288 // we need to emulate it coming back and saying it is
2289 // idle.
2290 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2291 msg.obj = next;
2292 mHandler.sendMessage(msg);
2293 }
2294
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002295 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002297 next.thumbnail = null;
2298 setFocusedActivityLocked(next);
2299 next.resumeKeyDispatchingLocked();
2300 ensureActivitiesVisibleLocked(null, 0);
2301 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002302 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002303
2304 // Mark the point when the activity is resuming
2305 // TODO: To be more accurate, the mark should be before the onCreate,
2306 // not after the onResume. But for subsequent starts, onResume is fine.
2307 if (next.app != null) {
2308 synchronized (mProcessStatsThread) {
2309 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2310 }
2311 } else {
2312 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314 }
2315
2316 /**
2317 * Make sure that all activities that need to be visible (that is, they
2318 * currently can be seen by the user) actually are.
2319 */
2320 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2321 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002322 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 TAG, "ensureActivitiesVisible behind " + top
2324 + " configChanges=0x" + Integer.toHexString(configChanges));
2325
2326 // If the top activity is not fullscreen, then we need to
2327 // make sure any activities under it are now visible.
2328 final int count = mHistory.size();
2329 int i = count-1;
2330 while (mHistory.get(i) != top) {
2331 i--;
2332 }
2333 HistoryRecord r;
2334 boolean behindFullscreen = false;
2335 for (; i>=0; i--) {
2336 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002337 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 TAG, "Make visible? " + r + " finishing=" + r.finishing
2339 + " state=" + r.state);
2340 if (r.finishing) {
2341 continue;
2342 }
2343
2344 final boolean doThisProcess = onlyThisProcess == null
2345 || onlyThisProcess.equals(r.processName);
2346
2347 // First: if this is not the current activity being started, make
2348 // sure it matches the current configuration.
2349 if (r != starting && doThisProcess) {
2350 ensureActivityConfigurationLocked(r, 0);
2351 }
2352
2353 if (r.app == null || r.app.thread == null) {
2354 if (onlyThisProcess == null
2355 || onlyThisProcess.equals(r.processName)) {
2356 // This activity needs to be visible, but isn't even
2357 // running... get it started, but don't resume it
2358 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002359 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 TAG, "Start and freeze screen for " + r);
2361 if (r != starting) {
2362 r.startFreezingScreenLocked(r.app, configChanges);
2363 }
2364 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002365 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002366 TAG, "Starting and making visible: " + r);
2367 mWindowManager.setAppVisibility(r, true);
2368 }
2369 if (r != starting) {
2370 startSpecificActivityLocked(r, false, false);
2371 }
2372 }
2373
2374 } else if (r.visible) {
2375 // If this activity is already visible, then there is nothing
2376 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002377 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002378 TAG, "Skipping: already visible at " + r);
2379 r.stopFreezingScreenLocked(false);
2380
2381 } else if (onlyThisProcess == null) {
2382 // This activity is not currently visible, but is running.
2383 // Tell it to become visible.
2384 r.visible = true;
2385 if (r.state != ActivityState.RESUMED && r != starting) {
2386 // If this activity is paused, tell it
2387 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002388 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002389 TAG, "Making visible and scheduling visibility: " + r);
2390 try {
2391 mWindowManager.setAppVisibility(r, true);
2392 r.app.thread.scheduleWindowVisibility(r, true);
2393 r.stopFreezingScreenLocked(false);
2394 } catch (Exception e) {
2395 // Just skip on any failure; we'll make it
2396 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002397 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 + r.intent.getComponent(), e);
2399 }
2400 }
2401 }
2402
2403 // Aggregate current change flags.
2404 configChanges |= r.configChangeFlags;
2405
2406 if (r.fullscreen) {
2407 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002408 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002409 TAG, "Stopping: fullscreen at " + r);
2410 behindFullscreen = true;
2411 i--;
2412 break;
2413 }
2414 }
2415
2416 // Now for any activities that aren't visible to the user, make
2417 // sure they no longer are keeping the screen frozen.
2418 while (i >= 0) {
2419 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002420 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002421 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2422 + " state=" + r.state
2423 + " behindFullscreen=" + behindFullscreen);
2424 if (!r.finishing) {
2425 if (behindFullscreen) {
2426 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002427 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002428 TAG, "Making invisible: " + r);
2429 r.visible = false;
2430 try {
2431 mWindowManager.setAppVisibility(r, false);
2432 if ((r.state == ActivityState.STOPPING
2433 || r.state == ActivityState.STOPPED)
2434 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002435 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 TAG, "Scheduling invisibility: " + r);
2437 r.app.thread.scheduleWindowVisibility(r, false);
2438 }
2439 } catch (Exception e) {
2440 // Just skip on any failure; we'll make it
2441 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002442 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002443 + r.intent.getComponent(), e);
2444 }
2445 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002446 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002447 TAG, "Already invisible: " + r);
2448 }
2449 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002450 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002451 TAG, "Now behindFullscreen: " + r);
2452 behindFullscreen = true;
2453 }
2454 }
2455 i--;
2456 }
2457 }
2458
2459 /**
2460 * Version of ensureActivitiesVisible that can easily be called anywhere.
2461 */
2462 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2463 int configChanges) {
2464 HistoryRecord r = topRunningActivityLocked(null);
2465 if (r != null) {
2466 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2467 }
2468 }
2469
2470 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2471 if (resumed) {
2472 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2473 } else {
2474 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2475 }
2476 }
2477
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002478 private boolean startHomeActivityLocked() {
2479 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2480 && mTopAction == null) {
2481 // We are running in factory test mode, but unable to find
2482 // the factory test app, so just sit around displaying the
2483 // error message and don't try to start anything.
2484 return false;
2485 }
2486 Intent intent = new Intent(
2487 mTopAction,
2488 mTopData != null ? Uri.parse(mTopData) : null);
2489 intent.setComponent(mTopComponent);
2490 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2491 intent.addCategory(Intent.CATEGORY_HOME);
2492 }
2493 ActivityInfo aInfo =
2494 intent.resolveActivityInfo(mContext.getPackageManager(),
2495 STOCK_PM_FLAGS);
2496 if (aInfo != null) {
2497 intent.setComponent(new ComponentName(
2498 aInfo.applicationInfo.packageName, aInfo.name));
2499 // Don't do this if the home app is currently being
2500 // instrumented.
2501 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2502 aInfo.applicationInfo.uid);
2503 if (app == null || app.instrumentationClass == null) {
2504 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2505 startActivityLocked(null, intent, null, null, 0, aInfo,
2506 null, null, 0, 0, 0, false, false);
2507 }
2508 }
2509
2510
2511 return true;
2512 }
2513
2514 /**
2515 * Starts the "new version setup screen" if appropriate.
2516 */
2517 private void startSetupActivityLocked() {
2518 // Only do this once per boot.
2519 if (mCheckedForSetup) {
2520 return;
2521 }
2522
2523 // We will show this screen if the current one is a different
2524 // version than the last one shown, and we are not running in
2525 // low-level factory test mode.
2526 final ContentResolver resolver = mContext.getContentResolver();
2527 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2528 Settings.Secure.getInt(resolver,
2529 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2530 mCheckedForSetup = true;
2531
2532 // See if we should be showing the platform update setup UI.
2533 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2534 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2535 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2536
2537 // We don't allow third party apps to replace this.
2538 ResolveInfo ri = null;
2539 for (int i=0; ris != null && i<ris.size(); i++) {
2540 if ((ris.get(i).activityInfo.applicationInfo.flags
2541 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2542 ri = ris.get(i);
2543 break;
2544 }
2545 }
2546
2547 if (ri != null) {
2548 String vers = ri.activityInfo.metaData != null
2549 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2550 : null;
2551 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2552 vers = ri.activityInfo.applicationInfo.metaData.getString(
2553 Intent.METADATA_SETUP_VERSION);
2554 }
2555 String lastVers = Settings.Secure.getString(
2556 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2557 if (vers != null && !vers.equals(lastVers)) {
2558 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2559 intent.setComponent(new ComponentName(
2560 ri.activityInfo.packageName, ri.activityInfo.name));
2561 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2562 null, null, 0, 0, 0, false, false);
2563 }
2564 }
2565 }
2566 }
2567
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002568 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002569 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002570
2571 final int identHash = System.identityHashCode(r);
2572 updateUsageStats(r, true);
2573
2574 int i = mWatchers.beginBroadcast();
2575 while (i > 0) {
2576 i--;
2577 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2578 if (w != null) {
2579 try {
2580 w.activityResuming(identHash);
2581 } catch (RemoteException e) {
2582 }
2583 }
2584 }
2585 mWatchers.finishBroadcast();
2586 }
2587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 /**
2589 * Ensure that the top activity in the stack is resumed.
2590 *
2591 * @param prev The previously resumed activity, for when in the process
2592 * of pausing; can be null to call from elsewhere.
2593 *
2594 * @return Returns true if something is being resumed, or false if
2595 * nothing happened.
2596 */
2597 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2598 // Find the first activity that is not finishing.
2599 HistoryRecord next = topRunningActivityLocked(null);
2600
2601 // Remember how we'll process this pause/resume situation, and ensure
2602 // that the state is reset however we wind up proceeding.
2603 final boolean userLeaving = mUserLeaving;
2604 mUserLeaving = false;
2605
2606 if (next == null) {
2607 // There are no more activities! Let's just start up the
2608 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002609 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 }
2611
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002612 next.delayedResume = false;
2613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614 // If the top activity is the resumed one, nothing to do.
2615 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2616 // Make sure we have executed any pending transitions, since there
2617 // should be nothing left to do at this point.
2618 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002619 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620 return false;
2621 }
2622
2623 // If we are sleeping, and there is no resumed activity, and the top
2624 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002625 if ((mSleeping || mShuttingDown)
2626 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627 // Make sure we have executed any pending transitions, since there
2628 // should be nothing left to do at this point.
2629 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002630 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631 return false;
2632 }
2633
2634 // The activity may be waiting for stop, but that is no longer
2635 // appropriate for it.
2636 mStoppingActivities.remove(next);
2637 mWaitingVisibleActivities.remove(next);
2638
Joe Onorato8a9b2202010-02-26 18:56:32 -08002639 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640
2641 // If we are currently pausing an activity, then don't do anything
2642 // until that is done.
2643 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002644 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002645 return false;
2646 }
2647
2648 // We need to start pausing the current activity so the top one
2649 // can be resumed...
2650 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002651 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002652 startPausingLocked(userLeaving, false);
2653 return true;
2654 }
2655
2656 if (prev != null && prev != next) {
2657 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2658 prev.waitingVisible = true;
2659 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002660 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 TAG, "Resuming top, waiting visible to hide: " + prev);
2662 } else {
2663 // The next activity is already visible, so hide the previous
2664 // activity's windows right now so we can show the new one ASAP.
2665 // We only do this if the previous is finishing, which should mean
2666 // it is on top of the one being resumed so hiding it quickly
2667 // is good. Otherwise, we want to do the normal route of allowing
2668 // the resumed activity to be shown so we can decide if the
2669 // previous should actually be hidden depending on whether the
2670 // new one is found to be full-screen or not.
2671 if (prev.finishing) {
2672 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002673 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674 + prev + ", waitingVisible="
2675 + (prev != null ? prev.waitingVisible : null)
2676 + ", nowVisible=" + next.nowVisible);
2677 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002678 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 + prev + ", waitingVisible="
2680 + (prev != null ? prev.waitingVisible : null)
2681 + ", nowVisible=" + next.nowVisible);
2682 }
2683 }
2684 }
2685
2686 // We are starting up the next activity, so tell the window manager
2687 // that the previous one will be hidden soon. This way it can know
2688 // to ignore it when computing the desired screen orientation.
2689 if (prev != null) {
2690 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002691 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002692 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002693 if (mNoAnimActivities.contains(prev)) {
2694 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2695 } else {
2696 mWindowManager.prepareAppTransition(prev.task == next.task
2697 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2698 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002700 mWindowManager.setAppWillBeHidden(prev);
2701 mWindowManager.setAppVisibility(prev, false);
2702 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002703 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002705 if (mNoAnimActivities.contains(next)) {
2706 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2707 } else {
2708 mWindowManager.prepareAppTransition(prev.task == next.task
2709 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2710 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2711 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 }
2713 if (false) {
2714 mWindowManager.setAppWillBeHidden(prev);
2715 mWindowManager.setAppVisibility(prev, false);
2716 }
2717 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002718 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002720 if (mNoAnimActivities.contains(next)) {
2721 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2722 } else {
2723 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002725 }
2726
2727 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002728 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002729
2730 // This activity is now becoming visible.
2731 mWindowManager.setAppVisibility(next, true);
2732
2733 HistoryRecord lastResumedActivity = mResumedActivity;
2734 ActivityState lastState = next.state;
2735
2736 updateCpuStats();
2737
2738 next.state = ActivityState.RESUMED;
2739 mResumedActivity = next;
2740 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002741 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 updateLRUListLocked(next);
2743
2744 // Have the window manager re-evaluate the orientation of
2745 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002746 boolean updated;
2747 synchronized (this) {
2748 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2749 mConfiguration,
2750 next.mayFreezeScreenLocked(next.app) ? next : null);
2751 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002752 next.frozenBeforeDestroy = true;
2753 }
2754 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002756 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002757 // The configuration update wasn't able to keep the existing
2758 // instance of the activity, and instead started a new one.
2759 // We should be all done, but let's just make sure our activity
2760 // is still at the top and schedule another run if something
2761 // weird happened.
2762 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002763 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002764 "Activity config changed during resume: " + next
2765 + ", new next: " + nextNext);
2766 if (nextNext != next) {
2767 // Do over!
2768 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2769 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002770 setFocusedActivityLocked(next);
2771 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002772 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002773 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002774 return true;
2775 }
2776
2777 try {
2778 // Deliver all pending results.
2779 ArrayList a = next.results;
2780 if (a != null) {
2781 final int N = a.size();
2782 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002783 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002784 TAG, "Delivering results to " + next
2785 + ": " + a);
2786 next.app.thread.scheduleSendResult(next, a);
2787 }
2788 }
2789
2790 if (next.newIntents != null) {
2791 next.app.thread.scheduleNewIntent(next.newIntents, next);
2792 }
2793
Doug Zongker2bec3d42009-12-04 12:52:44 -08002794 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 System.identityHashCode(next),
2796 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002797
2798 next.app.thread.scheduleResumeActivity(next,
2799 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002801 pauseIfSleepingLocked();
2802
2803 } catch (Exception e) {
2804 // Whoops, need to restart this activity!
2805 next.state = lastState;
2806 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002807 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 if (!next.hasBeenLaunched) {
2809 next.hasBeenLaunched = true;
2810 } else {
2811 if (SHOW_APP_STARTING_ICON) {
2812 mWindowManager.setAppStartingWindow(
2813 next, next.packageName, next.theme,
2814 next.nonLocalizedLabel,
2815 next.labelRes, next.icon, null, true);
2816 }
2817 }
2818 startSpecificActivityLocked(next, true, false);
2819 return true;
2820 }
2821
2822 // From this point on, if something goes wrong there is no way
2823 // to recover the activity.
2824 try {
2825 next.visible = true;
2826 completeResumeLocked(next);
2827 } catch (Exception e) {
2828 // If any exception gets thrown, toss away this
2829 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002830 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2832 "resume-exception");
2833 return true;
2834 }
2835
2836 // Didn't need to use the icicle, and it is now out of date.
2837 next.icicle = null;
2838 next.haveState = false;
2839 next.stopped = false;
2840
2841 } else {
2842 // Whoops, need to restart this activity!
2843 if (!next.hasBeenLaunched) {
2844 next.hasBeenLaunched = true;
2845 } else {
2846 if (SHOW_APP_STARTING_ICON) {
2847 mWindowManager.setAppStartingWindow(
2848 next, next.packageName, next.theme,
2849 next.nonLocalizedLabel,
2850 next.labelRes, next.icon, null, true);
2851 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002852 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002853 }
2854 startSpecificActivityLocked(next, true, true);
2855 }
2856
2857 return true;
2858 }
2859
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002860 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2861 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002862 final int NH = mHistory.size();
2863
2864 int addPos = -1;
2865
2866 if (!newTask) {
2867 // If starting in an existing task, find where that is...
2868 HistoryRecord next = null;
2869 boolean startIt = true;
2870 for (int i = NH-1; i >= 0; i--) {
2871 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2872 if (p.finishing) {
2873 continue;
2874 }
2875 if (p.task == r.task) {
2876 // Here it is! Now, if this is not yet visible to the
2877 // user, then just add it without starting; it will
2878 // get started when the user navigates back to it.
2879 addPos = i+1;
2880 if (!startIt) {
2881 mHistory.add(addPos, r);
2882 r.inHistory = true;
2883 r.task.numActivities++;
2884 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2885 r.info.screenOrientation, r.fullscreen);
2886 if (VALIDATE_TOKENS) {
2887 mWindowManager.validateAppTokens(mHistory);
2888 }
2889 return;
2890 }
2891 break;
2892 }
2893 if (p.fullscreen) {
2894 startIt = false;
2895 }
2896 next = p;
2897 }
2898 }
2899
2900 // Place a new activity at top of stack, so it is next to interact
2901 // with the user.
2902 if (addPos < 0) {
2903 addPos = mHistory.size();
2904 }
2905
2906 // If we are not placing the new activity frontmost, we do not want
2907 // to deliver the onUserLeaving callback to the actual frontmost
2908 // activity
2909 if (addPos < NH) {
2910 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002911 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 }
2913
2914 // Slot the activity into the history stack and proceed
2915 mHistory.add(addPos, r);
2916 r.inHistory = true;
2917 r.frontOfTask = newTask;
2918 r.task.numActivities++;
2919 if (NH > 0) {
2920 // We want to show the starting preview window if we are
2921 // switching to a new task, or the next activity's process is
2922 // not currently running.
2923 boolean showStartingIcon = newTask;
2924 ProcessRecord proc = r.app;
2925 if (proc == null) {
2926 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2927 }
2928 if (proc == null || proc.thread == null) {
2929 showStartingIcon = true;
2930 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002931 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002933 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2934 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2935 mNoAnimActivities.add(r);
2936 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2937 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2938 mNoAnimActivities.remove(r);
2939 } else {
2940 mWindowManager.prepareAppTransition(newTask
2941 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2942 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2943 mNoAnimActivities.remove(r);
2944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 mWindowManager.addAppToken(
2946 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2947 boolean doShow = true;
2948 if (newTask) {
2949 // Even though this activity is starting fresh, we still need
2950 // to reset it to make sure we apply affinities to move any
2951 // existing activities from other tasks in to it.
2952 // If the caller has requested that the target task be
2953 // reset, then do so.
2954 if ((r.intent.getFlags()
2955 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2956 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002957 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 }
2959 }
2960 if (SHOW_APP_STARTING_ICON && doShow) {
2961 // Figure out if we are transitioning from another activity that is
2962 // "has the same starting icon" as the next one. This allows the
2963 // window manager to keep the previous window it had previously
2964 // created, if it still had one.
2965 HistoryRecord prev = mResumedActivity;
2966 if (prev != null) {
2967 // We don't want to reuse the previous starting preview if:
2968 // (1) The current activity is in a different task.
2969 if (prev.task != r.task) prev = null;
2970 // (2) The current activity is already displayed.
2971 else if (prev.nowVisible) prev = null;
2972 }
2973 mWindowManager.setAppStartingWindow(
2974 r, r.packageName, r.theme, r.nonLocalizedLabel,
2975 r.labelRes, r.icon, prev, showStartingIcon);
2976 }
2977 } else {
2978 // If this is the first activity, don't do any fancy animations,
2979 // because there is nothing for it to animate on top of.
2980 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2981 r.info.screenOrientation, r.fullscreen);
2982 }
2983 if (VALIDATE_TOKENS) {
2984 mWindowManager.validateAppTokens(mHistory);
2985 }
2986
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002987 if (doResume) {
2988 resumeTopActivityLocked(null);
2989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 }
2991
2992 /**
2993 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002994 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2995 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 * an instance of that activity in the stack and, if found, finish all
2997 * activities on top of it and return the instance.
2998 *
2999 * @param newR Description of the new activity being started.
3000 * @return Returns the old activity that should be continue to be used,
3001 * or null if none was found.
3002 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003003 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003004 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003005 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003006
3007 // First find the requested task.
3008 while (i > 0) {
3009 i--;
3010 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3011 if (r.task.taskId == taskId) {
3012 i++;
3013 break;
3014 }
3015 }
3016
3017 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 while (i > 0) {
3019 i--;
3020 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3021 if (r.finishing) {
3022 continue;
3023 }
3024 if (r.task.taskId != taskId) {
3025 return null;
3026 }
3027 if (r.realActivity.equals(newR.realActivity)) {
3028 // Here it is! Now finish everything in front...
3029 HistoryRecord ret = r;
3030 if (doClear) {
3031 while (i < (mHistory.size()-1)) {
3032 i++;
3033 r = (HistoryRecord)mHistory.get(i);
3034 if (r.finishing) {
3035 continue;
3036 }
3037 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3038 null, "clear")) {
3039 i--;
3040 }
3041 }
3042 }
3043
3044 // Finally, if this is a normal launch mode (that is, not
3045 // expecting onNewIntent()), then we will finish the current
3046 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003047 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3048 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003050 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003052 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 null, "clear");
3054 }
3055 return null;
3056 }
3057 }
3058
3059 return ret;
3060 }
3061 }
3062
3063 return null;
3064 }
3065
3066 /**
3067 * Find the activity in the history stack within the given task. Returns
3068 * the index within the history at which it's found, or < 0 if not found.
3069 */
3070 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3071 int i = mHistory.size();
3072 while (i > 0) {
3073 i--;
3074 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3075 if (candidate.task.taskId != task) {
3076 break;
3077 }
3078 if (candidate.realActivity.equals(r.realActivity)) {
3079 return i;
3080 }
3081 }
3082
3083 return -1;
3084 }
3085
3086 /**
3087 * Reorder the history stack so that the activity at the given index is
3088 * brought to the front.
3089 */
3090 private final HistoryRecord moveActivityToFrontLocked(int where) {
3091 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3092 int top = mHistory.size();
3093 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3094 mHistory.add(top, newTop);
3095 oldTop.frontOfTask = false;
3096 newTop.frontOfTask = true;
3097 return newTop;
3098 }
3099
3100 /**
3101 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3102 * method will be called at the proper time.
3103 */
3104 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3105 boolean sent = false;
3106 if (r.state == ActivityState.RESUMED
3107 && r.app != null && r.app.thread != null) {
3108 try {
3109 ArrayList<Intent> ar = new ArrayList<Intent>();
3110 ar.add(new Intent(intent));
3111 r.app.thread.scheduleNewIntent(ar, r);
3112 sent = true;
3113 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003114 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 }
3116 }
3117 if (!sent) {
3118 r.addNewIntentLocked(new Intent(intent));
3119 }
3120 }
3121
3122 private final void logStartActivity(int tag, HistoryRecord r,
3123 TaskRecord task) {
3124 EventLog.writeEvent(tag,
3125 System.identityHashCode(r), task.taskId,
3126 r.shortComponentName, r.intent.getAction(),
3127 r.intent.getType(), r.intent.getDataString(),
3128 r.intent.getFlags());
3129 }
3130
3131 private final int startActivityLocked(IApplicationThread caller,
3132 Intent intent, String resolvedType,
3133 Uri[] grantedUriPermissions,
3134 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3135 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003136 int callingPid, int callingUid, boolean onlyIfNeeded,
3137 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003138 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003139
3140 HistoryRecord sourceRecord = null;
3141 HistoryRecord resultRecord = null;
3142 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003143 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003144 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3146 if (index >= 0) {
3147 sourceRecord = (HistoryRecord)mHistory.get(index);
3148 if (requestCode >= 0 && !sourceRecord.finishing) {
3149 resultRecord = sourceRecord;
3150 }
3151 }
3152 }
3153
3154 int launchFlags = intent.getFlags();
3155
3156 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3157 && sourceRecord != null) {
3158 // Transfer the result target from the source activity to the new
3159 // one being started, including any failures.
3160 if (requestCode >= 0) {
3161 return START_FORWARD_AND_REQUEST_CONFLICT;
3162 }
3163 resultRecord = sourceRecord.resultTo;
3164 resultWho = sourceRecord.resultWho;
3165 requestCode = sourceRecord.requestCode;
3166 sourceRecord.resultTo = null;
3167 if (resultRecord != null) {
3168 resultRecord.removeResultsLocked(
3169 sourceRecord, resultWho, requestCode);
3170 }
3171 }
3172
3173 int err = START_SUCCESS;
3174
3175 if (intent.getComponent() == null) {
3176 // We couldn't find a class that can handle the given Intent.
3177 // That's the end of that!
3178 err = START_INTENT_NOT_RESOLVED;
3179 }
3180
3181 if (err == START_SUCCESS && aInfo == null) {
3182 // We couldn't find the specific class specified in the Intent.
3183 // Also the end of the line.
3184 err = START_CLASS_NOT_FOUND;
3185 }
3186
3187 ProcessRecord callerApp = null;
3188 if (err == START_SUCCESS && caller != null) {
3189 callerApp = getRecordForAppLocked(caller);
3190 if (callerApp != null) {
3191 callingPid = callerApp.pid;
3192 callingUid = callerApp.info.uid;
3193 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003194 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 + " (pid=" + callingPid + ") when starting: "
3196 + intent.toString());
3197 err = START_PERMISSION_DENIED;
3198 }
3199 }
3200
3201 if (err != START_SUCCESS) {
3202 if (resultRecord != null) {
3203 sendActivityResultLocked(-1,
3204 resultRecord, resultWho, requestCode,
3205 Activity.RESULT_CANCELED, null);
3206 }
3207 return err;
3208 }
3209
3210 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3211 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3212 if (perm != PackageManager.PERMISSION_GRANTED) {
3213 if (resultRecord != null) {
3214 sendActivityResultLocked(-1,
3215 resultRecord, resultWho, requestCode,
3216 Activity.RESULT_CANCELED, null);
3217 }
3218 String msg = "Permission Denial: starting " + intent.toString()
3219 + " from " + callerApp + " (pid=" + callingPid
3220 + ", uid=" + callingUid + ")"
3221 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003222 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003223 throw new SecurityException(msg);
3224 }
3225
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003226 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003227 boolean abort = false;
3228 try {
3229 // The Intent we give to the watcher has the extra data
3230 // stripped off, since it can contain private information.
3231 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003232 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003233 aInfo.applicationInfo.packageName);
3234 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003235 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003236 }
3237
3238 if (abort) {
3239 if (resultRecord != null) {
3240 sendActivityResultLocked(-1,
3241 resultRecord, resultWho, requestCode,
3242 Activity.RESULT_CANCELED, null);
3243 }
3244 // We pretend to the caller that it was really started, but
3245 // they will just get a cancel result.
3246 return START_SUCCESS;
3247 }
3248 }
3249
3250 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3251 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003252 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003254 if (mResumedActivity == null
3255 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3256 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3257 PendingActivityLaunch pal = new PendingActivityLaunch();
3258 pal.r = r;
3259 pal.sourceRecord = sourceRecord;
3260 pal.grantedUriPermissions = grantedUriPermissions;
3261 pal.grantedMode = grantedMode;
3262 pal.onlyIfNeeded = onlyIfNeeded;
3263 mPendingActivityLaunches.add(pal);
3264 return START_SWITCHES_CANCELED;
3265 }
3266 }
3267
3268 if (mDidAppSwitch) {
3269 // This is the second allowed switch since we stopped switches,
3270 // so now just generally allow switches. Use case: user presses
3271 // home (switches disabled, switch to home, mDidAppSwitch now true);
3272 // user taps a home icon (coming from home so allowed, we hit here
3273 // and now allow anyone to switch again).
3274 mAppSwitchesAllowedTime = 0;
3275 } else {
3276 mDidAppSwitch = true;
3277 }
3278
3279 doPendingActivityLaunchesLocked(false);
3280
3281 return startActivityUncheckedLocked(r, sourceRecord,
3282 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3283 }
3284
3285 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3286 final int N = mPendingActivityLaunches.size();
3287 if (N <= 0) {
3288 return;
3289 }
3290 for (int i=0; i<N; i++) {
3291 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3292 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3293 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3294 doResume && i == (N-1));
3295 }
3296 mPendingActivityLaunches.clear();
3297 }
3298
3299 private final int startActivityUncheckedLocked(HistoryRecord r,
3300 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3301 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3302 final Intent intent = r.intent;
3303 final int callingUid = r.launchedFromUid;
3304
3305 int launchFlags = intent.getFlags();
3306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003307 // We'll invoke onUserLeaving before onPause only if the launching
3308 // activity did not explicitly state that this is an automated launch.
3309 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003310 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 "startActivity() => mUserLeaving=" + mUserLeaving);
3312
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003313 // If the caller has asked not to resume at this point, we make note
3314 // of this in the record so that we can skip it when trying to find
3315 // the top running activity.
3316 if (!doResume) {
3317 r.delayedResume = true;
3318 }
3319
3320 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3321 != 0 ? r : null;
3322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 // If the onlyIfNeeded flag is set, then we can do this if the activity
3324 // being launched is the same as the one making the call... or, as
3325 // a special case, if we do not know the caller then we count the
3326 // current top activity as the caller.
3327 if (onlyIfNeeded) {
3328 HistoryRecord checkedCaller = sourceRecord;
3329 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003330 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003331 }
3332 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3333 // Caller is not the same as launcher, so always needed.
3334 onlyIfNeeded = false;
3335 }
3336 }
3337
3338 if (grantedUriPermissions != null && callingUid > 0) {
3339 for (int i=0; i<grantedUriPermissions.length; i++) {
3340 grantUriPermissionLocked(callingUid, r.packageName,
3341 grantedUriPermissions[i], grantedMode, r);
3342 }
3343 }
3344
3345 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3346 intent, r);
3347
3348 if (sourceRecord == null) {
3349 // This activity is not being started from another... in this
3350 // case we -always- start a new task.
3351 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003352 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 -08003353 + intent);
3354 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3355 }
3356 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3357 // The original activity who is starting us is running as a single
3358 // instance... this new activity it is starting must go on its
3359 // own task.
3360 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3361 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3362 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3363 // The activity being started is a single instance... it always
3364 // gets launched into its own task.
3365 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3366 }
3367
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003368 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003369 // For whatever reason this activity is being launched into a new
3370 // task... yet the caller has requested a result back. Well, that
3371 // is pretty messed up, so instead immediately send back a cancel
3372 // and let the new task continue launched as normal without a
3373 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003374 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003375 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003376 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 Activity.RESULT_CANCELED, null);
3378 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379 }
3380
3381 boolean addingToTask = false;
3382 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3383 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3384 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3385 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3386 // If bring to front is requested, and no result is requested, and
3387 // we can find a task that was started with this same
3388 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003389 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003390 // See if there is a task to bring to the front. If this is
3391 // a SINGLE_INSTANCE activity, there can be one and only one
3392 // instance of it in the history, and it is always in its own
3393 // unique task, so we do a special search.
3394 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3395 ? findTaskLocked(intent, r.info)
3396 : findActivityLocked(intent, r.info);
3397 if (taskTop != null) {
3398 if (taskTop.task.intent == null) {
3399 // This task was started because of movement of
3400 // the activity based on affinity... now that we
3401 // are actually launching it, we can assign the
3402 // base intent.
3403 taskTop.task.setIntent(intent, r.info);
3404 }
3405 // If the target task is not in the front, then we need
3406 // to bring it to the front... except... well, with
3407 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3408 // to have the same behavior as if a new instance was
3409 // being started, which means not bringing it to the front
3410 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003411 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 if (curTop.task != taskTop.task) {
3413 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3414 boolean callerAtFront = sourceRecord == null
3415 || curTop.task == sourceRecord.task;
3416 if (callerAtFront) {
3417 // We really do want to push this one into the
3418 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003419 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420 }
3421 }
3422 // If the caller has requested that the target task be
3423 // reset, then do so.
3424 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3425 taskTop = resetTaskIfNeededLocked(taskTop, r);
3426 }
3427 if (onlyIfNeeded) {
3428 // We don't need to start a new activity, and
3429 // the client said not to do anything if that
3430 // is the case, so this is it! And for paranoia, make
3431 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003432 if (doResume) {
3433 resumeTopActivityLocked(null);
3434 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 return START_RETURN_INTENT_TO_CALLER;
3436 }
3437 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3438 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3439 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3440 // In this situation we want to remove all activities
3441 // from the task up to the one being started. In most
3442 // cases this means we are resetting the task to its
3443 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003444 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003445 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003446 if (top != null) {
3447 if (top.frontOfTask) {
3448 // Activity aliases may mean we use different
3449 // intents for the top activity, so make sure
3450 // the task now has the identity of the new
3451 // intent.
3452 top.task.setIntent(r.intent, r.info);
3453 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003454 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 deliverNewIntentLocked(top, r.intent);
3456 } else {
3457 // A special case: we need to
3458 // start the activity because it is not currently
3459 // running, and the caller has asked to clear the
3460 // current task to have this activity at the top.
3461 addingToTask = true;
3462 // Now pretend like this activity is being started
3463 // by the top of its task, so it is put in the
3464 // right place.
3465 sourceRecord = taskTop;
3466 }
3467 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3468 // In this case the top activity on the task is the
3469 // same as the one being launched, so we take that
3470 // as a request to bring the task to the foreground.
3471 // If the top activity in the task is the root
3472 // activity, deliver this new intent to it if it
3473 // desires.
3474 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3475 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003476 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477 if (taskTop.frontOfTask) {
3478 taskTop.task.setIntent(r.intent, r.info);
3479 }
3480 deliverNewIntentLocked(taskTop, r.intent);
3481 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3482 // In this case we are launching the root activity
3483 // of the task, but with a different intent. We
3484 // should start a new instance on top.
3485 addingToTask = true;
3486 sourceRecord = taskTop;
3487 }
3488 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3489 // In this case an activity is being launched in to an
3490 // existing task, without resetting that task. This
3491 // is typically the situation of launching an activity
3492 // from a notification or shortcut. We want to place
3493 // the new activity on top of the current task.
3494 addingToTask = true;
3495 sourceRecord = taskTop;
3496 } else if (!taskTop.task.rootWasReset) {
3497 // In this case we are launching in to an existing task
3498 // that has not yet been started from its front door.
3499 // The current task has been brought to the front.
3500 // Ideally, we'd probably like to place this new task
3501 // at the bottom of its stack, but that's a little hard
3502 // to do with the current organization of the code so
3503 // for now we'll just drop it.
3504 taskTop.task.setIntent(r.intent, r.info);
3505 }
3506 if (!addingToTask) {
3507 // We didn't do anything... but it was needed (a.k.a., client
3508 // don't use that intent!) And for paranoia, make
3509 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003510 if (doResume) {
3511 resumeTopActivityLocked(null);
3512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 return START_TASK_TO_FRONT;
3514 }
3515 }
3516 }
3517 }
3518
3519 //String uri = r.intent.toURI();
3520 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003521 //Slog.i(TAG, "Given intent: " + r.intent);
3522 //Slog.i(TAG, "URI is: " + uri);
3523 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524
3525 if (r.packageName != null) {
3526 // If the activity being launched is the same as the one currently
3527 // at the top, then we need to check if it should only be launched
3528 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003529 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3530 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531 if (top.realActivity.equals(r.realActivity)) {
3532 if (top.app != null && top.app.thread != null) {
3533 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3534 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3535 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003536 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 // For paranoia, make sure we have correctly
3538 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003539 if (doResume) {
3540 resumeTopActivityLocked(null);
3541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 if (onlyIfNeeded) {
3543 // We don't need to start a new activity, and
3544 // the client said not to do anything if that
3545 // is the case, so this is it!
3546 return START_RETURN_INTENT_TO_CALLER;
3547 }
3548 deliverNewIntentLocked(top, r.intent);
3549 return START_DELIVERED_TO_TOP;
3550 }
3551 }
3552 }
3553 }
3554
3555 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003556 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003558 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 Activity.RESULT_CANCELED, null);
3560 }
3561 return START_CLASS_NOT_FOUND;
3562 }
3563
3564 boolean newTask = false;
3565
3566 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003567 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3569 // todo: should do better management of integers.
3570 mCurTask++;
3571 if (mCurTask <= 0) {
3572 mCurTask = 1;
3573 }
3574 r.task = new TaskRecord(mCurTask, r.info, intent,
3575 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003576 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 + " in new task " + r.task);
3578 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003579 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580
3581 } else if (sourceRecord != null) {
3582 if (!addingToTask &&
3583 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3584 // In this case, we are adding the activity to an existing
3585 // task, but the caller has asked to clear that task if the
3586 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003587 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003588 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003590 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 deliverNewIntentLocked(top, r.intent);
3592 // For paranoia, make sure we have correctly
3593 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003594 if (doResume) {
3595 resumeTopActivityLocked(null);
3596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003597 return START_DELIVERED_TO_TOP;
3598 }
3599 } else if (!addingToTask &&
3600 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3601 // In this case, we are launching an activity in our own task
3602 // that may already be running somewhere in the history, and
3603 // we want to shuffle it to the front of the stack if so.
3604 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3605 if (where >= 0) {
3606 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003607 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003609 if (doResume) {
3610 resumeTopActivityLocked(null);
3611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003612 return START_DELIVERED_TO_TOP;
3613 }
3614 }
3615 // An existing activity is starting this new activity, so we want
3616 // to keep the new one in the same task as the one that is starting
3617 // it.
3618 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003619 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 + " in existing task " + r.task);
3621
3622 } else {
3623 // This not being started from an existing activity, and not part
3624 // of a new task... just put it in the top task, though these days
3625 // this case should never happen.
3626 final int N = mHistory.size();
3627 HistoryRecord prev =
3628 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3629 r.task = prev != null
3630 ? prev.task
3631 : new TaskRecord(mCurTask, r.info, intent,
3632 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003633 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 + " in new guessed " + r.task);
3635 }
3636 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003637 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003639 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003640 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 return START_SUCCESS;
3642 }
3643
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003644 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3645 long thisTime, long totalTime) {
3646 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3647 WaitResult w = mWaitingActivityLaunched.get(i);
3648 w.timeout = timeout;
3649 if (r != null) {
3650 w.who = new ComponentName(r.info.packageName, r.info.name);
3651 }
3652 w.thisTime = thisTime;
3653 w.totalTime = totalTime;
3654 }
3655 notify();
3656 }
3657
3658 void reportActivityVisibleLocked(HistoryRecord r) {
3659 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3660 WaitResult w = mWaitingActivityVisible.get(i);
3661 w.timeout = false;
3662 if (r != null) {
3663 w.who = new ComponentName(r.info.packageName, r.info.name);
3664 }
3665 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3666 w.thisTime = w.totalTime;
3667 }
3668 notify();
3669 }
3670
3671 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3673 int grantedMode, IBinder resultTo,
3674 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003675 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 // Refuse possible leaked file descriptors
3677 if (intent != null && intent.hasFileDescriptors()) {
3678 throw new IllegalArgumentException("File descriptors passed in Intent");
3679 }
3680
The Android Open Source Project4df24232009-03-05 14:34:35 -08003681 final boolean componentSpecified = intent.getComponent() != null;
3682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 // Don't modify the client's object!
3684 intent = new Intent(intent);
3685
3686 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003687 ActivityInfo aInfo;
3688 try {
3689 ResolveInfo rInfo =
3690 ActivityThread.getPackageManager().resolveIntent(
3691 intent, resolvedType,
3692 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003693 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 aInfo = rInfo != null ? rInfo.activityInfo : null;
3695 } catch (RemoteException e) {
3696 aInfo = null;
3697 }
3698
3699 if (aInfo != null) {
3700 // Store the found target back into the intent, because now that
3701 // we have it we never want to do this again. For example, if the
3702 // user navigates back to this point in the history, we should
3703 // always restart the exact same activity.
3704 intent.setComponent(new ComponentName(
3705 aInfo.applicationInfo.packageName, aInfo.name));
3706
3707 // Don't debug things in the system process
3708 if (debug) {
3709 if (!aInfo.processName.equals("system")) {
3710 setDebugApp(aInfo.processName, true, false);
3711 }
3712 }
3713 }
3714
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003715 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003716 int callingPid;
3717 int callingUid;
3718 if (caller == null) {
3719 callingPid = Binder.getCallingPid();
3720 callingUid = Binder.getCallingUid();
3721 } else {
3722 callingPid = callingUid = -1;
3723 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003724
3725 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003726 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3727 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003731 int res = startActivityLocked(caller, intent, resolvedType,
3732 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003733 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003734 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003735
Dianne Hackborne2522462010-03-29 18:41:30 -07003736 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003737 // If the caller also wants to switch to a new configuration,
3738 // do so now. This allows a clean switch, as we are waiting
3739 // for the current activity to pause (so we will not destroy
3740 // it), and have not yet started the next activity.
3741 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3742 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003743 mConfigWillChange = false;
3744 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3745 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003746 updateConfigurationLocked(config, null);
3747 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003749 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003750
3751 if (outResult != null) {
3752 outResult.result = res;
3753 if (res == IActivityManager.START_SUCCESS) {
3754 mWaitingActivityLaunched.add(outResult);
3755 do {
3756 try {
3757 wait();
3758 } catch (InterruptedException e) {
3759 }
3760 } while (!outResult.timeout && outResult.who == null);
3761 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3762 HistoryRecord r = this.topRunningActivityLocked(null);
3763 if (r.nowVisible) {
3764 outResult.timeout = false;
3765 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3766 outResult.totalTime = 0;
3767 outResult.thisTime = 0;
3768 } else {
3769 outResult.thisTime = SystemClock.uptimeMillis();
3770 mWaitingActivityVisible.add(outResult);
3771 do {
3772 try {
3773 wait();
3774 } catch (InterruptedException e) {
3775 }
3776 } while (!outResult.timeout && outResult.who == null);
3777 }
3778 }
3779 }
3780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781 return res;
3782 }
3783 }
3784
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003785 public final int startActivity(IApplicationThread caller,
3786 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3787 int grantedMode, IBinder resultTo,
3788 String resultWho, int requestCode, boolean onlyIfNeeded,
3789 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003790 return startActivityMayWait(caller, intent, resolvedType,
3791 grantedUriPermissions, grantedMode, resultTo, resultWho,
3792 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003793 }
3794
3795 public final WaitResult startActivityAndWait(IApplicationThread caller,
3796 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3797 int grantedMode, IBinder resultTo,
3798 String resultWho, int requestCode, boolean onlyIfNeeded,
3799 boolean debug) {
3800 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003801 startActivityMayWait(caller, intent, resolvedType,
3802 grantedUriPermissions, grantedMode, resultTo, resultWho,
3803 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003804 return res;
3805 }
3806
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003807 public final int startActivityWithConfig(IApplicationThread caller,
3808 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3809 int grantedMode, IBinder resultTo,
3810 String resultWho, int requestCode, boolean onlyIfNeeded,
3811 boolean debug, Configuration config) {
3812 return startActivityMayWait(caller, intent, resolvedType,
3813 grantedUriPermissions, grantedMode, resultTo, resultWho,
3814 requestCode, onlyIfNeeded, debug, null, config);
3815 }
3816
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003817 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003818 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003819 IBinder resultTo, String resultWho, int requestCode,
3820 int flagsMask, int flagsValues) {
3821 // Refuse possible leaked file descriptors
3822 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3823 throw new IllegalArgumentException("File descriptors passed in Intent");
3824 }
3825
3826 IIntentSender sender = intent.getTarget();
3827 if (!(sender instanceof PendingIntentRecord)) {
3828 throw new IllegalArgumentException("Bad PendingIntent object");
3829 }
3830
3831 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003832
3833 synchronized (this) {
3834 // If this is coming from the currently resumed activity, it is
3835 // effectively saying that app switches are allowed at this point.
3836 if (mResumedActivity != null
3837 && mResumedActivity.info.applicationInfo.uid ==
3838 Binder.getCallingUid()) {
3839 mAppSwitchesAllowedTime = 0;
3840 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003841 }
3842
3843 return pir.sendInner(0, fillInIntent, resolvedType,
3844 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3845 }
3846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003847 public boolean startNextMatchingActivity(IBinder callingActivity,
3848 Intent intent) {
3849 // Refuse possible leaked file descriptors
3850 if (intent != null && intent.hasFileDescriptors() == true) {
3851 throw new IllegalArgumentException("File descriptors passed in Intent");
3852 }
3853
3854 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003855 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 if (index < 0) {
3857 return false;
3858 }
3859 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3860 if (r.app == null || r.app.thread == null) {
3861 // The caller is not running... d'oh!
3862 return false;
3863 }
3864 intent = new Intent(intent);
3865 // The caller is not allowed to change the data.
3866 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3867 // And we are resetting to find the next component...
3868 intent.setComponent(null);
3869
3870 ActivityInfo aInfo = null;
3871 try {
3872 List<ResolveInfo> resolves =
3873 ActivityThread.getPackageManager().queryIntentActivities(
3874 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003875 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003876
3877 // Look for the original activity in the list...
3878 final int N = resolves != null ? resolves.size() : 0;
3879 for (int i=0; i<N; i++) {
3880 ResolveInfo rInfo = resolves.get(i);
3881 if (rInfo.activityInfo.packageName.equals(r.packageName)
3882 && rInfo.activityInfo.name.equals(r.info.name)) {
3883 // We found the current one... the next matching is
3884 // after it.
3885 i++;
3886 if (i<N) {
3887 aInfo = resolves.get(i).activityInfo;
3888 }
3889 break;
3890 }
3891 }
3892 } catch (RemoteException e) {
3893 }
3894
3895 if (aInfo == null) {
3896 // Nobody who is next!
3897 return false;
3898 }
3899
3900 intent.setComponent(new ComponentName(
3901 aInfo.applicationInfo.packageName, aInfo.name));
3902 intent.setFlags(intent.getFlags()&~(
3903 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3904 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3905 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3906 Intent.FLAG_ACTIVITY_NEW_TASK));
3907
3908 // Okay now we need to start the new activity, replacing the
3909 // currently running activity. This is a little tricky because
3910 // we want to start the new one as if the current one is finished,
3911 // but not finish the current one first so that there is no flicker.
3912 // And thus...
3913 final boolean wasFinishing = r.finishing;
3914 r.finishing = true;
3915
3916 // Propagate reply information over to the new activity.
3917 final HistoryRecord resultTo = r.resultTo;
3918 final String resultWho = r.resultWho;
3919 final int requestCode = r.requestCode;
3920 r.resultTo = null;
3921 if (resultTo != null) {
3922 resultTo.removeResultsLocked(r, resultWho, requestCode);
3923 }
3924
3925 final long origId = Binder.clearCallingIdentity();
3926 // XXX we are not dealing with propagating grantedUriPermissions...
3927 // those are not yet exposed to user code, so there is no need.
3928 int res = startActivityLocked(r.app.thread, intent,
3929 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003930 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003931 Binder.restoreCallingIdentity(origId);
3932
3933 r.finishing = wasFinishing;
3934 if (res != START_SUCCESS) {
3935 return false;
3936 }
3937 return true;
3938 }
3939 }
3940
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003941 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 Intent intent, String resolvedType, IBinder resultTo,
3943 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003944
3945 // This is so super not safe, that only the system (or okay root)
3946 // can do it.
3947 final int callingUid = Binder.getCallingUid();
3948 if (callingUid != 0 && callingUid != Process.myUid()) {
3949 throw new SecurityException(
3950 "startActivityInPackage only available to the system");
3951 }
3952
The Android Open Source Project4df24232009-03-05 14:34:35 -08003953 final boolean componentSpecified = intent.getComponent() != null;
3954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 // Don't modify the client's object!
3956 intent = new Intent(intent);
3957
3958 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003959 ActivityInfo aInfo;
3960 try {
3961 ResolveInfo rInfo =
3962 ActivityThread.getPackageManager().resolveIntent(
3963 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003964 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965 aInfo = rInfo != null ? rInfo.activityInfo : null;
3966 } catch (RemoteException e) {
3967 aInfo = null;
3968 }
3969
3970 if (aInfo != null) {
3971 // Store the found target back into the intent, because now that
3972 // we have it we never want to do this again. For example, if the
3973 // user navigates back to this point in the history, we should
3974 // always restart the exact same activity.
3975 intent.setComponent(new ComponentName(
3976 aInfo.applicationInfo.packageName, aInfo.name));
3977 }
3978
3979 synchronized(this) {
3980 return startActivityLocked(null, intent, resolvedType,
3981 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003982 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 }
3984 }
3985
Josh Bartel7f208742010-02-25 11:01:44 -06003986 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003987 // Remove any existing entries that are the same kind of task.
3988 int N = mRecentTasks.size();
3989 for (int i=0; i<N; i++) {
3990 TaskRecord tr = mRecentTasks.get(i);
3991 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3992 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3993 mRecentTasks.remove(i);
3994 i--;
3995 N--;
3996 if (task.intent == null) {
3997 // If the new recent task we are adding is not fully
3998 // specified, then replace it with the existing recent task.
3999 task = tr;
4000 }
4001 }
4002 }
4003 if (N >= MAX_RECENT_TASKS) {
4004 mRecentTasks.remove(N-1);
4005 }
4006 mRecentTasks.add(0, task);
4007 }
4008
4009 public void setRequestedOrientation(IBinder token,
4010 int requestedOrientation) {
4011 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004012 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004013 if (index < 0) {
4014 return;
4015 }
4016 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4017 final long origId = Binder.clearCallingIdentity();
4018 mWindowManager.setAppOrientation(r, requestedOrientation);
4019 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07004020 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 r.mayFreezeScreenLocked(r.app) ? r : null);
4022 if (config != null) {
4023 r.frozenBeforeDestroy = true;
4024 if (!updateConfigurationLocked(config, r)) {
4025 resumeTopActivityLocked(null);
4026 }
4027 }
4028 Binder.restoreCallingIdentity(origId);
4029 }
4030 }
4031
4032 public int getRequestedOrientation(IBinder token) {
4033 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004034 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035 if (index < 0) {
4036 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4037 }
4038 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4039 return mWindowManager.getAppOrientation(r);
4040 }
4041 }
4042
4043 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004044 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004045 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4046 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4047 if (!r.finishing) {
4048 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4049 "no-history");
4050 }
4051 } else if (r.app != null && r.app.thread != null) {
4052 if (mFocusedActivity == r) {
4053 setFocusedActivityLocked(topRunningActivityLocked(null));
4054 }
4055 r.resumeKeyDispatchingLocked();
4056 try {
4057 r.stopped = false;
4058 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004059 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060 TAG, "Stopping visible=" + r.visible + " for " + r);
4061 if (!r.visible) {
4062 mWindowManager.setAppVisibility(r, false);
4063 }
4064 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4065 } catch (Exception e) {
4066 // Maybe just ignore exceptions here... if the process
4067 // has crashed, our death notification will clean things
4068 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004069 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070 // Just in case, assume it to be stopped.
4071 r.stopped = true;
4072 r.state = ActivityState.STOPPED;
4073 if (r.configDestroy) {
4074 destroyActivityLocked(r, true);
4075 }
4076 }
4077 }
4078 }
4079
4080 /**
4081 * @return Returns true if the activity is being finished, false if for
4082 * some reason it is being left as-is.
4083 */
4084 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4085 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004086 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087 TAG, "Finishing activity: token=" + token
4088 + ", result=" + resultCode + ", data=" + resultData);
4089
Dianne Hackborn75b03852009-06-12 15:43:26 -07004090 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 if (index < 0) {
4092 return false;
4093 }
4094 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4095
4096 // Is this the last activity left?
4097 boolean lastActivity = true;
4098 for (int i=mHistory.size()-1; i>=0; i--) {
4099 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4100 if (!p.finishing && p != r) {
4101 lastActivity = false;
4102 break;
4103 }
4104 }
4105
4106 // If this is the last activity, but it is the home activity, then
4107 // just don't finish it.
4108 if (lastActivity) {
4109 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4110 return false;
4111 }
4112 }
4113
4114 finishActivityLocked(r, index, resultCode, resultData, reason);
4115 return true;
4116 }
4117
4118 /**
4119 * @return Returns true if this activity has been removed from the history
4120 * list, or false if it is still in the list and will be removed later.
4121 */
4122 private final boolean finishActivityLocked(HistoryRecord r, int index,
4123 int resultCode, Intent resultData, String reason) {
4124 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004125 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004126 return false;
4127 }
4128
4129 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004130 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131 System.identityHashCode(r),
4132 r.task.taskId, r.shortComponentName, reason);
4133 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004134 if (index < (mHistory.size()-1)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004135 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4136 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004137 if (r.frontOfTask) {
4138 // The next activity is now the front of the task.
4139 next.frontOfTask = true;
4140 }
4141 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4142 // If the caller asked that this activity (and all above it)
4143 // be cleared when the task is reset, don't lose that information,
4144 // but propagate it up to the next activity.
4145 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4146 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004147 }
4148 }
4149
4150 r.pauseKeyDispatchingLocked();
4151 if (mFocusedActivity == r) {
4152 setFocusedActivityLocked(topRunningActivityLocked(null));
4153 }
4154
4155 // send the result
4156 HistoryRecord resultTo = r.resultTo;
4157 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004158 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004159 + " who=" + r.resultWho + " req=" + r.requestCode
4160 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 if (r.info.applicationInfo.uid > 0) {
4162 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4163 r.packageName, resultData, r);
4164 }
4165 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4166 resultData);
4167 r.resultTo = null;
4168 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004169 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170
4171 // Make sure this HistoryRecord is not holding on to other resources,
4172 // because clients have remote IPC references to this object so we
4173 // can't assume that will go away and want to avoid circular IPC refs.
4174 r.results = null;
4175 r.pendingResults = null;
4176 r.newIntents = null;
4177 r.icicle = null;
4178
4179 if (mPendingThumbnails.size() > 0) {
4180 // There are clients waiting to receive thumbnails so, in case
4181 // this is an activity that someone is waiting for, add it
4182 // to the pending list so we can correctly update the clients.
4183 mCancelledThumbnails.add(r);
4184 }
4185
4186 if (mResumedActivity == r) {
4187 boolean endTask = index <= 0
4188 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004189 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 "Prepare close transition: finishing " + r);
4191 mWindowManager.prepareAppTransition(endTask
4192 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4193 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4194
4195 // Tell window manager to prepare for this one to be removed.
4196 mWindowManager.setAppVisibility(r, false);
4197
4198 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004199 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4200 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004201 startPausingLocked(false, false);
4202 }
4203
4204 } else if (r.state != ActivityState.PAUSING) {
4205 // If the activity is PAUSING, we will complete the finish once
4206 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004207 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004208 return finishCurrentActivityLocked(r, index,
4209 FINISH_AFTER_PAUSE) == null;
4210 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004211 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004212 }
4213
4214 return false;
4215 }
4216
4217 private static final int FINISH_IMMEDIATELY = 0;
4218 private static final int FINISH_AFTER_PAUSE = 1;
4219 private static final int FINISH_AFTER_VISIBLE = 2;
4220
4221 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4222 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004223 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 if (index < 0) {
4225 return null;
4226 }
4227
4228 return finishCurrentActivityLocked(r, index, mode);
4229 }
4230
4231 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4232 int index, int mode) {
4233 // First things first: if this activity is currently visible,
4234 // and the resumed activity is not yet visible, then hold off on
4235 // finishing until the resumed one becomes visible.
4236 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4237 if (!mStoppingActivities.contains(r)) {
4238 mStoppingActivities.add(r);
4239 if (mStoppingActivities.size() > 3) {
4240 // If we already have a few activities waiting to stop,
4241 // then give up on things going idle and start clearing
4242 // them out.
4243 Message msg = Message.obtain();
4244 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4245 mHandler.sendMessage(msg);
4246 }
4247 }
4248 r.state = ActivityState.STOPPING;
4249 updateOomAdjLocked();
4250 return r;
4251 }
4252
4253 // make sure the record is cleaned out of other places.
4254 mStoppingActivities.remove(r);
4255 mWaitingVisibleActivities.remove(r);
4256 if (mResumedActivity == r) {
4257 mResumedActivity = null;
4258 }
4259 final ActivityState prevState = r.state;
4260 r.state = ActivityState.FINISHING;
4261
4262 if (mode == FINISH_IMMEDIATELY
4263 || prevState == ActivityState.STOPPED
4264 || prevState == ActivityState.INITIALIZING) {
4265 // If this activity is already stopped, we can just finish
4266 // it right now.
4267 return destroyActivityLocked(r, true) ? null : r;
4268 } else {
4269 // Need to go through the full pause cycle to get this
4270 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004271 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 mFinishingActivities.add(r);
4273 resumeTopActivityLocked(null);
4274 }
4275 return r;
4276 }
4277
4278 /**
4279 * This is the internal entry point for handling Activity.finish().
4280 *
4281 * @param token The Binder token referencing the Activity we want to finish.
4282 * @param resultCode Result code, if any, from this Activity.
4283 * @param resultData Result data (Intent), if any, from this Activity.
4284 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004285 * @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 -08004286 */
4287 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4288 // Refuse possible leaked file descriptors
4289 if (resultData != null && resultData.hasFileDescriptors() == true) {
4290 throw new IllegalArgumentException("File descriptors passed in Intent");
4291 }
4292
4293 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004294 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 // Find the first activity that is not finishing.
4296 HistoryRecord next = topRunningActivityLocked(token, 0);
4297 if (next != null) {
4298 // ask watcher if this is allowed
4299 boolean resumeOK = true;
4300 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004301 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004303 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 }
4305
4306 if (!resumeOK) {
4307 return false;
4308 }
4309 }
4310 }
4311 final long origId = Binder.clearCallingIdentity();
4312 boolean res = requestFinishActivityLocked(token, resultCode,
4313 resultData, "app-request");
4314 Binder.restoreCallingIdentity(origId);
4315 return res;
4316 }
4317 }
4318
4319 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4320 String resultWho, int requestCode, int resultCode, Intent data) {
4321
4322 if (callingUid > 0) {
4323 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4324 data, r);
4325 }
4326
Joe Onorato8a9b2202010-02-26 18:56:32 -08004327 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004328 + " : who=" + resultWho + " req=" + requestCode
4329 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004330 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4331 try {
4332 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4333 list.add(new ResultInfo(resultWho, requestCode,
4334 resultCode, data));
4335 r.app.thread.scheduleSendResult(r, list);
4336 return;
4337 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004338 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 }
4340 }
4341
4342 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4343 }
4344
4345 public final void finishSubActivity(IBinder token, String resultWho,
4346 int requestCode) {
4347 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004348 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 if (index < 0) {
4350 return;
4351 }
4352 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4353
4354 final long origId = Binder.clearCallingIdentity();
4355
4356 int i;
4357 for (i=mHistory.size()-1; i>=0; i--) {
4358 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4359 if (r.resultTo == self && r.requestCode == requestCode) {
4360 if ((r.resultWho == null && resultWho == null) ||
4361 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4362 finishActivityLocked(r, i,
4363 Activity.RESULT_CANCELED, null, "request-sub");
4364 }
4365 }
4366 }
4367
4368 Binder.restoreCallingIdentity(origId);
4369 }
4370 }
4371
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004372 public boolean willActivityBeVisible(IBinder token) {
4373 synchronized(this) {
4374 int i;
4375 for (i=mHistory.size()-1; i>=0; i--) {
4376 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4377 if (r == token) {
4378 return true;
4379 }
4380 if (r.fullscreen && !r.finishing) {
4381 return false;
4382 }
4383 }
4384 return true;
4385 }
4386 }
4387
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004388 public void overridePendingTransition(IBinder token, String packageName,
4389 int enterAnim, int exitAnim) {
4390 synchronized(this) {
4391 int index = indexOfTokenLocked(token);
4392 if (index < 0) {
4393 return;
4394 }
4395 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4396
4397 final long origId = Binder.clearCallingIdentity();
4398
4399 if (self.state == ActivityState.RESUMED
4400 || self.state == ActivityState.PAUSING) {
4401 mWindowManager.overridePendingAppTransition(packageName,
4402 enterAnim, exitAnim);
4403 }
4404
4405 Binder.restoreCallingIdentity(origId);
4406 }
4407 }
4408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004409 /**
4410 * Perform clean-up of service connections in an activity record.
4411 */
4412 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4413 // Throw away any services that have been bound by this activity.
4414 if (r.connections != null) {
4415 Iterator<ConnectionRecord> it = r.connections.iterator();
4416 while (it.hasNext()) {
4417 ConnectionRecord c = it.next();
4418 removeConnectionLocked(c, null, r);
4419 }
4420 r.connections = null;
4421 }
4422 }
4423
4424 /**
4425 * Perform the common clean-up of an activity record. This is called both
4426 * as part of destroyActivityLocked() (when destroying the client-side
4427 * representation) and cleaning things up as a result of its hosting
4428 * processing going away, in which case there is no remaining client-side
4429 * state to destroy so only the cleanup here is needed.
4430 */
4431 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4432 if (mResumedActivity == r) {
4433 mResumedActivity = null;
4434 }
4435 if (mFocusedActivity == r) {
4436 mFocusedActivity = null;
4437 }
4438
4439 r.configDestroy = false;
4440 r.frozenBeforeDestroy = false;
4441
4442 // Make sure this record is no longer in the pending finishes list.
4443 // This could happen, for example, if we are trimming activities
4444 // down to the max limit while they are still waiting to finish.
4445 mFinishingActivities.remove(r);
4446 mWaitingVisibleActivities.remove(r);
4447
4448 // Remove any pending results.
4449 if (r.finishing && r.pendingResults != null) {
4450 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4451 PendingIntentRecord rec = apr.get();
4452 if (rec != null) {
4453 cancelIntentSenderLocked(rec, false);
4454 }
4455 }
4456 r.pendingResults = null;
4457 }
4458
4459 if (cleanServices) {
4460 cleanUpActivityServicesLocked(r);
4461 }
4462
4463 if (mPendingThumbnails.size() > 0) {
4464 // There are clients waiting to receive thumbnails so, in case
4465 // this is an activity that someone is waiting for, add it
4466 // to the pending list so we can correctly update the clients.
4467 mCancelledThumbnails.add(r);
4468 }
4469
4470 // Get rid of any pending idle timeouts.
4471 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4472 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4473 }
4474
4475 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4476 if (r.state != ActivityState.DESTROYED) {
4477 mHistory.remove(r);
4478 r.inHistory = false;
4479 r.state = ActivityState.DESTROYED;
4480 mWindowManager.removeAppToken(r);
4481 if (VALIDATE_TOKENS) {
4482 mWindowManager.validateAppTokens(mHistory);
4483 }
4484 cleanUpActivityServicesLocked(r);
4485 removeActivityUriPermissionsLocked(r);
4486 }
4487 }
4488
4489 /**
4490 * Destroy the current CLIENT SIDE instance of an activity. This may be
4491 * called both when actually finishing an activity, or when performing
4492 * a configuration switch where we destroy the current client-side object
4493 * but then create a new client-side object for this same HistoryRecord.
4494 */
4495 private final boolean destroyActivityLocked(HistoryRecord r,
4496 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004497 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004498 TAG, "Removing activity: token=" + r
4499 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004500 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004501 System.identityHashCode(r),
4502 r.task.taskId, r.shortComponentName);
4503
4504 boolean removedFromHistory = false;
4505
4506 cleanUpActivityLocked(r, false);
4507
Dianne Hackborn03abb812010-01-04 18:43:19 -08004508 final boolean hadApp = r.app != null;
4509
4510 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 if (removeFromApp) {
4512 int idx = r.app.activities.indexOf(r);
4513 if (idx >= 0) {
4514 r.app.activities.remove(idx);
4515 }
4516 if (r.persistent) {
4517 decPersistentCountLocked(r.app);
4518 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004519 if (r.app.activities.size() == 0) {
4520 // No longer have activities, so update location in
4521 // LRU list.
4522 updateLruProcessLocked(r.app, true, false);
4523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 }
4525
4526 boolean skipDestroy = false;
4527
4528 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004529 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004530 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4531 r.configChangeFlags);
4532 } catch (Exception e) {
4533 // We can just ignore exceptions here... if the process
4534 // has crashed, our death notification will clean things
4535 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004536 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537 if (r.finishing) {
4538 removeActivityFromHistoryLocked(r);
4539 removedFromHistory = true;
4540 skipDestroy = true;
4541 }
4542 }
4543
4544 r.app = null;
4545 r.nowVisible = false;
4546
4547 if (r.finishing && !skipDestroy) {
4548 r.state = ActivityState.DESTROYING;
4549 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4550 msg.obj = r;
4551 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4552 } else {
4553 r.state = ActivityState.DESTROYED;
4554 }
4555 } else {
4556 // remove this record from the history.
4557 if (r.finishing) {
4558 removeActivityFromHistoryLocked(r);
4559 removedFromHistory = true;
4560 } else {
4561 r.state = ActivityState.DESTROYED;
4562 }
4563 }
4564
4565 r.configChangeFlags = 0;
4566
Dianne Hackborn03abb812010-01-04 18:43:19 -08004567 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004568 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004569 }
4570
4571 return removedFromHistory;
4572 }
4573
Dianne Hackborn03abb812010-01-04 18:43:19 -08004574 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004576 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004577 TAG, "Removing app " + app + " from list " + list
4578 + " with " + i + " entries");
4579 while (i > 0) {
4580 i--;
4581 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004582 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004583 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4584 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004585 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 list.remove(i);
4587 }
4588 }
4589 }
4590
4591 /**
4592 * Main function for removing an existing process from the activity manager
4593 * as a result of that process going away. Clears out all connections
4594 * to the process.
4595 */
4596 private final void handleAppDiedLocked(ProcessRecord app,
4597 boolean restarting) {
4598 cleanUpApplicationRecordLocked(app, restarting, -1);
4599 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004600 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004601 }
4602
4603 // Just in case...
4604 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004605 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 mPausingActivity = null;
4607 }
4608 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4609 mLastPausedActivity = null;
4610 }
4611
4612 // Remove this application's activities from active lists.
4613 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4614 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4615 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4616 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4617
4618 boolean atTop = true;
4619 boolean hasVisibleActivities = false;
4620
4621 // Clean out the history list.
4622 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004623 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004624 TAG, "Removing app " + app + " from history with " + i + " entries");
4625 while (i > 0) {
4626 i--;
4627 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004628 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4630 if (r.app == app) {
4631 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004632 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004633 TAG, "Removing this entry! frozen=" + r.haveState
4634 + " finishing=" + r.finishing);
4635 mHistory.remove(i);
4636
4637 r.inHistory = false;
4638 mWindowManager.removeAppToken(r);
4639 if (VALIDATE_TOKENS) {
4640 mWindowManager.validateAppTokens(mHistory);
4641 }
4642 removeActivityUriPermissionsLocked(r);
4643
4644 } else {
4645 // We have the current state for this activity, so
4646 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004647 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004648 TAG, "Keeping entry, setting app to null");
4649 if (r.visible) {
4650 hasVisibleActivities = true;
4651 }
4652 r.app = null;
4653 r.nowVisible = false;
4654 if (!r.haveState) {
4655 r.icicle = null;
4656 }
4657 }
4658
4659 cleanUpActivityLocked(r, true);
4660 r.state = ActivityState.STOPPED;
4661 }
4662 atTop = false;
4663 }
4664
4665 app.activities.clear();
4666
4667 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004668 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004669 + " running instrumentation " + app.instrumentationClass);
4670 Bundle info = new Bundle();
4671 info.putString("shortMsg", "Process crashed.");
4672 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4673 }
4674
4675 if (!restarting) {
4676 if (!resumeTopActivityLocked(null)) {
4677 // If there was nothing to resume, and we are not already
4678 // restarting this process, but there is a visible activity that
4679 // is hosted by the process... then make sure all visible
4680 // activities are running, taking care of restarting this
4681 // process.
4682 if (hasVisibleActivities) {
4683 ensureActivitiesVisibleLocked(null, 0);
4684 }
4685 }
4686 }
4687 }
4688
4689 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4690 IBinder threadBinder = thread.asBinder();
4691
4692 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004693 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4694 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4696 return i;
4697 }
4698 }
4699 return -1;
4700 }
4701
4702 private final ProcessRecord getRecordForAppLocked(
4703 IApplicationThread thread) {
4704 if (thread == null) {
4705 return null;
4706 }
4707
4708 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004709 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 }
4711
4712 private final void appDiedLocked(ProcessRecord app, int pid,
4713 IApplicationThread thread) {
4714
4715 mProcDeaths[0]++;
4716
Magnus Edlund7bb25812010-02-24 15:45:06 +01004717 // Clean up already done if the process has been re-started.
4718 if (app.pid == pid && app.thread != null &&
4719 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07004720 if (!app.killedBackground) {
4721 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
4722 + ") has died.");
4723 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08004724 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004725 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 TAG, "Dying app: " + app + ", pid: " + pid
4727 + ", thread: " + thread.asBinder());
4728 boolean doLowMem = app.instrumentationClass == null;
4729 handleAppDiedLocked(app, false);
4730
4731 if (doLowMem) {
4732 // If there are no longer any background processes running,
4733 // and the app that died was not running instrumentation,
4734 // then tell everyone we are now low on memory.
4735 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004736 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4737 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004738 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4739 haveBg = true;
4740 break;
4741 }
4742 }
4743
4744 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004745 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004746 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004747 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004748 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4749 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004750 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004751 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4752 // The low memory report is overriding any current
4753 // state for a GC request. Make sure to do
4754 // visible/foreground processes first.
4755 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4756 rec.lastRequestedGc = 0;
4757 } else {
4758 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004760 rec.reportLowMemory = true;
4761 rec.lastLowMemory = now;
4762 mProcessesToGc.remove(rec);
4763 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004764 }
4765 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004766 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 }
4768 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004769 } else if (app.pid != pid) {
4770 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004771 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004772 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004773 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004774 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004775 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004776 + thread.asBinder());
4777 }
4778 }
4779
Dan Egnor42471dd2010-01-07 17:25:22 -08004780 /**
4781 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07004782 * @param clearTraces causes the dump file to be erased prior to the new
4783 * traces being written, if true; when false, the new traces will be
4784 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08004785 * @param pids of dalvik VM processes to dump stack traces for
4786 * @return file containing stack traces, or null if no dump file is configured
4787 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07004788 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004789 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4790 if (tracesPath == null || tracesPath.length() == 0) {
4791 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004793
4794 File tracesFile = new File(tracesPath);
4795 try {
4796 File tracesDir = tracesFile.getParentFile();
4797 if (!tracesDir.exists()) tracesFile.mkdirs();
4798 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4799
Christopher Tate6ee412d2010-05-28 12:01:56 -07004800 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08004801 tracesFile.createNewFile();
4802 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4803 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004804 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004805 return null;
4806 }
4807
4808 // Use a FileObserver to detect when traces finish writing.
4809 // The order of traces is considered important to maintain for legibility.
4810 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4811 public synchronized void onEvent(int event, String path) { notify(); }
4812 };
4813
4814 try {
4815 observer.startWatching();
4816 int num = pids.size();
4817 for (int i = 0; i < num; i++) {
4818 synchronized (observer) {
4819 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4820 observer.wait(200); // Wait for write-close, give up after 200msec
4821 }
4822 }
4823 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004824 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004825 } finally {
4826 observer.stopWatching();
4827 }
4828
4829 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 }
4831
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004832 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08004833 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004834 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004835
4836 synchronized (this) {
4837 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4838 if (mShuttingDown) {
4839 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
4840 return;
4841 } else if (app.notResponding) {
4842 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
4843 return;
4844 } else if (app.crashing) {
4845 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
4846 return;
4847 }
4848
4849 // In case we come through here for the same app before completing
4850 // this one, mark as anring now so we will bail out.
4851 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08004852
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004853 // Log the ANR to the event log.
4854 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4855 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08004856
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004857 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4858 pids.add(app.pid);
4859
4860 int parentPid = app.pid;
4861 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4862 if (parentPid != app.pid) pids.add(parentPid);
4863
4864 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08004865
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004866 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4867 ProcessRecord r = mLruProcesses.get(i);
4868 if (r != null && r.thread != null) {
4869 int pid = r.pid;
4870 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
4871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 }
4873 }
4874
Christopher Tate6ee412d2010-05-28 12:01:56 -07004875 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08004876
4877 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004878 StringBuilder info = mStringBuilder;
4879 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004880 info.append("ANR in ").append(app.processName);
4881 if (activity != null && activity.shortComponentName != null) {
4882 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004883 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004884 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004885 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004886 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004887 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004888 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004889 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891
Dan Egnor42471dd2010-01-07 17:25:22 -08004892 String cpuInfo = null;
4893 if (MONITOR_CPU_USAGE) {
4894 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004895 synchronized (mProcessStatsThread) {
4896 cpuInfo = mProcessStats.printCurrentState();
4897 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004898 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004899 }
4900
Joe Onorato8a9b2202010-02-26 18:56:32 -08004901 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004902 if (tracesFile == null) {
4903 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4904 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4905 }
4906
4907 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4908
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004909 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004911 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4912 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004913 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004914 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4915 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004916 }
4917 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004918 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004919 }
4920 }
4921
Dan Egnor42471dd2010-01-07 17:25:22 -08004922 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4923 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4924 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004925
4926 synchronized (this) {
4927 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4928 Process.killProcess(app.pid);
4929 return;
4930 }
4931
4932 // Set the app's notResponding state, and look up the errorReportReceiver
4933 makeAppNotRespondingLocked(app,
4934 activity != null ? activity.shortComponentName : null,
4935 annotation != null ? "ANR " + annotation : "ANR",
4936 info.toString());
4937
4938 // Bring up the infamous App Not Responding dialog
4939 Message msg = Message.obtain();
4940 HashMap map = new HashMap();
4941 msg.what = SHOW_NOT_RESPONDING_MSG;
4942 msg.obj = map;
4943 map.put("app", app);
4944 if (activity != null) {
4945 map.put("activity", activity);
4946 }
4947
4948 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08004949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950 }
4951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 private final void decPersistentCountLocked(ProcessRecord app)
4953 {
4954 app.persistentActivities--;
4955 if (app.persistentActivities > 0) {
4956 // Still more of 'em...
4957 return;
4958 }
4959 if (app.persistent) {
4960 // Ah, but the application itself is persistent. Whatever!
4961 return;
4962 }
4963
4964 // App is no longer persistent... make sure it and the ones
4965 // following it in the LRU list have the correc oom_adj.
4966 updateOomAdjLocked();
4967 }
4968
4969 public void setPersistent(IBinder token, boolean isPersistent) {
4970 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4971 != PackageManager.PERMISSION_GRANTED) {
4972 String msg = "Permission Denial: setPersistent() from pid="
4973 + Binder.getCallingPid()
4974 + ", uid=" + Binder.getCallingUid()
4975 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004976 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 throw new SecurityException(msg);
4978 }
4979
4980 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004981 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 if (index < 0) {
4983 return;
4984 }
4985 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4986 ProcessRecord app = r.app;
4987
Joe Onorato8a9b2202010-02-26 18:56:32 -08004988 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 TAG, "Setting persistence " + isPersistent + ": " + r);
4990
4991 if (isPersistent) {
4992 if (r.persistent) {
4993 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004994 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004995 return;
4996 }
4997 r.persistent = true;
4998 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004999 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 if (app.persistentActivities > 1) {
5001 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005002 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005003 return;
5004 }
5005 if (app.persistent) {
5006 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005007 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 return;
5009 }
5010
5011 // App is now persistent... make sure it and the ones
5012 // following it now have the correct oom_adj.
5013 final long origId = Binder.clearCallingIdentity();
5014 updateOomAdjLocked();
5015 Binder.restoreCallingIdentity(origId);
5016
5017 } else {
5018 if (!r.persistent) {
5019 // Okay okay, I heard you already!
5020 return;
5021 }
5022 r.persistent = false;
5023 final long origId = Binder.clearCallingIdentity();
5024 decPersistentCountLocked(app);
5025 Binder.restoreCallingIdentity(origId);
5026
5027 }
5028 }
5029 }
5030
5031 public boolean clearApplicationUserData(final String packageName,
5032 final IPackageDataObserver observer) {
5033 int uid = Binder.getCallingUid();
5034 int pid = Binder.getCallingPid();
5035 long callingId = Binder.clearCallingIdentity();
5036 try {
5037 IPackageManager pm = ActivityThread.getPackageManager();
5038 int pkgUid = -1;
5039 synchronized(this) {
5040 try {
5041 pkgUid = pm.getPackageUid(packageName);
5042 } catch (RemoteException e) {
5043 }
5044 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005045 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 return false;
5047 }
5048 if (uid == pkgUid || checkComponentPermission(
5049 android.Manifest.permission.CLEAR_APP_USER_DATA,
5050 pid, uid, -1)
5051 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005052 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 } else {
5054 throw new SecurityException(pid+" does not have permission:"+
5055 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5056 "for process:"+packageName);
5057 }
5058 }
5059
5060 try {
5061 //clear application user data
5062 pm.clearApplicationUserData(packageName, observer);
5063 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5064 Uri.fromParts("package", packageName, null));
5065 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005066 synchronized (this) {
5067 broadcastIntentLocked(null, null, intent,
5068 null, null, 0, null, null, null,
5069 false, false, MY_PID, Process.SYSTEM_UID);
5070 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 } catch (RemoteException e) {
5072 }
5073 } finally {
5074 Binder.restoreCallingIdentity(callingId);
5075 }
5076 return true;
5077 }
5078
Dianne Hackborn03abb812010-01-04 18:43:19 -08005079 public void killBackgroundProcesses(final String packageName) {
5080 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5081 != PackageManager.PERMISSION_GRANTED &&
5082 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5083 != PackageManager.PERMISSION_GRANTED) {
5084 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005085 + Binder.getCallingPid()
5086 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005087 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005088 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005089 throw new SecurityException(msg);
5090 }
5091
5092 long callingId = Binder.clearCallingIdentity();
5093 try {
5094 IPackageManager pm = ActivityThread.getPackageManager();
5095 int pkgUid = -1;
5096 synchronized(this) {
5097 try {
5098 pkgUid = pm.getPackageUid(packageName);
5099 } catch (RemoteException e) {
5100 }
5101 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005102 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 return;
5104 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005105 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005106 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005107 }
5108 } finally {
5109 Binder.restoreCallingIdentity(callingId);
5110 }
5111 }
5112
5113 public void forceStopPackage(final String packageName) {
5114 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5115 != PackageManager.PERMISSION_GRANTED) {
5116 String msg = "Permission Denial: forceStopPackage() from pid="
5117 + Binder.getCallingPid()
5118 + ", uid=" + Binder.getCallingUid()
5119 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005120 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005121 throw new SecurityException(msg);
5122 }
5123
5124 long callingId = Binder.clearCallingIdentity();
5125 try {
5126 IPackageManager pm = ActivityThread.getPackageManager();
5127 int pkgUid = -1;
5128 synchronized(this) {
5129 try {
5130 pkgUid = pm.getPackageUid(packageName);
5131 } catch (RemoteException e) {
5132 }
5133 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005134 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005135 return;
5136 }
5137 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 }
5139 } finally {
5140 Binder.restoreCallingIdentity(callingId);
5141 }
5142 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005143
5144 /*
5145 * The pkg name and uid have to be specified.
5146 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5147 */
5148 public void killApplicationWithUid(String pkg, int uid) {
5149 if (pkg == null) {
5150 return;
5151 }
5152 // Make sure the uid is valid.
5153 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005154 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005155 return;
5156 }
5157 int callerUid = Binder.getCallingUid();
5158 // Only the system server can kill an application
5159 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005160 // Post an aysnc message to kill the application
5161 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5162 msg.arg1 = uid;
5163 msg.arg2 = 0;
5164 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005165 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005166 } else {
5167 throw new SecurityException(callerUid + " cannot kill pkg: " +
5168 pkg);
5169 }
5170 }
5171
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005172 public void closeSystemDialogs(String reason) {
5173 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5174 if (reason != null) {
5175 intent.putExtra("reason", reason);
5176 }
5177
5178 final int uid = Binder.getCallingUid();
5179 final long origId = Binder.clearCallingIdentity();
5180 synchronized (this) {
5181 int i = mWatchers.beginBroadcast();
5182 while (i > 0) {
5183 i--;
5184 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5185 if (w != null) {
5186 try {
5187 w.closingSystemDialogs(reason);
5188 } catch (RemoteException e) {
5189 }
5190 }
5191 }
5192 mWatchers.finishBroadcast();
5193
Dianne Hackbornffa42482009-09-23 22:20:11 -07005194 mWindowManager.closeSystemDialogs(reason);
5195
5196 for (i=mHistory.size()-1; i>=0; i--) {
5197 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5198 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5199 finishActivityLocked(r, i,
5200 Activity.RESULT_CANCELED, null, "close-sys");
5201 }
5202 }
5203
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005204 broadcastIntentLocked(null, null, intent, null,
5205 null, 0, null, null, null, false, false, -1, uid);
5206 }
5207 Binder.restoreCallingIdentity(origId);
5208 }
5209
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005210 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005211 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005212 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5213 for (int i=pids.length-1; i>=0; i--) {
5214 infos[i] = new Debug.MemoryInfo();
5215 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005216 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005217 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005218 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005219
5220 public void killApplicationProcess(String processName, int uid) {
5221 if (processName == null) {
5222 return;
5223 }
5224
5225 int callerUid = Binder.getCallingUid();
5226 // Only the system server can kill an application
5227 if (callerUid == Process.SYSTEM_UID) {
5228 synchronized (this) {
5229 ProcessRecord app = getProcessRecordLocked(processName, uid);
5230 if (app != null) {
5231 try {
5232 app.thread.scheduleSuicide();
5233 } catch (RemoteException e) {
5234 // If the other end already died, then our work here is done.
5235 }
5236 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005237 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005238 + processName + " / " + uid);
5239 }
5240 }
5241 } else {
5242 throw new SecurityException(callerUid + " cannot kill app process: " +
5243 processName);
5244 }
5245 }
5246
Dianne Hackborn03abb812010-01-04 18:43:19 -08005247 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005248 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5250 Uri.fromParts("package", packageName, null));
5251 intent.putExtra(Intent.EXTRA_UID, uid);
5252 broadcastIntentLocked(null, null, intent,
5253 null, null, 0, null, null, null,
5254 false, false, MY_PID, Process.SYSTEM_UID);
5255 }
5256
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005257 private final boolean killPackageProcessesLocked(String packageName, int uid,
5258 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005259 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005260
Dianne Hackborn03abb812010-01-04 18:43:19 -08005261 // Remove all processes this package may have touched: all with the
5262 // same UID (except for the system or root user), and all whose name
5263 // matches the package name.
5264 final String procNamePrefix = packageName + ":";
5265 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5266 final int NA = apps.size();
5267 for (int ia=0; ia<NA; ia++) {
5268 ProcessRecord app = apps.valueAt(ia);
5269 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005270 if (doit) {
5271 procs.add(app);
5272 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005273 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5274 || app.processName.equals(packageName)
5275 || app.processName.startsWith(procNamePrefix)) {
5276 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005277 if (!doit) {
5278 return true;
5279 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005280 app.removed = true;
5281 procs.add(app);
5282 }
5283 }
5284 }
5285 }
5286
5287 int N = procs.size();
5288 for (int i=0; i<N; i++) {
5289 removeProcessLocked(procs.get(i), callerWillRestart);
5290 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005291 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005292 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005293
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005294 private final boolean forceStopPackageLocked(String name, int uid,
5295 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 int i, N;
5297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005298 if (uid < 0) {
5299 try {
5300 uid = ActivityThread.getPackageManager().getPackageUid(name);
5301 } catch (RemoteException e) {
5302 }
5303 }
5304
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005305 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005306 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005307
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005308 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5309 while (badApps.hasNext()) {
5310 SparseArray<Long> ba = badApps.next();
5311 if (ba.get(uid) != null) {
5312 badApps.remove();
5313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 }
5315 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005316
5317 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5318 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005319
5320 for (i=mHistory.size()-1; i>=0; i--) {
5321 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5322 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005323 if (!doit) {
5324 return true;
5325 }
5326 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005327 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 if (r.app != null) {
5329 r.app.removed = true;
5330 }
5331 r.app = null;
5332 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5333 }
5334 }
5335
5336 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5337 for (ServiceRecord service : mServices.values()) {
5338 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005339 if (!doit) {
5340 return true;
5341 }
5342 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005343 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 if (service.app != null) {
5345 service.app.removed = true;
5346 }
5347 service.app = null;
5348 services.add(service);
5349 }
5350 }
5351
5352 N = services.size();
5353 for (i=0; i<N; i++) {
5354 bringDownServiceLocked(services.get(i), true);
5355 }
5356
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005357 if (doit) {
5358 if (purgeCache) {
5359 AttributeCache ac = AttributeCache.instance();
5360 if (ac != null) {
5361 ac.removePackage(name);
5362 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005363 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005364 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005365 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005366
5367 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 }
5369
5370 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5371 final String name = app.processName;
5372 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005373 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005374 TAG, "Force removing process " + app + " (" + name
5375 + "/" + uid + ")");
5376
5377 mProcessNames.remove(name, uid);
5378 boolean needRestart = false;
5379 if (app.pid > 0 && app.pid != MY_PID) {
5380 int pid = app.pid;
5381 synchronized (mPidsSelfLocked) {
5382 mPidsSelfLocked.remove(pid);
5383 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5384 }
5385 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005386 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005387 Process.killProcess(pid);
5388
5389 if (app.persistent) {
5390 if (!callerWillRestart) {
5391 addAppLocked(app.info);
5392 } else {
5393 needRestart = true;
5394 }
5395 }
5396 } else {
5397 mRemovedProcesses.add(app);
5398 }
5399
5400 return needRestart;
5401 }
5402
5403 private final void processStartTimedOutLocked(ProcessRecord app) {
5404 final int pid = app.pid;
5405 boolean gone = false;
5406 synchronized (mPidsSelfLocked) {
5407 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5408 if (knownApp != null && knownApp.thread == null) {
5409 mPidsSelfLocked.remove(pid);
5410 gone = true;
5411 }
5412 }
5413
5414 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005415 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005416 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005417 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005418 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005419 // Take care of any launching providers waiting for this process.
5420 checkAppInLaunchingProvidersLocked(app, true);
5421 // Take care of any services that are waiting for the process.
5422 for (int i=0; i<mPendingServices.size(); i++) {
5423 ServiceRecord sr = mPendingServices.get(i);
5424 if (app.info.uid == sr.appInfo.uid
5425 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005426 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005427 mPendingServices.remove(i);
5428 i--;
5429 bringDownServiceLocked(sr, true);
5430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005431 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005432 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005433 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005434 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005435 try {
5436 IBackupManager bm = IBackupManager.Stub.asInterface(
5437 ServiceManager.getService(Context.BACKUP_SERVICE));
5438 bm.agentDisconnected(app.info.packageName);
5439 } catch (RemoteException e) {
5440 // Can't happen; the backup manager is local
5441 }
5442 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005443 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005444 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005445 mPendingBroadcast = null;
5446 scheduleBroadcastsLocked();
5447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005448 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005449 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005450 }
5451 }
5452
5453 private final boolean attachApplicationLocked(IApplicationThread thread,
5454 int pid) {
5455
5456 // Find the application record that is being attached... either via
5457 // the pid if we are running in multiple processes, or just pull the
5458 // next app record if we are emulating process with anonymous threads.
5459 ProcessRecord app;
5460 if (pid != MY_PID && pid >= 0) {
5461 synchronized (mPidsSelfLocked) {
5462 app = mPidsSelfLocked.get(pid);
5463 }
5464 } else if (mStartingProcesses.size() > 0) {
5465 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005466 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005467 } else {
5468 app = null;
5469 }
5470
5471 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005472 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005474 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005475 if (pid > 0 && pid != MY_PID) {
5476 Process.killProcess(pid);
5477 } else {
5478 try {
5479 thread.scheduleExit();
5480 } catch (Exception e) {
5481 // Ignore exceptions.
5482 }
5483 }
5484 return false;
5485 }
5486
5487 // If this application record is still attached to a previous
5488 // process, clean it up now.
5489 if (app.thread != null) {
5490 handleAppDiedLocked(app, true);
5491 }
5492
5493 // Tell the process all about itself.
5494
Joe Onorato8a9b2202010-02-26 18:56:32 -08005495 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005496 TAG, "Binding process pid " + pid + " to record " + app);
5497
5498 String processName = app.processName;
5499 try {
5500 thread.asBinder().linkToDeath(new AppDeathRecipient(
5501 app, pid, thread), 0);
5502 } catch (RemoteException e) {
5503 app.resetPackageList();
5504 startProcessLocked(app, "link fail", processName);
5505 return false;
5506 }
5507
Doug Zongker2bec3d42009-12-04 12:52:44 -08005508 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509
5510 app.thread = thread;
5511 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005512 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5513 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 app.forcingToForeground = null;
5515 app.foregroundServices = false;
5516 app.debugging = false;
5517
5518 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5519
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005520 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5521 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005522
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005523 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005524 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005525 }
5526
Joe Onorato8a9b2202010-02-26 18:56:32 -08005527 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005528 TAG, "New app record " + app
5529 + " thread=" + thread.asBinder() + " pid=" + pid);
5530 try {
5531 int testMode = IApplicationThread.DEBUG_OFF;
5532 if (mDebugApp != null && mDebugApp.equals(processName)) {
5533 testMode = mWaitForDebugger
5534 ? IApplicationThread.DEBUG_WAIT
5535 : IApplicationThread.DEBUG_ON;
5536 app.debugging = true;
5537 if (mDebugTransient) {
5538 mDebugApp = mOrigDebugApp;
5539 mWaitForDebugger = mOrigWaitForDebugger;
5540 }
5541 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005542
Christopher Tate181fafa2009-05-14 11:12:14 -07005543 // If the app is being launched for restore or full backup, set it up specially
5544 boolean isRestrictedBackupMode = false;
5545 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5546 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5547 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5548 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005549
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005550 ensurePackageDexOpt(app.instrumentationInfo != null
5551 ? app.instrumentationInfo.packageName
5552 : app.info.packageName);
5553 if (app.instrumentationClass != null) {
5554 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005555 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005556 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005557 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005558 thread.bindApplication(processName, app.instrumentationInfo != null
5559 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005560 app.instrumentationClass, app.instrumentationProfileFile,
5561 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005562 isRestrictedBackupMode || !normalMode,
5563 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005564 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005565 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005566 } catch (Exception e) {
5567 // todo: Yikes! What should we do? For now we will try to
5568 // start another process, but that could easily get us in
5569 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005570 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005571
5572 app.resetPackageList();
5573 startProcessLocked(app, "bind fail", processName);
5574 return false;
5575 }
5576
5577 // Remove this record from the list of starting applications.
5578 mPersistentStartingProcesses.remove(app);
5579 mProcessesOnHold.remove(app);
5580
5581 boolean badApp = false;
5582 boolean didSomething = false;
5583
5584 // See if the top visible activity is waiting to run in this process...
5585 HistoryRecord hr = topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07005586 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005587 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5588 && processName.equals(hr.processName)) {
5589 try {
5590 if (realStartActivityLocked(hr, app, true, true)) {
5591 didSomething = true;
5592 }
5593 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005594 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005595 + hr.intent.getComponent().flattenToShortString(), e);
5596 badApp = true;
5597 }
5598 } else {
5599 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5600 }
5601 }
5602
5603 // Find any services that should be running in this process...
5604 if (!badApp && mPendingServices.size() > 0) {
5605 ServiceRecord sr = null;
5606 try {
5607 for (int i=0; i<mPendingServices.size(); i++) {
5608 sr = mPendingServices.get(i);
5609 if (app.info.uid != sr.appInfo.uid
5610 || !processName.equals(sr.processName)) {
5611 continue;
5612 }
5613
5614 mPendingServices.remove(i);
5615 i--;
5616 realStartServiceLocked(sr, app);
5617 didSomething = true;
5618 }
5619 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005620 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005621 + sr.shortName, e);
5622 badApp = true;
5623 }
5624 }
5625
5626 // Check if the next broadcast receiver is in this process...
5627 BroadcastRecord br = mPendingBroadcast;
5628 if (!badApp && br != null && br.curApp == app) {
5629 try {
5630 mPendingBroadcast = null;
5631 processCurBroadcastLocked(br, app);
5632 didSomething = true;
5633 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005634 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 + br.curComponent.flattenToShortString(), e);
5636 badApp = true;
5637 logBroadcastReceiverDiscard(br);
5638 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5639 br.resultExtras, br.resultAbort, true);
5640 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005641 // We need to reset the state if we fails to start the receiver.
5642 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005643 }
5644 }
5645
Christopher Tate181fafa2009-05-14 11:12:14 -07005646 // Check whether the next backup agent is in this process...
5647 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005648 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005649 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005650 try {
5651 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5652 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005653 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005654 e.printStackTrace();
5655 }
5656 }
5657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005658 if (badApp) {
5659 // todo: Also need to kill application to deal with all
5660 // kinds of exceptions.
5661 handleAppDiedLocked(app, false);
5662 return false;
5663 }
5664
5665 if (!didSomething) {
5666 updateOomAdjLocked();
5667 }
5668
5669 return true;
5670 }
5671
5672 public final void attachApplication(IApplicationThread thread) {
5673 synchronized (this) {
5674 int callingPid = Binder.getCallingPid();
5675 final long origId = Binder.clearCallingIdentity();
5676 attachApplicationLocked(thread, callingPid);
5677 Binder.restoreCallingIdentity(origId);
5678 }
5679 }
5680
Dianne Hackborne88846e2009-09-30 21:34:25 -07005681 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005683 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005684 Binder.restoreCallingIdentity(origId);
5685 }
5686
5687 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5688 boolean remove) {
5689 int N = mStoppingActivities.size();
5690 if (N <= 0) return null;
5691
5692 ArrayList<HistoryRecord> stops = null;
5693
5694 final boolean nowVisible = mResumedActivity != null
5695 && mResumedActivity.nowVisible
5696 && !mResumedActivity.waitingVisible;
5697 for (int i=0; i<N; i++) {
5698 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005699 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 + nowVisible + " waitingVisible=" + s.waitingVisible
5701 + " finishing=" + s.finishing);
5702 if (s.waitingVisible && nowVisible) {
5703 mWaitingVisibleActivities.remove(s);
5704 s.waitingVisible = false;
5705 if (s.finishing) {
5706 // If this activity is finishing, it is sitting on top of
5707 // everyone else but we now know it is no longer needed...
5708 // so get rid of it. Otherwise, we need to go through the
5709 // normal flow and hide it once we determine that it is
5710 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005711 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 mWindowManager.setAppVisibility(s, false);
5713 }
5714 }
5715 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005716 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 if (stops == null) {
5718 stops = new ArrayList<HistoryRecord>();
5719 }
5720 stops.add(s);
5721 mStoppingActivities.remove(i);
5722 N--;
5723 i--;
5724 }
5725 }
5726
5727 return stops;
5728 }
5729
5730 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005731 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005732 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005733 mWindowManager.enableScreenAfterBoot();
5734 }
5735
Dianne Hackborne88846e2009-09-30 21:34:25 -07005736 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5737 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005738 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005739
5740 ArrayList<HistoryRecord> stops = null;
5741 ArrayList<HistoryRecord> finishes = null;
5742 ArrayList<HistoryRecord> thumbnails = null;
5743 int NS = 0;
5744 int NF = 0;
5745 int NT = 0;
5746 IApplicationThread sendThumbnail = null;
5747 boolean booting = false;
5748 boolean enableScreen = false;
5749
5750 synchronized (this) {
5751 if (token != null) {
5752 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5753 }
5754
5755 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005756 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005757 if (index >= 0) {
5758 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5759
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005760 if (fromTimeout) {
5761 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5762 }
5763
Dianne Hackborne88846e2009-09-30 21:34:25 -07005764 // This is a hack to semi-deal with a race condition
5765 // in the client where it can be constructed with a
5766 // newer configuration from when we asked it to launch.
5767 // We'll update with whatever configuration it now says
5768 // it used to launch.
5769 if (config != null) {
5770 r.configuration = config;
5771 }
5772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005773 // No longer need to keep the device awake.
5774 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5775 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5776 mLaunchingActivity.release();
5777 }
5778
5779 // We are now idle. If someone is waiting for a thumbnail from
5780 // us, we can now deliver.
5781 r.idle = true;
5782 scheduleAppGcsLocked();
5783 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5784 sendThumbnail = r.app.thread;
5785 r.thumbnailNeeded = false;
5786 }
5787
5788 // If this activity is fullscreen, set up to hide those under it.
5789
Joe Onorato8a9b2202010-02-26 18:56:32 -08005790 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 ensureActivitiesVisibleLocked(null, 0);
5792
Joe Onorato8a9b2202010-02-26 18:56:32 -08005793 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005794 if (!mBooted && !fromTimeout) {
5795 mBooted = true;
5796 enableScreen = true;
5797 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005798
5799 } else if (fromTimeout) {
5800 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005801 }
5802
5803 // Atomically retrieve all of the other things to do.
5804 stops = processStoppingActivitiesLocked(true);
5805 NS = stops != null ? stops.size() : 0;
5806 if ((NF=mFinishingActivities.size()) > 0) {
5807 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5808 mFinishingActivities.clear();
5809 }
5810 if ((NT=mCancelledThumbnails.size()) > 0) {
5811 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5812 mCancelledThumbnails.clear();
5813 }
5814
5815 booting = mBooting;
5816 mBooting = false;
5817 }
5818
5819 int i;
5820
5821 // Send thumbnail if requested.
5822 if (sendThumbnail != null) {
5823 try {
5824 sendThumbnail.requestThumbnail(token);
5825 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005826 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005827 sendPendingThumbnail(null, token, null, null, true);
5828 }
5829 }
5830
5831 // Stop any activities that are scheduled to do so but have been
5832 // waiting for the next one to start.
5833 for (i=0; i<NS; i++) {
5834 HistoryRecord r = (HistoryRecord)stops.get(i);
5835 synchronized (this) {
5836 if (r.finishing) {
5837 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5838 } else {
5839 stopActivityLocked(r);
5840 }
5841 }
5842 }
5843
5844 // Finish any activities that are scheduled to do so but have been
5845 // waiting for the next one to start.
5846 for (i=0; i<NF; i++) {
5847 HistoryRecord r = (HistoryRecord)finishes.get(i);
5848 synchronized (this) {
5849 destroyActivityLocked(r, true);
5850 }
5851 }
5852
5853 // Report back to any thumbnail receivers.
5854 for (i=0; i<NT; i++) {
5855 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5856 sendPendingThumbnail(r, null, null, null, true);
5857 }
5858
5859 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005860 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005861 }
5862
5863 trimApplications();
5864 //dump();
5865 //mWindowManager.dump();
5866
5867 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 enableScreenAfterBoot();
5869 }
5870 }
5871
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005872 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005873 IntentFilter pkgFilter = new IntentFilter();
5874 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5875 pkgFilter.addDataScheme("package");
5876 mContext.registerReceiver(new BroadcastReceiver() {
5877 @Override
5878 public void onReceive(Context context, Intent intent) {
5879 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5880 if (pkgs != null) {
5881 for (String pkg : pkgs) {
5882 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5883 setResultCode(Activity.RESULT_OK);
5884 return;
5885 }
5886 }
5887 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005888 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005889 }, pkgFilter);
5890
5891 synchronized (this) {
5892 // Ensure that any processes we had put on hold are now started
5893 // up.
5894 final int NP = mProcessesOnHold.size();
5895 if (NP > 0) {
5896 ArrayList<ProcessRecord> procs =
5897 new ArrayList<ProcessRecord>(mProcessesOnHold);
5898 for (int ip=0; ip<NP; ip++) {
5899 this.startProcessLocked(procs.get(ip), "on-hold", null);
5900 }
5901 }
5902
5903 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5904 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005905 broadcastIntentLocked(null, null,
5906 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5907 null, null, 0, null, null,
5908 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5909 false, false, MY_PID, Process.SYSTEM_UID);
5910 }
5911 }
5912 }
5913
5914 final void ensureBootCompleted() {
5915 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005916 boolean enableScreen;
5917 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005918 booting = mBooting;
5919 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005920 enableScreen = !mBooted;
5921 mBooted = true;
5922 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005923
5924 if (booting) {
5925 finishBooting();
5926 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005927
5928 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005929 enableScreenAfterBoot();
5930 }
5931 }
5932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 public final void activityPaused(IBinder token, Bundle icicle) {
5934 // Refuse possible leaked file descriptors
5935 if (icicle != null && icicle.hasFileDescriptors()) {
5936 throw new IllegalArgumentException("File descriptors passed in Bundle");
5937 }
5938
5939 final long origId = Binder.clearCallingIdentity();
5940 activityPaused(token, icicle, false);
5941 Binder.restoreCallingIdentity(origId);
5942 }
5943
5944 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005945 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005946 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5947 + ", timeout=" + timeout);
5948
5949 HistoryRecord r = null;
5950
5951 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005952 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005953 if (index >= 0) {
5954 r = (HistoryRecord)mHistory.get(index);
5955 if (!timeout) {
5956 r.icicle = icicle;
5957 r.haveState = true;
5958 }
5959 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5960 if (mPausingActivity == r) {
5961 r.state = ActivityState.PAUSED;
5962 completePauseLocked();
5963 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005964 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005965 System.identityHashCode(r), r.shortComponentName,
5966 mPausingActivity != null
5967 ? mPausingActivity.shortComponentName : "(none)");
5968 }
5969 }
5970 }
5971 }
5972
5973 public final void activityStopped(IBinder token, Bitmap thumbnail,
5974 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005975 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005976 TAG, "Activity stopped: token=" + token);
5977
5978 HistoryRecord r = null;
5979
5980 final long origId = Binder.clearCallingIdentity();
5981
5982 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005983 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 if (index >= 0) {
5985 r = (HistoryRecord)mHistory.get(index);
5986 r.thumbnail = thumbnail;
5987 r.description = description;
5988 r.stopped = true;
5989 r.state = ActivityState.STOPPED;
5990 if (!r.finishing) {
5991 if (r.configDestroy) {
5992 destroyActivityLocked(r, true);
5993 resumeTopActivityLocked(null);
5994 }
5995 }
5996 }
5997 }
5998
5999 if (r != null) {
6000 sendPendingThumbnail(r, null, null, null, false);
6001 }
6002
6003 trimApplications();
6004
6005 Binder.restoreCallingIdentity(origId);
6006 }
6007
6008 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006009 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006010 synchronized (this) {
6011 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
6012
Dianne Hackborn75b03852009-06-12 15:43:26 -07006013 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006014 if (index >= 0) {
6015 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6016 if (r.state == ActivityState.DESTROYING) {
6017 final long origId = Binder.clearCallingIdentity();
6018 removeActivityFromHistoryLocked(r);
6019 Binder.restoreCallingIdentity(origId);
6020 }
6021 }
6022 }
6023 }
6024
6025 public String getCallingPackage(IBinder token) {
6026 synchronized (this) {
6027 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07006028 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006029 }
6030 }
6031
6032 public ComponentName getCallingActivity(IBinder token) {
6033 synchronized (this) {
6034 HistoryRecord r = getCallingRecordLocked(token);
6035 return r != null ? r.intent.getComponent() : null;
6036 }
6037 }
6038
6039 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006040 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 if (index >= 0) {
6042 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6043 if (r != null) {
6044 return r.resultTo;
6045 }
6046 }
6047 return null;
6048 }
6049
6050 public ComponentName getActivityClassForToken(IBinder token) {
6051 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006052 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 if (index >= 0) {
6054 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6055 return r.intent.getComponent();
6056 }
6057 return null;
6058 }
6059 }
6060
6061 public String getPackageForToken(IBinder token) {
6062 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006063 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006064 if (index >= 0) {
6065 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6066 return r.packageName;
6067 }
6068 return null;
6069 }
6070 }
6071
6072 public IIntentSender getIntentSender(int type,
6073 String packageName, IBinder token, String resultWho,
6074 int requestCode, Intent intent, String resolvedType, int flags) {
6075 // Refuse possible leaked file descriptors
6076 if (intent != null && intent.hasFileDescriptors() == true) {
6077 throw new IllegalArgumentException("File descriptors passed in Intent");
6078 }
6079
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006080 if (type == INTENT_SENDER_BROADCAST) {
6081 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6082 throw new IllegalArgumentException(
6083 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6084 }
6085 }
6086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006087 synchronized(this) {
6088 int callingUid = Binder.getCallingUid();
6089 try {
6090 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6091 Process.supportsProcesses()) {
6092 int uid = ActivityThread.getPackageManager()
6093 .getPackageUid(packageName);
6094 if (uid != Binder.getCallingUid()) {
6095 String msg = "Permission Denial: getIntentSender() from pid="
6096 + Binder.getCallingPid()
6097 + ", uid=" + Binder.getCallingUid()
6098 + ", (need uid=" + uid + ")"
6099 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006100 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006101 throw new SecurityException(msg);
6102 }
6103 }
6104 } catch (RemoteException e) {
6105 throw new SecurityException(e);
6106 }
6107 HistoryRecord activity = null;
6108 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006109 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006110 if (index < 0) {
6111 return null;
6112 }
6113 activity = (HistoryRecord)mHistory.get(index);
6114 if (activity.finishing) {
6115 return null;
6116 }
6117 }
6118
6119 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6120 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6121 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6122 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6123 |PendingIntent.FLAG_UPDATE_CURRENT);
6124
6125 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6126 type, packageName, activity, resultWho,
6127 requestCode, intent, resolvedType, flags);
6128 WeakReference<PendingIntentRecord> ref;
6129 ref = mIntentSenderRecords.get(key);
6130 PendingIntentRecord rec = ref != null ? ref.get() : null;
6131 if (rec != null) {
6132 if (!cancelCurrent) {
6133 if (updateCurrent) {
6134 rec.key.requestIntent.replaceExtras(intent);
6135 }
6136 return rec;
6137 }
6138 rec.canceled = true;
6139 mIntentSenderRecords.remove(key);
6140 }
6141 if (noCreate) {
6142 return rec;
6143 }
6144 rec = new PendingIntentRecord(this, key, callingUid);
6145 mIntentSenderRecords.put(key, rec.ref);
6146 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6147 if (activity.pendingResults == null) {
6148 activity.pendingResults
6149 = new HashSet<WeakReference<PendingIntentRecord>>();
6150 }
6151 activity.pendingResults.add(rec.ref);
6152 }
6153 return rec;
6154 }
6155 }
6156
6157 public void cancelIntentSender(IIntentSender sender) {
6158 if (!(sender instanceof PendingIntentRecord)) {
6159 return;
6160 }
6161 synchronized(this) {
6162 PendingIntentRecord rec = (PendingIntentRecord)sender;
6163 try {
6164 int uid = ActivityThread.getPackageManager()
6165 .getPackageUid(rec.key.packageName);
6166 if (uid != Binder.getCallingUid()) {
6167 String msg = "Permission Denial: cancelIntentSender() from pid="
6168 + Binder.getCallingPid()
6169 + ", uid=" + Binder.getCallingUid()
6170 + " is not allowed to cancel packges "
6171 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006172 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006173 throw new SecurityException(msg);
6174 }
6175 } catch (RemoteException e) {
6176 throw new SecurityException(e);
6177 }
6178 cancelIntentSenderLocked(rec, true);
6179 }
6180 }
6181
6182 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6183 rec.canceled = true;
6184 mIntentSenderRecords.remove(rec.key);
6185 if (cleanActivity && rec.key.activity != null) {
6186 rec.key.activity.pendingResults.remove(rec.ref);
6187 }
6188 }
6189
6190 public String getPackageForIntentSender(IIntentSender pendingResult) {
6191 if (!(pendingResult instanceof PendingIntentRecord)) {
6192 return null;
6193 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006194 try {
6195 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6196 return res.key.packageName;
6197 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006198 }
6199 return null;
6200 }
6201
6202 public void setProcessLimit(int max) {
6203 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6204 "setProcessLimit()");
6205 mProcessLimit = max;
6206 }
6207
6208 public int getProcessLimit() {
6209 return mProcessLimit;
6210 }
6211
6212 void foregroundTokenDied(ForegroundToken token) {
6213 synchronized (ActivityManagerService.this) {
6214 synchronized (mPidsSelfLocked) {
6215 ForegroundToken cur
6216 = mForegroundProcesses.get(token.pid);
6217 if (cur != token) {
6218 return;
6219 }
6220 mForegroundProcesses.remove(token.pid);
6221 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6222 if (pr == null) {
6223 return;
6224 }
6225 pr.forcingToForeground = null;
6226 pr.foregroundServices = false;
6227 }
6228 updateOomAdjLocked();
6229 }
6230 }
6231
6232 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6233 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6234 "setProcessForeground()");
6235 synchronized(this) {
6236 boolean changed = false;
6237
6238 synchronized (mPidsSelfLocked) {
6239 ProcessRecord pr = mPidsSelfLocked.get(pid);
6240 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006241 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006242 return;
6243 }
6244 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6245 if (oldToken != null) {
6246 oldToken.token.unlinkToDeath(oldToken, 0);
6247 mForegroundProcesses.remove(pid);
6248 pr.forcingToForeground = null;
6249 changed = true;
6250 }
6251 if (isForeground && token != null) {
6252 ForegroundToken newToken = new ForegroundToken() {
6253 public void binderDied() {
6254 foregroundTokenDied(this);
6255 }
6256 };
6257 newToken.pid = pid;
6258 newToken.token = token;
6259 try {
6260 token.linkToDeath(newToken, 0);
6261 mForegroundProcesses.put(pid, newToken);
6262 pr.forcingToForeground = token;
6263 changed = true;
6264 } catch (RemoteException e) {
6265 // If the process died while doing this, we will later
6266 // do the cleanup with the process death link.
6267 }
6268 }
6269 }
6270
6271 if (changed) {
6272 updateOomAdjLocked();
6273 }
6274 }
6275 }
6276
6277 // =========================================================
6278 // PERMISSIONS
6279 // =========================================================
6280
6281 static class PermissionController extends IPermissionController.Stub {
6282 ActivityManagerService mActivityManagerService;
6283 PermissionController(ActivityManagerService activityManagerService) {
6284 mActivityManagerService = activityManagerService;
6285 }
6286
6287 public boolean checkPermission(String permission, int pid, int uid) {
6288 return mActivityManagerService.checkPermission(permission, pid,
6289 uid) == PackageManager.PERMISSION_GRANTED;
6290 }
6291 }
6292
6293 /**
6294 * This can be called with or without the global lock held.
6295 */
6296 int checkComponentPermission(String permission, int pid, int uid,
6297 int reqUid) {
6298 // We might be performing an operation on behalf of an indirect binder
6299 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6300 // client identity accordingly before proceeding.
6301 Identity tlsIdentity = sCallerIdentity.get();
6302 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006303 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6305 uid = tlsIdentity.uid;
6306 pid = tlsIdentity.pid;
6307 }
6308
6309 // Root, system server and our own process get to do everything.
6310 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6311 !Process.supportsProcesses()) {
6312 return PackageManager.PERMISSION_GRANTED;
6313 }
6314 // If the target requires a specific UID, always fail for others.
6315 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006316 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006317 return PackageManager.PERMISSION_DENIED;
6318 }
6319 if (permission == null) {
6320 return PackageManager.PERMISSION_GRANTED;
6321 }
6322 try {
6323 return ActivityThread.getPackageManager()
6324 .checkUidPermission(permission, uid);
6325 } catch (RemoteException e) {
6326 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006327 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006328 }
6329 return PackageManager.PERMISSION_DENIED;
6330 }
6331
6332 /**
6333 * As the only public entry point for permissions checking, this method
6334 * can enforce the semantic that requesting a check on a null global
6335 * permission is automatically denied. (Internally a null permission
6336 * string is used when calling {@link #checkComponentPermission} in cases
6337 * when only uid-based security is needed.)
6338 *
6339 * This can be called with or without the global lock held.
6340 */
6341 public int checkPermission(String permission, int pid, int uid) {
6342 if (permission == null) {
6343 return PackageManager.PERMISSION_DENIED;
6344 }
6345 return checkComponentPermission(permission, pid, uid, -1);
6346 }
6347
6348 /**
6349 * Binder IPC calls go through the public entry point.
6350 * This can be called with or without the global lock held.
6351 */
6352 int checkCallingPermission(String permission) {
6353 return checkPermission(permission,
6354 Binder.getCallingPid(),
6355 Binder.getCallingUid());
6356 }
6357
6358 /**
6359 * This can be called with or without the global lock held.
6360 */
6361 void enforceCallingPermission(String permission, String func) {
6362 if (checkCallingPermission(permission)
6363 == PackageManager.PERMISSION_GRANTED) {
6364 return;
6365 }
6366
6367 String msg = "Permission Denial: " + func + " from pid="
6368 + Binder.getCallingPid()
6369 + ", uid=" + Binder.getCallingUid()
6370 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006371 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 throw new SecurityException(msg);
6373 }
6374
6375 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6376 ProviderInfo pi, int uid, int modeFlags) {
6377 try {
6378 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6379 if ((pi.readPermission != null) &&
6380 (pm.checkUidPermission(pi.readPermission, uid)
6381 != PackageManager.PERMISSION_GRANTED)) {
6382 return false;
6383 }
6384 }
6385 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6386 if ((pi.writePermission != null) &&
6387 (pm.checkUidPermission(pi.writePermission, uid)
6388 != PackageManager.PERMISSION_GRANTED)) {
6389 return false;
6390 }
6391 }
6392 return true;
6393 } catch (RemoteException e) {
6394 return false;
6395 }
6396 }
6397
6398 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6399 int modeFlags) {
6400 // Root gets to do everything.
6401 if (uid == 0 || !Process.supportsProcesses()) {
6402 return true;
6403 }
6404 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6405 if (perms == null) return false;
6406 UriPermission perm = perms.get(uri);
6407 if (perm == null) return false;
6408 return (modeFlags&perm.modeFlags) == modeFlags;
6409 }
6410
6411 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6412 // Another redirected-binder-call permissions check as in
6413 // {@link checkComponentPermission}.
6414 Identity tlsIdentity = sCallerIdentity.get();
6415 if (tlsIdentity != null) {
6416 uid = tlsIdentity.uid;
6417 pid = tlsIdentity.pid;
6418 }
6419
6420 // Our own process gets to do everything.
6421 if (pid == MY_PID) {
6422 return PackageManager.PERMISSION_GRANTED;
6423 }
6424 synchronized(this) {
6425 return checkUriPermissionLocked(uri, uid, modeFlags)
6426 ? PackageManager.PERMISSION_GRANTED
6427 : PackageManager.PERMISSION_DENIED;
6428 }
6429 }
6430
6431 private void grantUriPermissionLocked(int callingUid,
6432 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6433 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6434 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6435 if (modeFlags == 0) {
6436 return;
6437 }
6438
Joe Onorato8a9b2202010-02-26 18:56:32 -08006439 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006440 "Requested grant " + targetPkg + " permission to " + uri);
6441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 final IPackageManager pm = ActivityThread.getPackageManager();
6443
6444 // If this is not a content: uri, we can't do anything with it.
6445 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006446 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006447 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006448 return;
6449 }
6450
6451 String name = uri.getAuthority();
6452 ProviderInfo pi = null;
6453 ContentProviderRecord cpr
6454 = (ContentProviderRecord)mProvidersByName.get(name);
6455 if (cpr != null) {
6456 pi = cpr.info;
6457 } else {
6458 try {
6459 pi = pm.resolveContentProvider(name,
6460 PackageManager.GET_URI_PERMISSION_PATTERNS);
6461 } catch (RemoteException ex) {
6462 }
6463 }
6464 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006465 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006466 return;
6467 }
6468
6469 int targetUid;
6470 try {
6471 targetUid = pm.getPackageUid(targetPkg);
6472 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006473 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006474 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006475 return;
6476 }
6477 } catch (RemoteException ex) {
6478 return;
6479 }
6480
6481 // First... does the target actually need this permission?
6482 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6483 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006484 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006485 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 return;
6487 }
6488
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006489 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006490 if (!pi.grantUriPermissions) {
6491 throw new SecurityException("Provider " + pi.packageName
6492 + "/" + pi.name
6493 + " does not allow granting of Uri permissions (uri "
6494 + uri + ")");
6495 }
6496 if (pi.uriPermissionPatterns != null) {
6497 final int N = pi.uriPermissionPatterns.length;
6498 boolean allowed = false;
6499 for (int i=0; i<N; i++) {
6500 if (pi.uriPermissionPatterns[i] != null
6501 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6502 allowed = true;
6503 break;
6504 }
6505 }
6506 if (!allowed) {
6507 throw new SecurityException("Provider " + pi.packageName
6508 + "/" + pi.name
6509 + " does not allow granting of permission to path of Uri "
6510 + uri);
6511 }
6512 }
6513
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006514 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 // this uri?
6516 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6517 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6518 throw new SecurityException("Uid " + callingUid
6519 + " does not have permission to uri " + uri);
6520 }
6521 }
6522
6523 // Okay! So here we are: the caller has the assumed permission
6524 // to the uri, and the target doesn't. Let's now give this to
6525 // the target.
6526
Joe Onorato8a9b2202010-02-26 18:56:32 -08006527 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006528 "Granting " + targetPkg + " permission to " + uri);
6529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006530 HashMap<Uri, UriPermission> targetUris
6531 = mGrantedUriPermissions.get(targetUid);
6532 if (targetUris == null) {
6533 targetUris = new HashMap<Uri, UriPermission>();
6534 mGrantedUriPermissions.put(targetUid, targetUris);
6535 }
6536
6537 UriPermission perm = targetUris.get(uri);
6538 if (perm == null) {
6539 perm = new UriPermission(targetUid, uri);
6540 targetUris.put(uri, perm);
6541
6542 }
6543 perm.modeFlags |= modeFlags;
6544 if (activity == null) {
6545 perm.globalModeFlags |= modeFlags;
6546 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6547 perm.readActivities.add(activity);
6548 if (activity.readUriPermissions == null) {
6549 activity.readUriPermissions = new HashSet<UriPermission>();
6550 }
6551 activity.readUriPermissions.add(perm);
6552 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6553 perm.writeActivities.add(activity);
6554 if (activity.writeUriPermissions == null) {
6555 activity.writeUriPermissions = new HashSet<UriPermission>();
6556 }
6557 activity.writeUriPermissions.add(perm);
6558 }
6559 }
6560
6561 private void grantUriPermissionFromIntentLocked(int callingUid,
6562 String targetPkg, Intent intent, HistoryRecord activity) {
6563 if (intent == null) {
6564 return;
6565 }
6566 Uri data = intent.getData();
6567 if (data == null) {
6568 return;
6569 }
6570 grantUriPermissionLocked(callingUid, targetPkg, data,
6571 intent.getFlags(), activity);
6572 }
6573
6574 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6575 Uri uri, int modeFlags) {
6576 synchronized(this) {
6577 final ProcessRecord r = getRecordForAppLocked(caller);
6578 if (r == null) {
6579 throw new SecurityException("Unable to find app for caller "
6580 + caller
6581 + " when granting permission to uri " + uri);
6582 }
6583 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006584 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006585 return;
6586 }
6587 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006588 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006589 return;
6590 }
6591
6592 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6593 null);
6594 }
6595 }
6596
6597 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6598 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6599 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6600 HashMap<Uri, UriPermission> perms
6601 = mGrantedUriPermissions.get(perm.uid);
6602 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006603 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006604 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006605 perms.remove(perm.uri);
6606 if (perms.size() == 0) {
6607 mGrantedUriPermissions.remove(perm.uid);
6608 }
6609 }
6610 }
6611 }
6612
6613 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6614 if (activity.readUriPermissions != null) {
6615 for (UriPermission perm : activity.readUriPermissions) {
6616 perm.readActivities.remove(activity);
6617 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6618 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6619 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6620 removeUriPermissionIfNeededLocked(perm);
6621 }
6622 }
6623 }
6624 if (activity.writeUriPermissions != null) {
6625 for (UriPermission perm : activity.writeUriPermissions) {
6626 perm.writeActivities.remove(activity);
6627 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6628 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6629 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6630 removeUriPermissionIfNeededLocked(perm);
6631 }
6632 }
6633 }
6634 }
6635
6636 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6637 int modeFlags) {
6638 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6639 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6640 if (modeFlags == 0) {
6641 return;
6642 }
6643
Joe Onorato8a9b2202010-02-26 18:56:32 -08006644 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006645 "Revoking all granted permissions to " + uri);
6646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006647 final IPackageManager pm = ActivityThread.getPackageManager();
6648
6649 final String authority = uri.getAuthority();
6650 ProviderInfo pi = null;
6651 ContentProviderRecord cpr
6652 = (ContentProviderRecord)mProvidersByName.get(authority);
6653 if (cpr != null) {
6654 pi = cpr.info;
6655 } else {
6656 try {
6657 pi = pm.resolveContentProvider(authority,
6658 PackageManager.GET_URI_PERMISSION_PATTERNS);
6659 } catch (RemoteException ex) {
6660 }
6661 }
6662 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006663 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006664 return;
6665 }
6666
6667 // Does the caller have this permission on the URI?
6668 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6669 // Right now, if you are not the original owner of the permission,
6670 // you are not allowed to revoke it.
6671 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6672 throw new SecurityException("Uid " + callingUid
6673 + " does not have permission to uri " + uri);
6674 //}
6675 }
6676
6677 // Go through all of the permissions and remove any that match.
6678 final List<String> SEGMENTS = uri.getPathSegments();
6679 if (SEGMENTS != null) {
6680 final int NS = SEGMENTS.size();
6681 int N = mGrantedUriPermissions.size();
6682 for (int i=0; i<N; i++) {
6683 HashMap<Uri, UriPermission> perms
6684 = mGrantedUriPermissions.valueAt(i);
6685 Iterator<UriPermission> it = perms.values().iterator();
6686 toploop:
6687 while (it.hasNext()) {
6688 UriPermission perm = it.next();
6689 Uri targetUri = perm.uri;
6690 if (!authority.equals(targetUri.getAuthority())) {
6691 continue;
6692 }
6693 List<String> targetSegments = targetUri.getPathSegments();
6694 if (targetSegments == null) {
6695 continue;
6696 }
6697 if (targetSegments.size() < NS) {
6698 continue;
6699 }
6700 for (int j=0; j<NS; j++) {
6701 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6702 continue toploop;
6703 }
6704 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006705 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006706 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006707 perm.clearModes(modeFlags);
6708 if (perm.modeFlags == 0) {
6709 it.remove();
6710 }
6711 }
6712 if (perms.size() == 0) {
6713 mGrantedUriPermissions.remove(
6714 mGrantedUriPermissions.keyAt(i));
6715 N--;
6716 i--;
6717 }
6718 }
6719 }
6720 }
6721
6722 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6723 int modeFlags) {
6724 synchronized(this) {
6725 final ProcessRecord r = getRecordForAppLocked(caller);
6726 if (r == null) {
6727 throw new SecurityException("Unable to find app for caller "
6728 + caller
6729 + " when revoking permission to uri " + uri);
6730 }
6731 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006732 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006733 return;
6734 }
6735
6736 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6737 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6738 if (modeFlags == 0) {
6739 return;
6740 }
6741
6742 final IPackageManager pm = ActivityThread.getPackageManager();
6743
6744 final String authority = uri.getAuthority();
6745 ProviderInfo pi = null;
6746 ContentProviderRecord cpr
6747 = (ContentProviderRecord)mProvidersByName.get(authority);
6748 if (cpr != null) {
6749 pi = cpr.info;
6750 } else {
6751 try {
6752 pi = pm.resolveContentProvider(authority,
6753 PackageManager.GET_URI_PERMISSION_PATTERNS);
6754 } catch (RemoteException ex) {
6755 }
6756 }
6757 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006758 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006759 return;
6760 }
6761
6762 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6763 }
6764 }
6765
6766 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6767 synchronized (this) {
6768 ProcessRecord app =
6769 who != null ? getRecordForAppLocked(who) : null;
6770 if (app == null) return;
6771
6772 Message msg = Message.obtain();
6773 msg.what = WAIT_FOR_DEBUGGER_MSG;
6774 msg.obj = app;
6775 msg.arg1 = waiting ? 1 : 0;
6776 mHandler.sendMessage(msg);
6777 }
6778 }
6779
6780 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6781 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006782 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006783 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006784 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006785 }
6786
6787 // =========================================================
6788 // TASK MANAGEMENT
6789 // =========================================================
6790
6791 public List getTasks(int maxNum, int flags,
6792 IThumbnailReceiver receiver) {
6793 ArrayList list = new ArrayList();
6794
6795 PendingThumbnailsRecord pending = null;
6796 IApplicationThread topThumbnail = null;
6797 HistoryRecord topRecord = null;
6798
6799 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006800 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006801 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6802 + ", receiver=" + receiver);
6803
6804 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6805 != PackageManager.PERMISSION_GRANTED) {
6806 if (receiver != null) {
6807 // If the caller wants to wait for pending thumbnails,
6808 // it ain't gonna get them.
6809 try {
6810 receiver.finished();
6811 } catch (RemoteException ex) {
6812 }
6813 }
6814 String msg = "Permission Denial: getTasks() from pid="
6815 + Binder.getCallingPid()
6816 + ", uid=" + Binder.getCallingUid()
6817 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006818 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006819 throw new SecurityException(msg);
6820 }
6821
6822 int pos = mHistory.size()-1;
6823 HistoryRecord next =
6824 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6825 HistoryRecord top = null;
6826 CharSequence topDescription = null;
6827 TaskRecord curTask = null;
6828 int numActivities = 0;
6829 int numRunning = 0;
6830 while (pos >= 0 && maxNum > 0) {
6831 final HistoryRecord r = next;
6832 pos--;
6833 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6834
6835 // Initialize state for next task if needed.
6836 if (top == null ||
6837 (top.state == ActivityState.INITIALIZING
6838 && top.task == r.task)) {
6839 top = r;
6840 topDescription = r.description;
6841 curTask = r.task;
6842 numActivities = numRunning = 0;
6843 }
6844
6845 // Add 'r' into the current task.
6846 numActivities++;
6847 if (r.app != null && r.app.thread != null) {
6848 numRunning++;
6849 }
6850 if (topDescription == null) {
6851 topDescription = r.description;
6852 }
6853
Joe Onorato8a9b2202010-02-26 18:56:32 -08006854 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006855 TAG, r.intent.getComponent().flattenToShortString()
6856 + ": task=" + r.task);
6857
6858 // If the next one is a different task, generate a new
6859 // TaskInfo entry for what we have.
6860 if (next == null || next.task != curTask) {
6861 ActivityManager.RunningTaskInfo ci
6862 = new ActivityManager.RunningTaskInfo();
6863 ci.id = curTask.taskId;
6864 ci.baseActivity = r.intent.getComponent();
6865 ci.topActivity = top.intent.getComponent();
6866 ci.thumbnail = top.thumbnail;
6867 ci.description = topDescription;
6868 ci.numActivities = numActivities;
6869 ci.numRunning = numRunning;
6870 //System.out.println(
6871 // "#" + maxNum + ": " + " descr=" + ci.description);
6872 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006873 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006874 TAG, "State=" + top.state + "Idle=" + top.idle
6875 + " app=" + top.app
6876 + " thr=" + (top.app != null ? top.app.thread : null));
6877 if (top.state == ActivityState.RESUMED
6878 || top.state == ActivityState.PAUSING) {
6879 if (top.idle && top.app != null
6880 && top.app.thread != null) {
6881 topRecord = top;
6882 topThumbnail = top.app.thread;
6883 } else {
6884 top.thumbnailNeeded = true;
6885 }
6886 }
6887 if (pending == null) {
6888 pending = new PendingThumbnailsRecord(receiver);
6889 }
6890 pending.pendingRecords.add(top);
6891 }
6892 list.add(ci);
6893 maxNum--;
6894 top = null;
6895 }
6896 }
6897
6898 if (pending != null) {
6899 mPendingThumbnails.add(pending);
6900 }
6901 }
6902
Joe Onorato8a9b2202010-02-26 18:56:32 -08006903 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006904
6905 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006906 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006907 try {
6908 topThumbnail.requestThumbnail(topRecord);
6909 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006910 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006911 sendPendingThumbnail(null, topRecord, null, null, true);
6912 }
6913 }
6914
6915 if (pending == null && receiver != null) {
6916 // In this case all thumbnails were available and the client
6917 // is being asked to be told when the remaining ones come in...
6918 // which is unusually, since the top-most currently running
6919 // activity should never have a canned thumbnail! Oh well.
6920 try {
6921 receiver.finished();
6922 } catch (RemoteException ex) {
6923 }
6924 }
6925
6926 return list;
6927 }
6928
6929 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6930 int flags) {
6931 synchronized (this) {
6932 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6933 "getRecentTasks()");
6934
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006935 IPackageManager pm = ActivityThread.getPackageManager();
6936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 final int N = mRecentTasks.size();
6938 ArrayList<ActivityManager.RecentTaskInfo> res
6939 = new ArrayList<ActivityManager.RecentTaskInfo>(
6940 maxNum < N ? maxNum : N);
6941 for (int i=0; i<N && maxNum > 0; i++) {
6942 TaskRecord tr = mRecentTasks.get(i);
6943 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6944 || (tr.intent == null)
6945 || ((tr.intent.getFlags()
6946 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6947 ActivityManager.RecentTaskInfo rti
6948 = new ActivityManager.RecentTaskInfo();
6949 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6950 rti.baseIntent = new Intent(
6951 tr.intent != null ? tr.intent : tr.affinityIntent);
6952 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006953
6954 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
6955 // Check whether this activity is currently available.
6956 try {
6957 if (rti.origActivity != null) {
6958 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
6959 continue;
6960 }
6961 } else if (rti.baseIntent != null) {
6962 if (pm.queryIntentActivities(rti.baseIntent,
6963 null, 0) == null) {
6964 continue;
6965 }
6966 }
6967 } catch (RemoteException e) {
6968 // Will never happen.
6969 }
6970 }
6971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006972 res.add(rti);
6973 maxNum--;
6974 }
6975 }
6976 return res;
6977 }
6978 }
6979
6980 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6981 int j;
6982 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6983 TaskRecord jt = startTask;
6984
6985 // First look backwards
6986 for (j=startIndex-1; j>=0; j--) {
6987 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6988 if (r.task != jt) {
6989 jt = r.task;
6990 if (affinity.equals(jt.affinity)) {
6991 return j;
6992 }
6993 }
6994 }
6995
6996 // Now look forwards
6997 final int N = mHistory.size();
6998 jt = startTask;
6999 for (j=startIndex+1; j<N; j++) {
7000 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7001 if (r.task != jt) {
7002 if (affinity.equals(jt.affinity)) {
7003 return j;
7004 }
7005 jt = r.task;
7006 }
7007 }
7008
7009 // Might it be at the top?
7010 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
7011 return N-1;
7012 }
7013
7014 return -1;
7015 }
7016
7017 /**
7018 * Perform a reset of the given task, if needed as part of launching it.
7019 * Returns the new HistoryRecord at the top of the task.
7020 */
7021 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
7022 HistoryRecord newActivity) {
7023 boolean forceReset = (newActivity.info.flags
7024 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
7025 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
7026 if ((newActivity.info.flags
7027 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
7028 forceReset = true;
7029 }
7030 }
7031
7032 final TaskRecord task = taskTop.task;
7033
7034 // We are going to move through the history list so that we can look
7035 // at each activity 'target' with 'below' either the interesting
7036 // activity immediately below it in the stack or null.
7037 HistoryRecord target = null;
7038 int targetI = 0;
7039 int taskTopI = -1;
7040 int replyChainEnd = -1;
7041 int lastReparentPos = -1;
7042 for (int i=mHistory.size()-1; i>=-1; i--) {
7043 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
7044
7045 if (below != null && below.finishing) {
7046 continue;
7047 }
7048 if (target == null) {
7049 target = below;
7050 targetI = i;
7051 // If we were in the middle of a reply chain before this
7052 // task, it doesn't appear like the root of the chain wants
7053 // anything interesting, so drop it.
7054 replyChainEnd = -1;
7055 continue;
7056 }
7057
7058 final int flags = target.info.flags;
7059
7060 final boolean finishOnTaskLaunch =
7061 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7062 final boolean allowTaskReparenting =
7063 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7064
7065 if (target.task == task) {
7066 // We are inside of the task being reset... we'll either
7067 // finish this activity, push it out for another task,
7068 // or leave it as-is. We only do this
7069 // for activities that are not the root of the task (since
7070 // if we finish the root, we may no longer have the task!).
7071 if (taskTopI < 0) {
7072 taskTopI = targetI;
7073 }
7074 if (below != null && below.task == task) {
7075 final boolean clearWhenTaskReset =
7076 (target.intent.getFlags()
7077 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007078 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007079 // If this activity is sending a reply to a previous
7080 // activity, we can't do anything with it now until
7081 // we reach the start of the reply chain.
7082 // XXX note that we are assuming the result is always
7083 // to the previous activity, which is almost always
7084 // the case but we really shouldn't count on.
7085 if (replyChainEnd < 0) {
7086 replyChainEnd = targetI;
7087 }
Ed Heyl73798232009-03-24 21:32:21 -07007088 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007089 && target.taskAffinity != null
7090 && !target.taskAffinity.equals(task.affinity)) {
7091 // If this activity has an affinity for another
7092 // task, then we need to move it out of here. We will
7093 // move it as far out of the way as possible, to the
7094 // bottom of the activity stack. This also keeps it
7095 // correctly ordered with any activities we previously
7096 // moved.
7097 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7098 if (target.taskAffinity != null
7099 && target.taskAffinity.equals(p.task.affinity)) {
7100 // If the activity currently at the bottom has the
7101 // same task affinity as the one we are moving,
7102 // then merge it into the same task.
7103 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007104 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007105 + " out to bottom task " + p.task);
7106 } else {
7107 mCurTask++;
7108 if (mCurTask <= 0) {
7109 mCurTask = 1;
7110 }
7111 target.task = new TaskRecord(mCurTask, target.info, null,
7112 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7113 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007114 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007115 + " out to new task " + target.task);
7116 }
7117 mWindowManager.setAppGroupId(target, task.taskId);
7118 if (replyChainEnd < 0) {
7119 replyChainEnd = targetI;
7120 }
7121 int dstPos = 0;
7122 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7123 p = (HistoryRecord)mHistory.get(srcPos);
7124 if (p.finishing) {
7125 continue;
7126 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007127 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007128 + " out to target's task " + target.task);
7129 task.numActivities--;
7130 p.task = target.task;
7131 target.task.numActivities++;
7132 mHistory.remove(srcPos);
7133 mHistory.add(dstPos, p);
7134 mWindowManager.moveAppToken(dstPos, p);
7135 mWindowManager.setAppGroupId(p, p.task.taskId);
7136 dstPos++;
7137 if (VALIDATE_TOKENS) {
7138 mWindowManager.validateAppTokens(mHistory);
7139 }
7140 i++;
7141 }
7142 if (taskTop == p) {
7143 taskTop = below;
7144 }
7145 if (taskTopI == replyChainEnd) {
7146 taskTopI = -1;
7147 }
7148 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007149 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007150 } else if (forceReset || finishOnTaskLaunch
7151 || clearWhenTaskReset) {
7152 // If the activity should just be removed -- either
7153 // because it asks for it, or the task should be
7154 // cleared -- then finish it and anything that is
7155 // part of its reply chain.
7156 if (clearWhenTaskReset) {
7157 // In this case, we want to finish this activity
7158 // and everything above it, so be sneaky and pretend
7159 // like these are all in the reply chain.
7160 replyChainEnd = targetI+1;
7161 while (replyChainEnd < mHistory.size() &&
7162 ((HistoryRecord)mHistory.get(
7163 replyChainEnd)).task == task) {
7164 replyChainEnd++;
7165 }
7166 replyChainEnd--;
7167 } else if (replyChainEnd < 0) {
7168 replyChainEnd = targetI;
7169 }
7170 HistoryRecord p = null;
7171 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7172 p = (HistoryRecord)mHistory.get(srcPos);
7173 if (p.finishing) {
7174 continue;
7175 }
7176 if (finishActivityLocked(p, srcPos,
7177 Activity.RESULT_CANCELED, null, "reset")) {
7178 replyChainEnd--;
7179 srcPos--;
7180 }
7181 }
7182 if (taskTop == p) {
7183 taskTop = below;
7184 }
7185 if (taskTopI == replyChainEnd) {
7186 taskTopI = -1;
7187 }
7188 replyChainEnd = -1;
7189 } else {
7190 // If we were in the middle of a chain, well the
7191 // activity that started it all doesn't want anything
7192 // special, so leave it all as-is.
7193 replyChainEnd = -1;
7194 }
7195 } else {
7196 // Reached the bottom of the task -- any reply chain
7197 // should be left as-is.
7198 replyChainEnd = -1;
7199 }
7200
7201 } else if (target.resultTo != null) {
7202 // If this activity is sending a reply to a previous
7203 // activity, we can't do anything with it now until
7204 // we reach the start of the reply chain.
7205 // XXX note that we are assuming the result is always
7206 // to the previous activity, which is almost always
7207 // the case but we really shouldn't count on.
7208 if (replyChainEnd < 0) {
7209 replyChainEnd = targetI;
7210 }
7211
7212 } else if (taskTopI >= 0 && allowTaskReparenting
7213 && task.affinity != null
7214 && task.affinity.equals(target.taskAffinity)) {
7215 // We are inside of another task... if this activity has
7216 // an affinity for our task, then either remove it if we are
7217 // clearing or move it over to our task. Note that
7218 // we currently punt on the case where we are resetting a
7219 // task that is not at the top but who has activities above
7220 // with an affinity to it... this is really not a normal
7221 // case, and we will need to later pull that task to the front
7222 // and usually at that point we will do the reset and pick
7223 // up those remaining activities. (This only happens if
7224 // someone starts an activity in a new task from an activity
7225 // in a task that is not currently on top.)
7226 if (forceReset || finishOnTaskLaunch) {
7227 if (replyChainEnd < 0) {
7228 replyChainEnd = targetI;
7229 }
7230 HistoryRecord p = null;
7231 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7232 p = (HistoryRecord)mHistory.get(srcPos);
7233 if (p.finishing) {
7234 continue;
7235 }
7236 if (finishActivityLocked(p, srcPos,
7237 Activity.RESULT_CANCELED, null, "reset")) {
7238 taskTopI--;
7239 lastReparentPos--;
7240 replyChainEnd--;
7241 srcPos--;
7242 }
7243 }
7244 replyChainEnd = -1;
7245 } else {
7246 if (replyChainEnd < 0) {
7247 replyChainEnd = targetI;
7248 }
7249 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7250 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7251 if (p.finishing) {
7252 continue;
7253 }
7254 if (lastReparentPos < 0) {
7255 lastReparentPos = taskTopI;
7256 taskTop = p;
7257 } else {
7258 lastReparentPos--;
7259 }
7260 mHistory.remove(srcPos);
7261 p.task.numActivities--;
7262 p.task = task;
7263 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007264 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007265 + " in to resetting task " + task);
7266 task.numActivities++;
7267 mWindowManager.moveAppToken(lastReparentPos, p);
7268 mWindowManager.setAppGroupId(p, p.task.taskId);
7269 if (VALIDATE_TOKENS) {
7270 mWindowManager.validateAppTokens(mHistory);
7271 }
7272 }
7273 replyChainEnd = -1;
7274
7275 // Now we've moved it in to place... but what if this is
7276 // a singleTop activity and we have put it on top of another
7277 // instance of the same activity? Then we drop the instance
7278 // below so it remains singleTop.
7279 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7280 for (int j=lastReparentPos-1; j>=0; j--) {
7281 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7282 if (p.finishing) {
7283 continue;
7284 }
7285 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7286 if (finishActivityLocked(p, j,
7287 Activity.RESULT_CANCELED, null, "replace")) {
7288 taskTopI--;
7289 lastReparentPos--;
7290 }
7291 }
7292 }
7293 }
7294 }
7295 }
7296
7297 target = below;
7298 targetI = i;
7299 }
7300
7301 return taskTop;
7302 }
7303
7304 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007305 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 */
7307 public void moveTaskToFront(int task) {
7308 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7309 "moveTaskToFront()");
7310
7311 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007312 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7313 Binder.getCallingUid(), "Task to front")) {
7314 return;
7315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 final long origId = Binder.clearCallingIdentity();
7317 try {
7318 int N = mRecentTasks.size();
7319 for (int i=0; i<N; i++) {
7320 TaskRecord tr = mRecentTasks.get(i);
7321 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007322 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007323 return;
7324 }
7325 }
7326 for (int i=mHistory.size()-1; i>=0; i--) {
7327 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7328 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007329 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007330 return;
7331 }
7332 }
7333 } finally {
7334 Binder.restoreCallingIdentity(origId);
7335 }
7336 }
7337 }
7338
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007339 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007340 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341
7342 final int task = tr.taskId;
7343 int top = mHistory.size()-1;
7344
7345 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7346 // nothing to do!
7347 return;
7348 }
7349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 ArrayList moved = new ArrayList();
7351
7352 // Applying the affinities may have removed entries from the history,
7353 // so get the size again.
7354 top = mHistory.size()-1;
7355 int pos = top;
7356
7357 // Shift all activities with this task up to the top
7358 // of the stack, keeping them in the same internal order.
7359 while (pos >= 0) {
7360 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007361 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007362 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7363 boolean first = true;
7364 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007365 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007366 mHistory.remove(pos);
7367 mHistory.add(top, r);
7368 moved.add(0, r);
7369 top--;
7370 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007371 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 first = false;
7373 }
7374 }
7375 pos--;
7376 }
7377
Joe Onorato8a9b2202010-02-26 18:56:32 -08007378 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007379 "Prepare to front transition: task=" + tr);
7380 if (reason != null &&
7381 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7382 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7383 HistoryRecord r = topRunningActivityLocked(null);
7384 if (r != null) {
7385 mNoAnimActivities.add(r);
7386 }
7387 } else {
7388 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7389 }
7390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 mWindowManager.moveAppTokensToTop(moved);
7392 if (VALIDATE_TOKENS) {
7393 mWindowManager.validateAppTokens(mHistory);
7394 }
7395
Josh Bartel7f208742010-02-25 11:01:44 -06007396 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007397 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398 }
7399
Josh Bartel7f208742010-02-25 11:01:44 -06007400 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 resumeTopActivityLocked(null);
7402 }
7403
7404 public void moveTaskToBack(int task) {
7405 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7406 "moveTaskToBack()");
7407
7408 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007409 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7410 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7411 Binder.getCallingUid(), "Task to back")) {
7412 return;
7413 }
7414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007416 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417 Binder.restoreCallingIdentity(origId);
7418 }
7419 }
7420
7421 /**
7422 * Moves an activity, and all of the other activities within the same task, to the bottom
7423 * of the history stack. The activity's order within the task is unchanged.
7424 *
7425 * @param token A reference to the activity we wish to move
7426 * @param nonRoot If false then this only works if the activity is the root
7427 * of a task; if true it will work for any activity in a task.
7428 * @return Returns true if the move completed, false if not.
7429 */
7430 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7431 synchronized(this) {
7432 final long origId = Binder.clearCallingIdentity();
7433 int taskId = getTaskForActivityLocked(token, !nonRoot);
7434 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007435 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 }
7437 Binder.restoreCallingIdentity(origId);
7438 }
7439 return false;
7440 }
7441
7442 /**
7443 * Worker method for rearranging history stack. Implements the function of moving all
7444 * activities for a specific task (gathering them if disjoint) into a single group at the
7445 * bottom of the stack.
7446 *
7447 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7448 * to premeptively cancel the move.
7449 *
7450 * @param task The taskId to collect and move to the bottom.
7451 * @return Returns true if the move completed, false if not.
7452 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007453 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007454 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007455
7456 // If we have a watcher, preflight the move before committing to it. First check
7457 // for *other* available tasks, but if none are available, then try again allowing the
7458 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007459 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007460 HistoryRecord next = topRunningActivityLocked(null, task);
7461 if (next == null) {
7462 next = topRunningActivityLocked(null, 0);
7463 }
7464 if (next != null) {
7465 // ask watcher if this is allowed
7466 boolean moveOK = true;
7467 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007468 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007469 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007470 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 }
7472 if (!moveOK) {
7473 return false;
7474 }
7475 }
7476 }
7477
7478 ArrayList moved = new ArrayList();
7479
Joe Onorato8a9b2202010-02-26 18:56:32 -08007480 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007482
7483 final int N = mHistory.size();
7484 int bottom = 0;
7485 int pos = 0;
7486
7487 // Shift all activities with this task down to the bottom
7488 // of the stack, keeping them in the same internal order.
7489 while (pos < N) {
7490 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007491 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007492 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7493 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007494 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 mHistory.remove(pos);
7496 mHistory.add(bottom, r);
7497 moved.add(r);
7498 bottom++;
7499 }
7500 pos++;
7501 }
7502
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007503 if (reason != null &&
7504 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7505 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7506 HistoryRecord r = topRunningActivityLocked(null);
7507 if (r != null) {
7508 mNoAnimActivities.add(r);
7509 }
7510 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007511 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007513 mWindowManager.moveAppTokensToBottom(moved);
7514 if (VALIDATE_TOKENS) {
7515 mWindowManager.validateAppTokens(mHistory);
7516 }
7517
Josh Bartel7f208742010-02-25 11:01:44 -06007518 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007519 return true;
7520 }
7521
7522 public void moveTaskBackwards(int task) {
7523 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7524 "moveTaskBackwards()");
7525
7526 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007527 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7528 Binder.getCallingUid(), "Task backwards")) {
7529 return;
7530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007531 final long origId = Binder.clearCallingIdentity();
7532 moveTaskBackwardsLocked(task);
7533 Binder.restoreCallingIdentity(origId);
7534 }
7535 }
7536
7537 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007538 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007539 }
7540
7541 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7542 synchronized(this) {
7543 return getTaskForActivityLocked(token, onlyRoot);
7544 }
7545 }
7546
7547 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7548 final int N = mHistory.size();
7549 TaskRecord lastTask = null;
7550 for (int i=0; i<N; i++) {
7551 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7552 if (r == token) {
7553 if (!onlyRoot || lastTask != r.task) {
7554 return r.task.taskId;
7555 }
7556 return -1;
7557 }
7558 lastTask = r.task;
7559 }
7560
7561 return -1;
7562 }
7563
7564 /**
7565 * Returns the top activity in any existing task matching the given
7566 * Intent. Returns null if no such task is found.
7567 */
7568 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7569 ComponentName cls = intent.getComponent();
7570 if (info.targetActivity != null) {
7571 cls = new ComponentName(info.packageName, info.targetActivity);
7572 }
7573
7574 TaskRecord cp = null;
7575
7576 final int N = mHistory.size();
7577 for (int i=(N-1); i>=0; i--) {
7578 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7579 if (!r.finishing && r.task != cp
7580 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7581 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007582 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 // + "/aff=" + r.task.affinity + " to new cls="
7584 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7585 if (r.task.affinity != null) {
7586 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007587 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007588 return r;
7589 }
7590 } else if (r.task.intent != null
7591 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007592 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007593 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007594 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007595 return r;
7596 } else if (r.task.affinityIntent != null
7597 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007598 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007600 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007601 return r;
7602 }
7603 }
7604 }
7605
7606 return null;
7607 }
7608
7609 /**
7610 * Returns the first activity (starting from the top of the stack) that
7611 * is the same as the given activity. Returns null if no such activity
7612 * is found.
7613 */
7614 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7615 ComponentName cls = intent.getComponent();
7616 if (info.targetActivity != null) {
7617 cls = new ComponentName(info.packageName, info.targetActivity);
7618 }
7619
7620 final int N = mHistory.size();
7621 for (int i=(N-1); i>=0; i--) {
7622 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7623 if (!r.finishing) {
7624 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007625 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007627 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007628 return r;
7629 }
7630 }
7631 }
7632
7633 return null;
7634 }
7635
7636 public void finishOtherInstances(IBinder token, ComponentName className) {
7637 synchronized(this) {
7638 final long origId = Binder.clearCallingIdentity();
7639
7640 int N = mHistory.size();
7641 TaskRecord lastTask = null;
7642 for (int i=0; i<N; i++) {
7643 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7644 if (r.realActivity.equals(className)
7645 && r != token && lastTask != r.task) {
7646 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7647 null, "others")) {
7648 i--;
7649 N--;
7650 }
7651 }
7652 lastTask = r.task;
7653 }
7654
7655 Binder.restoreCallingIdentity(origId);
7656 }
7657 }
7658
7659 // =========================================================
7660 // THUMBNAILS
7661 // =========================================================
7662
7663 public void reportThumbnail(IBinder token,
7664 Bitmap thumbnail, CharSequence description) {
7665 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7666 final long origId = Binder.clearCallingIdentity();
7667 sendPendingThumbnail(null, token, thumbnail, description, true);
7668 Binder.restoreCallingIdentity(origId);
7669 }
7670
7671 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7672 Bitmap thumbnail, CharSequence description, boolean always) {
7673 TaskRecord task = null;
7674 ArrayList receivers = null;
7675
7676 //System.out.println("Send pending thumbnail: " + r);
7677
7678 synchronized(this) {
7679 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007680 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007681 if (index < 0) {
7682 return;
7683 }
7684 r = (HistoryRecord)mHistory.get(index);
7685 }
7686 if (thumbnail == null) {
7687 thumbnail = r.thumbnail;
7688 description = r.description;
7689 }
7690 if (thumbnail == null && !always) {
7691 // If there is no thumbnail, and this entry is not actually
7692 // going away, then abort for now and pick up the next
7693 // thumbnail we get.
7694 return;
7695 }
7696 task = r.task;
7697
7698 int N = mPendingThumbnails.size();
7699 int i=0;
7700 while (i<N) {
7701 PendingThumbnailsRecord pr =
7702 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7703 //System.out.println("Looking in " + pr.pendingRecords);
7704 if (pr.pendingRecords.remove(r)) {
7705 if (receivers == null) {
7706 receivers = new ArrayList();
7707 }
7708 receivers.add(pr);
7709 if (pr.pendingRecords.size() == 0) {
7710 pr.finished = true;
7711 mPendingThumbnails.remove(i);
7712 N--;
7713 continue;
7714 }
7715 }
7716 i++;
7717 }
7718 }
7719
7720 if (receivers != null) {
7721 final int N = receivers.size();
7722 for (int i=0; i<N; i++) {
7723 try {
7724 PendingThumbnailsRecord pr =
7725 (PendingThumbnailsRecord)receivers.get(i);
7726 pr.receiver.newThumbnail(
7727 task != null ? task.taskId : -1, thumbnail, description);
7728 if (pr.finished) {
7729 pr.receiver.finished();
7730 }
7731 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007732 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733 }
7734 }
7735 }
7736 }
7737
7738 // =========================================================
7739 // CONTENT PROVIDERS
7740 // =========================================================
7741
7742 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7743 List providers = null;
7744 try {
7745 providers = ActivityThread.getPackageManager().
7746 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007747 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007748 } catch (RemoteException ex) {
7749 }
7750 if (providers != null) {
7751 final int N = providers.size();
7752 for (int i=0; i<N; i++) {
7753 ProviderInfo cpi =
7754 (ProviderInfo)providers.get(i);
7755 ContentProviderRecord cpr =
7756 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7757 if (cpr == null) {
7758 cpr = new ContentProviderRecord(cpi, app.info);
7759 mProvidersByClass.put(cpi.name, cpr);
7760 }
7761 app.pubProviders.put(cpi.name, cpr);
7762 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007763 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007764 }
7765 }
7766 return providers;
7767 }
7768
7769 private final String checkContentProviderPermissionLocked(
7770 ProviderInfo cpi, ProcessRecord r, int mode) {
7771 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7772 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7773 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7774 cpi.exported ? -1 : cpi.applicationInfo.uid)
7775 == PackageManager.PERMISSION_GRANTED
7776 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7777 return null;
7778 }
7779 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7780 cpi.exported ? -1 : cpi.applicationInfo.uid)
7781 == PackageManager.PERMISSION_GRANTED) {
7782 return null;
7783 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007784
7785 PathPermission[] pps = cpi.pathPermissions;
7786 if (pps != null) {
7787 int i = pps.length;
7788 while (i > 0) {
7789 i--;
7790 PathPermission pp = pps[i];
7791 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7792 cpi.exported ? -1 : cpi.applicationInfo.uid)
7793 == PackageManager.PERMISSION_GRANTED
7794 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7795 return null;
7796 }
7797 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7798 cpi.exported ? -1 : cpi.applicationInfo.uid)
7799 == PackageManager.PERMISSION_GRANTED) {
7800 return null;
7801 }
7802 }
7803 }
7804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007805 String msg = "Permission Denial: opening provider " + cpi.name
7806 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7807 + ", uid=" + callingUid + ") requires "
7808 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007809 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 return msg;
7811 }
7812
7813 private final ContentProviderHolder getContentProviderImpl(
7814 IApplicationThread caller, String name) {
7815 ContentProviderRecord cpr;
7816 ProviderInfo cpi = null;
7817
7818 synchronized(this) {
7819 ProcessRecord r = null;
7820 if (caller != null) {
7821 r = getRecordForAppLocked(caller);
7822 if (r == null) {
7823 throw new SecurityException(
7824 "Unable to find app for caller " + caller
7825 + " (pid=" + Binder.getCallingPid()
7826 + ") when getting content provider " + name);
7827 }
7828 }
7829
7830 // First check if this content provider has been published...
7831 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7832 if (cpr != null) {
7833 cpi = cpr.info;
7834 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7835 return new ContentProviderHolder(cpi,
7836 cpi.readPermission != null
7837 ? cpi.readPermission : cpi.writePermission);
7838 }
7839
7840 if (r != null && cpr.canRunHere(r)) {
7841 // This provider has been published or is in the process
7842 // of being published... but it is also allowed to run
7843 // in the caller's process, so don't make a connection
7844 // and just let the caller instantiate its own instance.
7845 if (cpr.provider != null) {
7846 // don't give caller the provider object, it needs
7847 // to make its own.
7848 cpr = new ContentProviderRecord(cpr);
7849 }
7850 return cpr;
7851 }
7852
7853 final long origId = Binder.clearCallingIdentity();
7854
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007855 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856 // return it right away.
7857 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007858 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007859 "Adding provider requested by "
7860 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007861 + cpr.info.processName);
7862 Integer cnt = r.conProviders.get(cpr);
7863 if (cnt == null) {
7864 r.conProviders.put(cpr, new Integer(1));
7865 } else {
7866 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007868 cpr.clients.add(r);
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07007869 if (cpr.app != null && r.setAdj >= VISIBLE_APP_ADJ) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07007870 // If this is a visible app accessing the provider,
7871 // make sure to count it as being accessed and thus
7872 // back up on the LRU list. This is good because
7873 // content providers are often expensive to start.
7874 updateLruProcessLocked(cpr.app, false, true);
7875 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07007876 } else {
7877 cpr.externals++;
7878 }
7879
7880 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 updateOomAdjLocked(cpr.app);
7882 }
7883
7884 Binder.restoreCallingIdentity(origId);
7885
7886 } else {
7887 try {
7888 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007889 resolveContentProvider(name,
7890 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007891 } catch (RemoteException ex) {
7892 }
7893 if (cpi == null) {
7894 return null;
7895 }
7896
7897 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7898 return new ContentProviderHolder(cpi,
7899 cpi.readPermission != null
7900 ? cpi.readPermission : cpi.writePermission);
7901 }
7902
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007903 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7904 && !cpi.processName.equals("system")) {
7905 // If this content provider does not run in the system
7906 // process, and the system is not yet ready to run other
7907 // processes, then fail fast instead of hanging.
7908 throw new IllegalArgumentException(
7909 "Attempt to launch content provider before system ready");
7910 }
7911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007912 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7913 final boolean firstClass = cpr == null;
7914 if (firstClass) {
7915 try {
7916 ApplicationInfo ai =
7917 ActivityThread.getPackageManager().
7918 getApplicationInfo(
7919 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007920 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007921 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007922 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 + cpi.name);
7924 return null;
7925 }
7926 cpr = new ContentProviderRecord(cpi, ai);
7927 } catch (RemoteException ex) {
7928 // pm is in same process, this will never happen.
7929 }
7930 }
7931
7932 if (r != null && cpr.canRunHere(r)) {
7933 // If this is a multiprocess provider, then just return its
7934 // info and allow the caller to instantiate it. Only do
7935 // this if the provider is the same user as the caller's
7936 // process, or can run as root (so can be in any process).
7937 return cpr;
7938 }
7939
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007940 if (DEBUG_PROVIDER) {
7941 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007942 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007943 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007944 }
7945
7946 // This is single process, and our app is now connecting to it.
7947 // See if we are already in the process of launching this
7948 // provider.
7949 final int N = mLaunchingProviders.size();
7950 int i;
7951 for (i=0; i<N; i++) {
7952 if (mLaunchingProviders.get(i) == cpr) {
7953 break;
7954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 }
7956
7957 // If the provider is not already being launched, then get it
7958 // started.
7959 if (i >= N) {
7960 final long origId = Binder.clearCallingIdentity();
7961 ProcessRecord proc = startProcessLocked(cpi.processName,
7962 cpr.appInfo, false, 0, "content provider",
7963 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007964 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007965 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007966 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967 + cpi.applicationInfo.packageName + "/"
7968 + cpi.applicationInfo.uid + " for provider "
7969 + name + ": process is bad");
7970 return null;
7971 }
7972 cpr.launchingApp = proc;
7973 mLaunchingProviders.add(cpr);
7974 Binder.restoreCallingIdentity(origId);
7975 }
7976
7977 // Make sure the provider is published (the same provider class
7978 // may be published under multiple names).
7979 if (firstClass) {
7980 mProvidersByClass.put(cpi.name, cpr);
7981 }
7982 mProvidersByName.put(name, cpr);
7983
7984 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007985 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007986 "Adding provider requested by "
7987 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007988 + cpr.info.processName);
7989 Integer cnt = r.conProviders.get(cpr);
7990 if (cnt == null) {
7991 r.conProviders.put(cpr, new Integer(1));
7992 } else {
7993 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7994 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007995 cpr.clients.add(r);
7996 } else {
7997 cpr.externals++;
7998 }
7999 }
8000 }
8001
8002 // Wait for the provider to be published...
8003 synchronized (cpr) {
8004 while (cpr.provider == null) {
8005 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008006 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008007 + cpi.applicationInfo.packageName + "/"
8008 + cpi.applicationInfo.uid + " for provider "
8009 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008010 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008011 cpi.applicationInfo.packageName,
8012 cpi.applicationInfo.uid, name);
8013 return null;
8014 }
8015 try {
8016 cpr.wait();
8017 } catch (InterruptedException ex) {
8018 }
8019 }
8020 }
8021 return cpr;
8022 }
8023
8024 public final ContentProviderHolder getContentProvider(
8025 IApplicationThread caller, String name) {
8026 if (caller == null) {
8027 String msg = "null IApplicationThread when getting content provider "
8028 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008029 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008030 throw new SecurityException(msg);
8031 }
8032
8033 return getContentProviderImpl(caller, name);
8034 }
8035
8036 private ContentProviderHolder getContentProviderExternal(String name) {
8037 return getContentProviderImpl(null, name);
8038 }
8039
8040 /**
8041 * Drop a content provider from a ProcessRecord's bookkeeping
8042 * @param cpr
8043 */
8044 public void removeContentProvider(IApplicationThread caller, String name) {
8045 synchronized (this) {
8046 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
8047 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008048 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008049 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008050 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008051 return;
8052 }
8053 final ProcessRecord r = getRecordForAppLocked(caller);
8054 if (r == null) {
8055 throw new SecurityException(
8056 "Unable to find app for caller " + caller +
8057 " when removing content provider " + name);
8058 }
8059 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008060 ContentProviderRecord localCpr = (ContentProviderRecord)
8061 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008062 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008063 + r.info.processName + " from process "
8064 + localCpr.appInfo.processName);
8065 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008067 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008068 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 return;
8070 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008071 Integer cnt = r.conProviders.get(localCpr);
8072 if (cnt == null || cnt.intValue() <= 1) {
8073 localCpr.clients.remove(r);
8074 r.conProviders.remove(localCpr);
8075 } else {
8076 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008078 }
8079 updateOomAdjLocked();
8080 }
8081 }
8082
8083 private void removeContentProviderExternal(String name) {
8084 synchronized (this) {
8085 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
8086 if(cpr == null) {
8087 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008088 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008089 return;
8090 }
8091
8092 //update content provider record entry info
8093 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
8094 localCpr.externals--;
8095 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008096 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008097 }
8098 updateOomAdjLocked();
8099 }
8100 }
8101
8102 public final void publishContentProviders(IApplicationThread caller,
8103 List<ContentProviderHolder> providers) {
8104 if (providers == null) {
8105 return;
8106 }
8107
8108 synchronized(this) {
8109 final ProcessRecord r = getRecordForAppLocked(caller);
8110 if (r == null) {
8111 throw new SecurityException(
8112 "Unable to find app for caller " + caller
8113 + " (pid=" + Binder.getCallingPid()
8114 + ") when publishing content providers");
8115 }
8116
8117 final long origId = Binder.clearCallingIdentity();
8118
8119 final int N = providers.size();
8120 for (int i=0; i<N; i++) {
8121 ContentProviderHolder src = providers.get(i);
8122 if (src == null || src.info == null || src.provider == null) {
8123 continue;
8124 }
8125 ContentProviderRecord dst =
8126 (ContentProviderRecord)r.pubProviders.get(src.info.name);
8127 if (dst != null) {
8128 mProvidersByClass.put(dst.info.name, dst);
8129 String names[] = dst.info.authority.split(";");
8130 for (int j = 0; j < names.length; j++) {
8131 mProvidersByName.put(names[j], dst);
8132 }
8133
8134 int NL = mLaunchingProviders.size();
8135 int j;
8136 for (j=0; j<NL; j++) {
8137 if (mLaunchingProviders.get(j) == dst) {
8138 mLaunchingProviders.remove(j);
8139 j--;
8140 NL--;
8141 }
8142 }
8143 synchronized (dst) {
8144 dst.provider = src.provider;
8145 dst.app = r;
8146 dst.notifyAll();
8147 }
8148 updateOomAdjLocked(r);
8149 }
8150 }
8151
8152 Binder.restoreCallingIdentity(origId);
8153 }
8154 }
8155
8156 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008157 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008158 synchronized (mSelf) {
8159 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8160 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008161 if (providers != null) {
8162 for (int i=providers.size()-1; i>=0; i--) {
8163 ProviderInfo pi = (ProviderInfo)providers.get(i);
8164 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8165 Slog.w(TAG, "Not installing system proc provider " + pi.name
8166 + ": not system .apk");
8167 providers.remove(i);
8168 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008169 }
8170 }
8171 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008172 if (providers != null) {
8173 mSystemThread.installSystemProviders(providers);
8174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 }
8176
8177 // =========================================================
8178 // GLOBAL MANAGEMENT
8179 // =========================================================
8180
8181 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8182 ApplicationInfo info, String customProcess) {
8183 String proc = customProcess != null ? customProcess : info.processName;
8184 BatteryStatsImpl.Uid.Proc ps = null;
8185 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8186 synchronized (stats) {
8187 ps = stats.getProcessStatsLocked(info.uid, proc);
8188 }
8189 return new ProcessRecord(ps, thread, info, proc);
8190 }
8191
8192 final ProcessRecord addAppLocked(ApplicationInfo info) {
8193 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8194
8195 if (app == null) {
8196 app = newProcessRecordLocked(null, info, null);
8197 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008198 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008199 }
8200
8201 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8202 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8203 app.persistent = true;
8204 app.maxAdj = CORE_SERVER_ADJ;
8205 }
8206 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8207 mPersistentStartingProcesses.add(app);
8208 startProcessLocked(app, "added application", app.processName);
8209 }
8210
8211 return app;
8212 }
8213
8214 public void unhandledBack() {
8215 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8216 "unhandledBack()");
8217
8218 synchronized(this) {
8219 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008220 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008221 TAG, "Performing unhandledBack(): stack size = " + count);
8222 if (count > 1) {
8223 final long origId = Binder.clearCallingIdentity();
8224 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8225 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8226 Binder.restoreCallingIdentity(origId);
8227 }
8228 }
8229 }
8230
8231 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8232 String name = uri.getAuthority();
8233 ContentProviderHolder cph = getContentProviderExternal(name);
8234 ParcelFileDescriptor pfd = null;
8235 if (cph != null) {
8236 // We record the binder invoker's uid in thread-local storage before
8237 // going to the content provider to open the file. Later, in the code
8238 // that handles all permissions checks, we look for this uid and use
8239 // that rather than the Activity Manager's own uid. The effect is that
8240 // we do the check against the caller's permissions even though it looks
8241 // to the content provider like the Activity Manager itself is making
8242 // the request.
8243 sCallerIdentity.set(new Identity(
8244 Binder.getCallingPid(), Binder.getCallingUid()));
8245 try {
8246 pfd = cph.provider.openFile(uri, "r");
8247 } catch (FileNotFoundException e) {
8248 // do nothing; pfd will be returned null
8249 } finally {
8250 // Ensure that whatever happens, we clean up the identity state
8251 sCallerIdentity.remove();
8252 }
8253
8254 // We've got the fd now, so we're done with the provider.
8255 removeContentProviderExternal(name);
8256 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008257 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008258 }
8259 return pfd;
8260 }
8261
8262 public void goingToSleep() {
8263 synchronized(this) {
8264 mSleeping = true;
8265 mWindowManager.setEventDispatching(false);
8266
8267 if (mResumedActivity != null) {
8268 pauseIfSleepingLocked();
8269 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008270 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008271 }
8272 }
8273 }
8274
Dianne Hackborn55280a92009-05-07 15:53:46 -07008275 public boolean shutdown(int timeout) {
8276 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8277 != PackageManager.PERMISSION_GRANTED) {
8278 throw new SecurityException("Requires permission "
8279 + android.Manifest.permission.SHUTDOWN);
8280 }
8281
8282 boolean timedout = false;
8283
8284 synchronized(this) {
8285 mShuttingDown = true;
8286 mWindowManager.setEventDispatching(false);
8287
8288 if (mResumedActivity != null) {
8289 pauseIfSleepingLocked();
8290 final long endTime = System.currentTimeMillis() + timeout;
8291 while (mResumedActivity != null || mPausingActivity != null) {
8292 long delay = endTime - System.currentTimeMillis();
8293 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008294 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008295 timedout = true;
8296 break;
8297 }
8298 try {
8299 this.wait();
8300 } catch (InterruptedException e) {
8301 }
8302 }
8303 }
8304 }
8305
8306 mUsageStatsService.shutdown();
8307 mBatteryStatsService.shutdown();
8308
8309 return timedout;
8310 }
8311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008313 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008314 if (!mGoingToSleep.isHeld()) {
8315 mGoingToSleep.acquire();
8316 if (mLaunchingActivity.isHeld()) {
8317 mLaunchingActivity.release();
8318 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8319 }
8320 }
8321
8322 // If we are not currently pausing an activity, get the current
8323 // one to pause. If we are pausing one, we will just let that stuff
8324 // run and release the wake lock when all done.
8325 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008326 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8327 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 startPausingLocked(false, true);
8329 }
8330 }
8331 }
8332
8333 public void wakingUp() {
8334 synchronized(this) {
8335 if (mGoingToSleep.isHeld()) {
8336 mGoingToSleep.release();
8337 }
8338 mWindowManager.setEventDispatching(true);
8339 mSleeping = false;
8340 resumeTopActivityLocked(null);
8341 }
8342 }
8343
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008344 public void stopAppSwitches() {
8345 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8346 != PackageManager.PERMISSION_GRANTED) {
8347 throw new SecurityException("Requires permission "
8348 + android.Manifest.permission.STOP_APP_SWITCHES);
8349 }
8350
8351 synchronized(this) {
8352 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8353 + APP_SWITCH_DELAY_TIME;
8354 mDidAppSwitch = false;
8355 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8356 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8357 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8358 }
8359 }
8360
8361 public void resumeAppSwitches() {
8362 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8363 != PackageManager.PERMISSION_GRANTED) {
8364 throw new SecurityException("Requires permission "
8365 + android.Manifest.permission.STOP_APP_SWITCHES);
8366 }
8367
8368 synchronized(this) {
8369 // Note that we don't execute any pending app switches... we will
8370 // let those wait until either the timeout, or the next start
8371 // activity request.
8372 mAppSwitchesAllowedTime = 0;
8373 }
8374 }
8375
8376 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8377 String name) {
8378 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8379 return true;
8380 }
8381
8382 final int perm = checkComponentPermission(
8383 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8384 callingUid, -1);
8385 if (perm == PackageManager.PERMISSION_GRANTED) {
8386 return true;
8387 }
8388
Joe Onorato8a9b2202010-02-26 18:56:32 -08008389 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008390 return false;
8391 }
8392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008393 public void setDebugApp(String packageName, boolean waitForDebugger,
8394 boolean persistent) {
8395 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8396 "setDebugApp()");
8397
8398 // Note that this is not really thread safe if there are multiple
8399 // callers into it at the same time, but that's not a situation we
8400 // care about.
8401 if (persistent) {
8402 final ContentResolver resolver = mContext.getContentResolver();
8403 Settings.System.putString(
8404 resolver, Settings.System.DEBUG_APP,
8405 packageName);
8406 Settings.System.putInt(
8407 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8408 waitForDebugger ? 1 : 0);
8409 }
8410
8411 synchronized (this) {
8412 if (!persistent) {
8413 mOrigDebugApp = mDebugApp;
8414 mOrigWaitForDebugger = mWaitForDebugger;
8415 }
8416 mDebugApp = packageName;
8417 mWaitForDebugger = waitForDebugger;
8418 mDebugTransient = !persistent;
8419 if (packageName != null) {
8420 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008421 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008422 Binder.restoreCallingIdentity(origId);
8423 }
8424 }
8425 }
8426
8427 public void setAlwaysFinish(boolean enabled) {
8428 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8429 "setAlwaysFinish()");
8430
8431 Settings.System.putInt(
8432 mContext.getContentResolver(),
8433 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8434
8435 synchronized (this) {
8436 mAlwaysFinishActivities = enabled;
8437 }
8438 }
8439
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008440 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008441 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008442 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008444 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008445 }
8446 }
8447
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008448 public boolean isUserAMonkey() {
8449 // For now the fact that there is a controller implies
8450 // we have a monkey.
8451 synchronized (this) {
8452 return mController != null;
8453 }
8454 }
8455
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008456 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008457 synchronized (this) {
8458 mWatchers.register(watcher);
8459 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008460 }
8461
8462 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008463 synchronized (this) {
8464 mWatchers.unregister(watcher);
8465 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008466 }
8467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008468 public final void enterSafeMode() {
8469 synchronized(this) {
8470 // It only makes sense to do this before the system is ready
8471 // and started launching other packages.
8472 if (!mSystemReady) {
8473 try {
8474 ActivityThread.getPackageManager().enterSafeMode();
8475 } catch (RemoteException e) {
8476 }
8477
8478 View v = LayoutInflater.from(mContext).inflate(
8479 com.android.internal.R.layout.safe_mode, null);
8480 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8481 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8482 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8483 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8484 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8485 lp.format = v.getBackground().getOpacity();
8486 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8487 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8488 ((WindowManager)mContext.getSystemService(
8489 Context.WINDOW_SERVICE)).addView(v, lp);
8490 }
8491 }
8492 }
8493
8494 public void noteWakeupAlarm(IIntentSender sender) {
8495 if (!(sender instanceof PendingIntentRecord)) {
8496 return;
8497 }
8498 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8499 synchronized (stats) {
8500 if (mBatteryStatsService.isOnBattery()) {
8501 mBatteryStatsService.enforceCallingPermission();
8502 PendingIntentRecord rec = (PendingIntentRecord)sender;
8503 int MY_UID = Binder.getCallingUid();
8504 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8505 BatteryStatsImpl.Uid.Pkg pkg =
8506 stats.getPackageStatsLocked(uid, rec.key.packageName);
8507 pkg.incWakeupsLocked();
8508 }
8509 }
8510 }
8511
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008512 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008513 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008514 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008516 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008517 // XXX Note: don't acquire main activity lock here, because the window
8518 // manager calls in with its locks held.
8519
8520 boolean killed = false;
8521 synchronized (mPidsSelfLocked) {
8522 int[] types = new int[pids.length];
8523 int worstType = 0;
8524 for (int i=0; i<pids.length; i++) {
8525 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8526 if (proc != null) {
8527 int type = proc.setAdj;
8528 types[i] = type;
8529 if (type > worstType) {
8530 worstType = type;
8531 }
8532 }
8533 }
8534
8535 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8536 // then constrain it so we will kill all hidden procs.
8537 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8538 worstType = HIDDEN_APP_MIN_ADJ;
8539 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008540 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008541 for (int i=0; i<pids.length; i++) {
8542 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8543 if (proc == null) {
8544 continue;
8545 }
8546 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008547 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008548 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008549 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8550 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008551 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008552 proc.killedBackground = true;
8553 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 }
8555 }
8556 }
8557 return killed;
8558 }
8559
8560 public void reportPss(IApplicationThread caller, int pss) {
8561 Watchdog.PssRequestor req;
8562 String name;
8563 ProcessRecord callerApp;
8564 synchronized (this) {
8565 if (caller == null) {
8566 return;
8567 }
8568 callerApp = getRecordForAppLocked(caller);
8569 if (callerApp == null) {
8570 return;
8571 }
8572 callerApp.lastPss = pss;
8573 req = callerApp;
8574 name = callerApp.processName;
8575 }
8576 Watchdog.getInstance().reportPss(req, name, pss);
8577 if (!callerApp.persistent) {
8578 removeRequestedPss(callerApp);
8579 }
8580 }
8581
8582 public void requestPss(Runnable completeCallback) {
8583 ArrayList<ProcessRecord> procs;
8584 synchronized (this) {
8585 mRequestPssCallback = completeCallback;
8586 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008587 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8588 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008589 if (!proc.persistent) {
8590 mRequestPssList.add(proc);
8591 }
8592 }
8593 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8594 }
8595
8596 int oldPri = Process.getThreadPriority(Process.myTid());
8597 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8598 for (int i=procs.size()-1; i>=0; i--) {
8599 ProcessRecord proc = procs.get(i);
8600 proc.lastPss = 0;
8601 proc.requestPss();
8602 }
8603 Process.setThreadPriority(oldPri);
8604 }
8605
8606 void removeRequestedPss(ProcessRecord proc) {
8607 Runnable callback = null;
8608 synchronized (this) {
8609 if (mRequestPssList.remove(proc)) {
8610 if (mRequestPssList.size() == 0) {
8611 callback = mRequestPssCallback;
8612 mRequestPssCallback = null;
8613 }
8614 }
8615 }
8616
8617 if (callback != null) {
8618 callback.run();
8619 }
8620 }
8621
8622 public void collectPss(Watchdog.PssStats stats) {
8623 stats.mEmptyPss = 0;
8624 stats.mEmptyCount = 0;
8625 stats.mBackgroundPss = 0;
8626 stats.mBackgroundCount = 0;
8627 stats.mServicePss = 0;
8628 stats.mServiceCount = 0;
8629 stats.mVisiblePss = 0;
8630 stats.mVisibleCount = 0;
8631 stats.mForegroundPss = 0;
8632 stats.mForegroundCount = 0;
8633 stats.mNoPssCount = 0;
8634 synchronized (this) {
8635 int i;
8636 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8637 ? mProcDeaths.length : stats.mProcDeaths.length;
8638 int aggr = 0;
8639 for (i=0; i<NPD; i++) {
8640 aggr += mProcDeaths[i];
8641 stats.mProcDeaths[i] = aggr;
8642 }
8643 while (i<stats.mProcDeaths.length) {
8644 stats.mProcDeaths[i] = 0;
8645 i++;
8646 }
8647
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008648 for (i=mLruProcesses.size()-1; i>=0; i--) {
8649 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 if (proc.persistent) {
8651 continue;
8652 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008653 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008654 if (proc.lastPss == 0) {
8655 stats.mNoPssCount++;
8656 continue;
8657 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008658 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8659 if (proc.empty) {
8660 stats.mEmptyPss += proc.lastPss;
8661 stats.mEmptyCount++;
8662 } else {
8663 stats.mBackgroundPss += proc.lastPss;
8664 stats.mBackgroundCount++;
8665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008666 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8667 stats.mVisiblePss += proc.lastPss;
8668 stats.mVisibleCount++;
8669 } else {
8670 stats.mForegroundPss += proc.lastPss;
8671 stats.mForegroundCount++;
8672 }
8673 }
8674 }
8675 }
8676
8677 public final void startRunning(String pkg, String cls, String action,
8678 String data) {
8679 synchronized(this) {
8680 if (mStartRunning) {
8681 return;
8682 }
8683 mStartRunning = true;
8684 mTopComponent = pkg != null && cls != null
8685 ? new ComponentName(pkg, cls) : null;
8686 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8687 mTopData = data;
8688 if (!mSystemReady) {
8689 return;
8690 }
8691 }
8692
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008693 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008694 }
8695
8696 private void retrieveSettings() {
8697 final ContentResolver resolver = mContext.getContentResolver();
8698 String debugApp = Settings.System.getString(
8699 resolver, Settings.System.DEBUG_APP);
8700 boolean waitForDebugger = Settings.System.getInt(
8701 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8702 boolean alwaysFinishActivities = Settings.System.getInt(
8703 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8704
8705 Configuration configuration = new Configuration();
8706 Settings.System.getConfiguration(resolver, configuration);
8707
8708 synchronized (this) {
8709 mDebugApp = mOrigDebugApp = debugApp;
8710 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8711 mAlwaysFinishActivities = alwaysFinishActivities;
8712 // This happens before any activities are started, so we can
8713 // change mConfiguration in-place.
8714 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008715 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008716 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 }
8718 }
8719
8720 public boolean testIsSystemReady() {
8721 // no need to synchronize(this) just to read & return the value
8722 return mSystemReady;
8723 }
8724
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008725 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008726 // In the simulator, startRunning will never have been called, which
8727 // normally sets a few crucial variables. Do it here instead.
8728 if (!Process.supportsProcesses()) {
8729 mStartRunning = true;
8730 mTopAction = Intent.ACTION_MAIN;
8731 }
8732
8733 synchronized(this) {
8734 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008735 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008736 return;
8737 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008738
8739 // Check to see if there are any update receivers to run.
8740 if (!mDidUpdate) {
8741 if (mWaitingUpdate) {
8742 return;
8743 }
8744 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8745 List<ResolveInfo> ris = null;
8746 try {
8747 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8748 intent, null, 0);
8749 } catch (RemoteException e) {
8750 }
8751 if (ris != null) {
8752 for (int i=ris.size()-1; i>=0; i--) {
8753 if ((ris.get(i).activityInfo.applicationInfo.flags
8754 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8755 ris.remove(i);
8756 }
8757 }
8758 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8759 for (int i=0; i<ris.size(); i++) {
8760 ActivityInfo ai = ris.get(i).activityInfo;
8761 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8762 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008763 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008764 finisher = new IIntentReceiver.Stub() {
8765 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008766 String data, Bundle extras, boolean ordered,
8767 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008768 throws RemoteException {
8769 synchronized (ActivityManagerService.this) {
8770 mDidUpdate = true;
8771 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008772 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008773 }
8774 };
8775 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008776 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008777 broadcastIntentLocked(null, null, intent, null, finisher,
8778 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008779 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008780 mWaitingUpdate = true;
8781 }
8782 }
8783 }
8784 if (mWaitingUpdate) {
8785 return;
8786 }
8787 mDidUpdate = true;
8788 }
8789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008790 mSystemReady = true;
8791 if (!mStartRunning) {
8792 return;
8793 }
8794 }
8795
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008796 ArrayList<ProcessRecord> procsToKill = null;
8797 synchronized(mPidsSelfLocked) {
8798 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8799 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8800 if (!isAllowedWhileBooting(proc.info)){
8801 if (procsToKill == null) {
8802 procsToKill = new ArrayList<ProcessRecord>();
8803 }
8804 procsToKill.add(proc);
8805 }
8806 }
8807 }
8808
8809 if (procsToKill != null) {
8810 synchronized(this) {
8811 for (int i=procsToKill.size()-1; i>=0; i--) {
8812 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008813 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008814 removeProcessLocked(proc, true);
8815 }
8816 }
8817 }
8818
Joe Onorato8a9b2202010-02-26 18:56:32 -08008819 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008820 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008821 SystemClock.uptimeMillis());
8822
8823 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008824 // Make sure we have no pre-ready processes sitting around.
8825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008826 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8827 ResolveInfo ri = mContext.getPackageManager()
8828 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008829 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008830 CharSequence errorMsg = null;
8831 if (ri != null) {
8832 ActivityInfo ai = ri.activityInfo;
8833 ApplicationInfo app = ai.applicationInfo;
8834 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8835 mTopAction = Intent.ACTION_FACTORY_TEST;
8836 mTopData = null;
8837 mTopComponent = new ComponentName(app.packageName,
8838 ai.name);
8839 } else {
8840 errorMsg = mContext.getResources().getText(
8841 com.android.internal.R.string.factorytest_not_system);
8842 }
8843 } else {
8844 errorMsg = mContext.getResources().getText(
8845 com.android.internal.R.string.factorytest_no_action);
8846 }
8847 if (errorMsg != null) {
8848 mTopAction = null;
8849 mTopData = null;
8850 mTopComponent = null;
8851 Message msg = Message.obtain();
8852 msg.what = SHOW_FACTORY_ERROR_MSG;
8853 msg.getData().putCharSequence("msg", errorMsg);
8854 mHandler.sendMessage(msg);
8855 }
8856 }
8857 }
8858
8859 retrieveSettings();
8860
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008861 if (goingCallback != null) goingCallback.run();
8862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008863 synchronized (this) {
8864 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8865 try {
8866 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008867 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008868 if (apps != null) {
8869 int N = apps.size();
8870 int i;
8871 for (i=0; i<N; i++) {
8872 ApplicationInfo info
8873 = (ApplicationInfo)apps.get(i);
8874 if (info != null &&
8875 !info.packageName.equals("android")) {
8876 addAppLocked(info);
8877 }
8878 }
8879 }
8880 } catch (RemoteException ex) {
8881 // pm is in same process, this will never happen.
8882 }
8883 }
8884
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008885 // Start up initial activity.
8886 mBooting = true;
8887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008888 try {
8889 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8890 Message msg = Message.obtain();
8891 msg.what = SHOW_UID_ERROR_MSG;
8892 mHandler.sendMessage(msg);
8893 }
8894 } catch (RemoteException e) {
8895 }
8896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008897 resumeTopActivityLocked(null);
8898 }
8899 }
8900
Dan Egnorb7f03672009-12-09 16:22:32 -08008901 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008902 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008903 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008904 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008905 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008906 startAppProblemLocked(app);
8907 app.stopFreezingAllLocked();
8908 return handleAppCrashLocked(app);
8909 }
8910
Dan Egnorb7f03672009-12-09 16:22:32 -08008911 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008912 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008913 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008914 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008915 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8916 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008917 startAppProblemLocked(app);
8918 app.stopFreezingAllLocked();
8919 }
8920
8921 /**
8922 * Generate a process error record, suitable for attachment to a ProcessRecord.
8923 *
8924 * @param app The ProcessRecord in which the error occurred.
8925 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8926 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008927 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 * @param shortMsg Short message describing the crash.
8929 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008930 * @param stackTrace Full crash stack trace, may be null.
8931 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008932 * @return Returns a fully-formed AppErrorStateInfo record.
8933 */
8934 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008935 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008936 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008938 report.condition = condition;
8939 report.processName = app.processName;
8940 report.pid = app.pid;
8941 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008942 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008943 report.shortMsg = shortMsg;
8944 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008945 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008946
8947 return report;
8948 }
8949
Dan Egnor42471dd2010-01-07 17:25:22 -08008950 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008951 synchronized (this) {
8952 app.crashing = false;
8953 app.crashingReport = null;
8954 app.notResponding = false;
8955 app.notRespondingReport = null;
8956 if (app.anrDialog == fromDialog) {
8957 app.anrDialog = null;
8958 }
8959 if (app.waitDialog == fromDialog) {
8960 app.waitDialog = null;
8961 }
8962 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008963 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07008964 Slog.i(ActivityManagerService.TAG, "Killing "
8965 + app.processName + " (pid=" + app.pid + "): user's request");
8966 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
8967 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008968 Process.killProcess(app.pid);
8969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970 }
8971 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008972
Dan Egnorb7f03672009-12-09 16:22:32 -08008973 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008974 long now = SystemClock.uptimeMillis();
8975
8976 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8977 app.info.uid);
8978 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8979 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008980 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008981 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008982 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008983 app.info.processName, app.info.uid);
8984 killServicesLocked(app, false);
8985 for (int i=mHistory.size()-1; i>=0; i--) {
8986 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8987 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008988 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008989 + r.intent.getComponent().flattenToShortString());
8990 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8991 }
8992 }
8993 if (!app.persistent) {
8994 // We don't want to start this process again until the user
8995 // explicitly does so... but for persistent process, we really
8996 // need to keep it running. If a persistent process is actually
8997 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008998 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008999 app.info.processName);
9000 mBadProcesses.put(app.info.processName, app.info.uid, now);
9001 app.bad = true;
9002 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
9003 app.removed = true;
9004 removeProcessLocked(app, false);
9005 return false;
9006 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009007 } else {
9008 HistoryRecord r = topRunningActivityLocked(null);
9009 if (r.app == app) {
9010 // If the top running activity is from this crashing
9011 // process, then terminate it to avoid getting in a loop.
9012 Slog.w(TAG, " Force finishing activity "
9013 + r.intent.getComponent().flattenToShortString());
9014 int index = indexOfTokenLocked(r);
9015 finishActivityLocked(r, index,
9016 Activity.RESULT_CANCELED, null, "crashed");
9017 // Also terminate an activities below it that aren't yet
9018 // stopped, to avoid a situation where one will get
9019 // re-start our crashing activity once it gets resumed again.
9020 index--;
9021 if (index >= 0) {
9022 r = (HistoryRecord)mHistory.get(index);
9023 if (r.state == ActivityState.RESUMED
9024 || r.state == ActivityState.PAUSING
9025 || r.state == ActivityState.PAUSED) {
9026 if (!r.isHomeActivity) {
9027 Slog.w(TAG, " Force finishing activity "
9028 + r.intent.getComponent().flattenToShortString());
9029 finishActivityLocked(r, index,
9030 Activity.RESULT_CANCELED, null, "crashed");
9031 }
9032 }
9033 }
9034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009035 }
9036
9037 // Bump up the crash count of any services currently running in the proc.
9038 if (app.services.size() != 0) {
9039 // Any services running in the application need to be placed
9040 // back in the pending list.
9041 Iterator it = app.services.iterator();
9042 while (it.hasNext()) {
9043 ServiceRecord sr = (ServiceRecord)it.next();
9044 sr.crashCount++;
9045 }
9046 }
9047
9048 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9049 return true;
9050 }
9051
9052 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009053 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9054 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 skipCurrentReceiverLocked(app);
9056 }
9057
9058 void skipCurrentReceiverLocked(ProcessRecord app) {
9059 boolean reschedule = false;
9060 BroadcastRecord r = app.curReceiver;
9061 if (r != null) {
9062 // The current broadcast is waiting for this app's receiver
9063 // to be finished. Looks like that's not going to happen, so
9064 // let the broadcast continue.
9065 logBroadcastReceiverDiscard(r);
9066 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9067 r.resultExtras, r.resultAbort, true);
9068 reschedule = true;
9069 }
9070 r = mPendingBroadcast;
9071 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009072 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073 "skip & discard pending app " + r);
9074 logBroadcastReceiverDiscard(r);
9075 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9076 r.resultExtras, r.resultAbort, true);
9077 reschedule = true;
9078 }
9079 if (reschedule) {
9080 scheduleBroadcastsLocked();
9081 }
9082 }
9083
Dan Egnor60d87622009-12-16 16:32:58 -08009084 /**
9085 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9086 * The application process will exit immediately after this call returns.
9087 * @param app object of the crashing app, null for the system server
9088 * @param crashInfo describing the exception
9089 */
9090 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9091 ProcessRecord r = findAppProcess(app);
9092
9093 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9094 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009095 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009096 crashInfo.exceptionClassName,
9097 crashInfo.exceptionMessage,
9098 crashInfo.throwFileName,
9099 crashInfo.throwLineNumber);
9100
Dan Egnor42471dd2010-01-07 17:25:22 -08009101 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009102
9103 crashApplication(r, crashInfo);
9104 }
9105
9106 /**
9107 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9108 * @param app object of the crashing app, null for the system server
9109 * @param tag reported by the caller
9110 * @param crashInfo describing the context of the error
9111 * @return true if the process should exit immediately (WTF is fatal)
9112 */
9113 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009114 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009115 ProcessRecord r = findAppProcess(app);
9116
9117 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9118 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009119 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009120 tag, crashInfo.exceptionMessage);
9121
Dan Egnor42471dd2010-01-07 17:25:22 -08009122 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009123
Doug Zongker43866e02010-01-07 12:09:54 -08009124 if (Settings.Secure.getInt(mContext.getContentResolver(),
9125 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009126 crashApplication(r, crashInfo);
9127 return true;
9128 } else {
9129 return false;
9130 }
9131 }
9132
9133 /**
9134 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9135 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9136 */
9137 private ProcessRecord findAppProcess(IBinder app) {
9138 if (app == null) {
9139 return null;
9140 }
9141
9142 synchronized (this) {
9143 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9144 final int NA = apps.size();
9145 for (int ia=0; ia<NA; ia++) {
9146 ProcessRecord p = apps.valueAt(ia);
9147 if (p.thread != null && p.thread.asBinder() == app) {
9148 return p;
9149 }
9150 }
9151 }
9152
Joe Onorato8a9b2202010-02-26 18:56:32 -08009153 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009154 return null;
9155 }
9156 }
9157
9158 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009159 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009160 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009161 * @param process which caused the error, null means the system server
9162 * @param activity which triggered the error, null if unknown
9163 * @param parent activity related to the error, null if unknown
9164 * @param subject line related to the error, null if absent
9165 * @param report in long form describing the error, null if absent
9166 * @param logFile to include in the report, null if none
9167 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009168 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009169 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009170 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9171 final String report, final File logFile,
9172 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009173 // NOTE -- this must never acquire the ActivityManagerService lock,
9174 // otherwise the watchdog may be prevented from resetting the system.
9175
Dan Egnora455d192010-03-12 08:52:28 -08009176 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009177 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009178 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009179 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009180 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009181 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009182 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009183 }
9184
Dan Egnora455d192010-03-12 08:52:28 -08009185 final String dropboxTag = prefix + eventType;
9186 final DropBoxManager dbox = (DropBoxManager)
9187 mContext.getSystemService(Context.DROPBOX_SERVICE);
9188
9189 // Exit early if the dropbox isn't configured to accept this report type.
9190 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9191
9192 final StringBuilder sb = new StringBuilder(1024);
9193 if (process == null || process.pid == MY_PID) {
9194 sb.append("Process: system_server\n");
9195 } else {
9196 sb.append("Process: ").append(process.processName).append("\n");
9197 }
9198 if (process != null) {
9199 int flags = process.info.flags;
9200 IPackageManager pm = ActivityThread.getPackageManager();
9201 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9202 for (String pkg : process.pkgList) {
9203 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009204 try {
Dan Egnora455d192010-03-12 08:52:28 -08009205 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9206 if (pi != null) {
9207 sb.append(" v").append(pi.versionCode);
9208 if (pi.versionName != null) {
9209 sb.append(" (").append(pi.versionName).append(")");
9210 }
9211 }
9212 } catch (RemoteException e) {
9213 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009214 }
Dan Egnora455d192010-03-12 08:52:28 -08009215 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009216 }
Dan Egnora455d192010-03-12 08:52:28 -08009217 }
9218 if (activity != null) {
9219 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9220 }
9221 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9222 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9223 }
9224 if (parent != null && parent != activity) {
9225 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9226 }
9227 if (subject != null) {
9228 sb.append("Subject: ").append(subject).append("\n");
9229 }
9230 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9231 sb.append("\n");
9232
9233 // Do the rest in a worker thread to avoid blocking the caller on I/O
9234 // (After this point, we shouldn't access AMS internal data structures.)
9235 Thread worker = new Thread("Error dump: " + dropboxTag) {
9236 @Override
9237 public void run() {
9238 if (report != null) {
9239 sb.append(report);
9240 }
9241 if (logFile != null) {
9242 try {
9243 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9244 } catch (IOException e) {
9245 Slog.e(TAG, "Error reading " + logFile, e);
9246 }
9247 }
9248 if (crashInfo != null && crashInfo.stackTrace != null) {
9249 sb.append(crashInfo.stackTrace);
9250 }
9251
9252 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9253 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9254 if (lines > 0) {
9255 sb.append("\n");
9256
9257 // Merge several logcat streams, and take the last N lines
9258 InputStreamReader input = null;
9259 try {
9260 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9261 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9262 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9263
9264 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9265 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9266 input = new InputStreamReader(logcat.getInputStream());
9267
9268 int num;
9269 char[] buf = new char[8192];
9270 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9271 } catch (IOException e) {
9272 Slog.e(TAG, "Error running logcat", e);
9273 } finally {
9274 if (input != null) try { input.close(); } catch (IOException e) {}
9275 }
9276 }
9277
9278 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009279 }
Dan Egnora455d192010-03-12 08:52:28 -08009280 };
9281
9282 if (process == null || process.pid == MY_PID) {
9283 worker.run(); // We may be about to die -- need to run this synchronously
9284 } else {
9285 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009286 }
9287 }
9288
9289 /**
9290 * Bring up the "unexpected error" dialog box for a crashing app.
9291 * Deal with edge cases (intercepts from instrumented applications,
9292 * ActivityController, error intent receivers, that sort of thing).
9293 * @param r the application crashing
9294 * @param crashInfo describing the failure
9295 */
9296 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009297 long timeMillis = System.currentTimeMillis();
9298 String shortMsg = crashInfo.exceptionClassName;
9299 String longMsg = crashInfo.exceptionMessage;
9300 String stackTrace = crashInfo.stackTrace;
9301 if (shortMsg != null && longMsg != null) {
9302 longMsg = shortMsg + ": " + longMsg;
9303 } else if (shortMsg != null) {
9304 longMsg = shortMsg;
9305 }
9306
Dan Egnor60d87622009-12-16 16:32:58 -08009307 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009308 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009309 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009310 try {
9311 String name = r != null ? r.processName : null;
9312 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009313 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009314 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009315 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009316 + " at watcher's request");
9317 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009318 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009319 }
9320 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009321 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009322 }
9323 }
9324
9325 final long origId = Binder.clearCallingIdentity();
9326
9327 // If this process is running instrumentation, finish it.
9328 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009329 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009331 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9332 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009333 Bundle info = new Bundle();
9334 info.putString("shortMsg", shortMsg);
9335 info.putString("longMsg", longMsg);
9336 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9337 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009338 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009339 }
9340
Dan Egnor60d87622009-12-16 16:32:58 -08009341 // If we can't identify the process or it's already exceeded its crash quota,
9342 // quit right away without showing a crash dialog.
9343 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009344 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009345 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009346 }
9347
9348 Message msg = Message.obtain();
9349 msg.what = SHOW_ERROR_MSG;
9350 HashMap data = new HashMap();
9351 data.put("result", result);
9352 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009353 msg.obj = data;
9354 mHandler.sendMessage(msg);
9355
9356 Binder.restoreCallingIdentity(origId);
9357 }
9358
9359 int res = result.get();
9360
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009361 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009362 synchronized (this) {
9363 if (r != null) {
9364 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9365 SystemClock.uptimeMillis());
9366 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009367 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009368 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009369 }
9370 }
9371
9372 if (appErrorIntent != null) {
9373 try {
9374 mContext.startActivity(appErrorIntent);
9375 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009376 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009377 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009379 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009380
9381 Intent createAppErrorIntentLocked(ProcessRecord r,
9382 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9383 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009384 if (report == null) {
9385 return null;
9386 }
9387 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9388 result.setComponent(r.errorReportReceiver);
9389 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9390 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9391 return result;
9392 }
9393
Dan Egnorb7f03672009-12-09 16:22:32 -08009394 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9395 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009396 if (r.errorReportReceiver == null) {
9397 return null;
9398 }
9399
9400 if (!r.crashing && !r.notResponding) {
9401 return null;
9402 }
9403
Dan Egnorb7f03672009-12-09 16:22:32 -08009404 ApplicationErrorReport report = new ApplicationErrorReport();
9405 report.packageName = r.info.packageName;
9406 report.installerPackageName = r.errorReportReceiver.getPackageName();
9407 report.processName = r.processName;
9408 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009409 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009410
Dan Egnorb7f03672009-12-09 16:22:32 -08009411 if (r.crashing) {
9412 report.type = ApplicationErrorReport.TYPE_CRASH;
9413 report.crashInfo = crashInfo;
9414 } else if (r.notResponding) {
9415 report.type = ApplicationErrorReport.TYPE_ANR;
9416 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009417
Dan Egnorb7f03672009-12-09 16:22:32 -08009418 report.anrInfo.activity = r.notRespondingReport.tag;
9419 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9420 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009421 }
9422
Dan Egnorb7f03672009-12-09 16:22:32 -08009423 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009424 }
9425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009426 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9427 // assume our apps are happy - lazy create the list
9428 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9429
9430 synchronized (this) {
9431
9432 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009433 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9434 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009435 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9436 // This one's in trouble, so we'll generate a report for it
9437 // crashes are higher priority (in case there's a crash *and* an anr)
9438 ActivityManager.ProcessErrorStateInfo report = null;
9439 if (app.crashing) {
9440 report = app.crashingReport;
9441 } else if (app.notResponding) {
9442 report = app.notRespondingReport;
9443 }
9444
9445 if (report != null) {
9446 if (errList == null) {
9447 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9448 }
9449 errList.add(report);
9450 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009451 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 " crashing = " + app.crashing +
9453 " notResponding = " + app.notResponding);
9454 }
9455 }
9456 }
9457 }
9458
9459 return errList;
9460 }
9461
9462 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9463 // Lazy instantiation of list
9464 List<ActivityManager.RunningAppProcessInfo> runList = null;
9465 synchronized (this) {
9466 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009467 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9468 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009469 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9470 // Generate process state info for running application
9471 ActivityManager.RunningAppProcessInfo currApp =
9472 new ActivityManager.RunningAppProcessInfo(app.processName,
9473 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009474 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009475 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009476 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009477 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9478 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9479 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009480 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9481 } else if (adj >= HOME_APP_ADJ) {
9482 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9483 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009484 } else if (adj >= SECONDARY_SERVER_ADJ) {
9485 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9486 } else if (adj >= VISIBLE_APP_ADJ) {
9487 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9488 } else {
9489 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9490 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009491 currApp.importanceReasonCode = app.adjTypeCode;
9492 if (app.adjSource instanceof ProcessRecord) {
9493 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9494 } else if (app.adjSource instanceof HistoryRecord) {
9495 HistoryRecord r = (HistoryRecord)app.adjSource;
9496 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9497 }
9498 if (app.adjTarget instanceof ComponentName) {
9499 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9500 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009501 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009502 // + " lru=" + currApp.lru);
9503 if (runList == null) {
9504 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9505 }
9506 runList.add(currApp);
9507 }
9508 }
9509 }
9510 return runList;
9511 }
9512
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009513 public List<ApplicationInfo> getRunningExternalApplications() {
9514 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9515 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9516 if (runningApps != null && runningApps.size() > 0) {
9517 Set<String> extList = new HashSet<String>();
9518 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9519 if (app.pkgList != null) {
9520 for (String pkg : app.pkgList) {
9521 extList.add(pkg);
9522 }
9523 }
9524 }
9525 IPackageManager pm = ActivityThread.getPackageManager();
9526 for (String pkg : extList) {
9527 try {
9528 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9529 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9530 retList.add(info);
9531 }
9532 } catch (RemoteException e) {
9533 }
9534 }
9535 }
9536 return retList;
9537 }
9538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009539 @Override
9540 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009541 if (checkCallingPermission(android.Manifest.permission.DUMP)
9542 != PackageManager.PERMISSION_GRANTED) {
9543 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9544 + Binder.getCallingPid()
9545 + ", uid=" + Binder.getCallingUid()
9546 + " without permission "
9547 + android.Manifest.permission.DUMP);
9548 return;
9549 }
9550
9551 boolean dumpAll = false;
9552
9553 int opti = 0;
9554 while (opti < args.length) {
9555 String opt = args[opti];
9556 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9557 break;
9558 }
9559 opti++;
9560 if ("-a".equals(opt)) {
9561 dumpAll = true;
9562 } else if ("-h".equals(opt)) {
9563 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009564 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009565 pw.println(" cmd may be one of:");
9566 pw.println(" activities: activity stack state");
9567 pw.println(" broadcasts: broadcast state");
9568 pw.println(" intents: pending intent state");
9569 pw.println(" processes: process state");
9570 pw.println(" providers: content provider state");
9571 pw.println(" services: service state");
9572 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009573 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009574 } else {
9575 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009576 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009577 }
9578
9579 // Is the caller requesting to dump a particular piece of data?
9580 if (opti < args.length) {
9581 String cmd = args[opti];
9582 opti++;
9583 if ("activities".equals(cmd) || "a".equals(cmd)) {
9584 synchronized (this) {
9585 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009586 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009587 return;
9588 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9589 synchronized (this) {
9590 dumpBroadcastsLocked(fd, pw, args, opti, true);
9591 }
9592 return;
9593 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9594 synchronized (this) {
9595 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9596 }
9597 return;
9598 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9599 synchronized (this) {
9600 dumpProcessesLocked(fd, pw, args, opti, true);
9601 }
9602 return;
9603 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9604 synchronized (this) {
9605 dumpProvidersLocked(fd, pw, args, opti, true);
9606 }
9607 return;
9608 } else if ("service".equals(cmd)) {
9609 dumpService(fd, pw, args, opti, true);
9610 return;
9611 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9612 synchronized (this) {
9613 dumpServicesLocked(fd, pw, args, opti, true);
9614 }
9615 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009616 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009617 }
9618
9619 // No piece of data specified, dump everything.
9620 synchronized (this) {
9621 boolean needSep;
9622 if (dumpAll) {
9623 pw.println("Providers in Current Activity Manager State:");
9624 }
9625 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9626 if (needSep) {
9627 pw.println(" ");
9628 }
9629 if (dumpAll) {
9630 pw.println("-------------------------------------------------------------------------------");
9631 pw.println("Broadcasts in Current Activity Manager State:");
9632 }
9633 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9634 if (needSep) {
9635 pw.println(" ");
9636 }
9637 if (dumpAll) {
9638 pw.println("-------------------------------------------------------------------------------");
9639 pw.println("Services in Current Activity Manager State:");
9640 }
9641 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9642 if (needSep) {
9643 pw.println(" ");
9644 }
9645 if (dumpAll) {
9646 pw.println("-------------------------------------------------------------------------------");
9647 pw.println("PendingIntents in Current Activity Manager State:");
9648 }
9649 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9650 if (needSep) {
9651 pw.println(" ");
9652 }
9653 if (dumpAll) {
9654 pw.println("-------------------------------------------------------------------------------");
9655 pw.println("Activities in Current Activity Manager State:");
9656 }
9657 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9658 if (needSep) {
9659 pw.println(" ");
9660 }
9661 if (dumpAll) {
9662 pw.println("-------------------------------------------------------------------------------");
9663 pw.println("Processes in Current Activity Manager State:");
9664 }
9665 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9666 }
9667 }
9668
9669 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9670 int opti, boolean dumpAll, boolean needHeader) {
9671 if (needHeader) {
9672 pw.println(" Activity stack:");
9673 }
9674 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9675 pw.println(" ");
9676 pw.println(" Running activities (most recent first):");
9677 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9678 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009679 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009680 pw.println(" Activities waiting for another to become visible:");
9681 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9682 }
9683 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009684 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009685 pw.println(" Activities waiting to stop:");
9686 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9687 }
9688 if (mFinishingActivities.size() > 0) {
9689 pw.println(" ");
9690 pw.println(" Activities waiting to finish:");
9691 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9692 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009693
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009694 pw.println(" ");
9695 pw.println(" mPausingActivity: " + mPausingActivity);
9696 pw.println(" mResumedActivity: " + mResumedActivity);
9697 pw.println(" mFocusedActivity: " + mFocusedActivity);
9698 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009699
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009700 if (dumpAll && mRecentTasks.size() > 0) {
9701 pw.println(" ");
9702 pw.println("Recent tasks in Current Activity Manager State:");
9703
9704 final int N = mRecentTasks.size();
9705 for (int i=0; i<N; i++) {
9706 TaskRecord tr = mRecentTasks.get(i);
9707 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9708 pw.println(tr);
9709 mRecentTasks.get(i).dump(pw, " ");
9710 }
9711 }
9712
9713 pw.println(" ");
9714 pw.println(" mCurTask: " + mCurTask);
9715
9716 return true;
9717 }
9718
9719 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9720 int opti, boolean dumpAll) {
9721 boolean needSep = false;
9722 int numPers = 0;
9723
9724 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009725 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9726 final int NA = procs.size();
9727 for (int ia=0; ia<NA; ia++) {
9728 if (!needSep) {
9729 pw.println(" All known processes:");
9730 needSep = true;
9731 }
9732 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009733 pw.print(r.persistent ? " *PERS*" : " *APP*");
9734 pw.print(" UID "); pw.print(procs.keyAt(ia));
9735 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009736 r.dump(pw, " ");
9737 if (r.persistent) {
9738 numPers++;
9739 }
9740 }
9741 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009742 }
9743
9744 if (mLruProcesses.size() > 0) {
9745 if (needSep) pw.println(" ");
9746 needSep = true;
9747 pw.println(" Running processes (most recent first):");
9748 dumpProcessList(pw, this, mLruProcesses, " ",
9749 "App ", "PERS", true);
9750 needSep = true;
9751 }
9752
9753 synchronized (mPidsSelfLocked) {
9754 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009755 if (needSep) pw.println(" ");
9756 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009757 pw.println(" PID mappings:");
9758 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9759 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9760 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009761 }
9762 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009763 }
9764
9765 if (mForegroundProcesses.size() > 0) {
9766 if (needSep) pw.println(" ");
9767 needSep = true;
9768 pw.println(" Foreground Processes:");
9769 for (int i=0; i<mForegroundProcesses.size(); i++) {
9770 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9771 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009772 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009773 }
9774
9775 if (mPersistentStartingProcesses.size() > 0) {
9776 if (needSep) pw.println(" ");
9777 needSep = true;
9778 pw.println(" Persisent processes that are starting:");
9779 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9780 "Starting Norm", "Restarting PERS", false);
9781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009783 if (mStartingProcesses.size() > 0) {
9784 if (needSep) pw.println(" ");
9785 needSep = true;
9786 pw.println(" Processes that are starting:");
9787 dumpProcessList(pw, this, mStartingProcesses, " ",
9788 "Starting Norm", "Starting PERS", false);
9789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009790
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009791 if (mRemovedProcesses.size() > 0) {
9792 if (needSep) pw.println(" ");
9793 needSep = true;
9794 pw.println(" Processes that are being removed:");
9795 dumpProcessList(pw, this, mRemovedProcesses, " ",
9796 "Removed Norm", "Removed PERS", false);
9797 }
9798
9799 if (mProcessesOnHold.size() > 0) {
9800 if (needSep) pw.println(" ");
9801 needSep = true;
9802 pw.println(" Processes that are on old until the system is ready:");
9803 dumpProcessList(pw, this, mProcessesOnHold, " ",
9804 "OnHold Norm", "OnHold PERS", false);
9805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009806
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009807 if (mProcessesToGc.size() > 0) {
9808 if (needSep) pw.println(" ");
9809 needSep = true;
9810 pw.println(" Processes that are waiting to GC:");
9811 long now = SystemClock.uptimeMillis();
9812 for (int i=0; i<mProcessesToGc.size(); i++) {
9813 ProcessRecord proc = mProcessesToGc.get(i);
9814 pw.print(" Process "); pw.println(proc);
9815 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9816 pw.print(", last gced=");
9817 pw.print(now-proc.lastRequestedGc);
9818 pw.print(" ms ago, last lowMem=");
9819 pw.print(now-proc.lastLowMemory);
9820 pw.println(" ms ago");
9821
9822 }
9823 }
9824
9825 if (mProcessCrashTimes.getMap().size() > 0) {
9826 if (needSep) pw.println(" ");
9827 needSep = true;
9828 pw.println(" Time since processes crashed:");
9829 long now = SystemClock.uptimeMillis();
9830 for (Map.Entry<String, SparseArray<Long>> procs
9831 : mProcessCrashTimes.getMap().entrySet()) {
9832 SparseArray<Long> uids = procs.getValue();
9833 final int N = uids.size();
9834 for (int i=0; i<N; i++) {
9835 pw.print(" Process "); pw.print(procs.getKey());
9836 pw.print(" uid "); pw.print(uids.keyAt(i));
9837 pw.print(": last crashed ");
9838 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009839 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009840 }
9841 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009842 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009843
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009844 if (mBadProcesses.getMap().size() > 0) {
9845 if (needSep) pw.println(" ");
9846 needSep = true;
9847 pw.println(" Bad processes:");
9848 for (Map.Entry<String, SparseArray<Long>> procs
9849 : mBadProcesses.getMap().entrySet()) {
9850 SparseArray<Long> uids = procs.getValue();
9851 final int N = uids.size();
9852 for (int i=0; i<N; i++) {
9853 pw.print(" Bad process "); pw.print(procs.getKey());
9854 pw.print(" uid "); pw.print(uids.keyAt(i));
9855 pw.print(": crashed at time ");
9856 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009857 }
9858 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009861 pw.println(" ");
9862 pw.println(" mHomeProcess: " + mHomeProcess);
9863 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07009864 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009865 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9866 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9867 || mOrigWaitForDebugger) {
9868 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9869 + " mDebugTransient=" + mDebugTransient
9870 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9871 }
9872 if (mAlwaysFinishActivities || mController != null) {
9873 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9874 + " mController=" + mController);
9875 }
9876 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009877 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009878 pw.println(" mStartRunning=" + mStartRunning
9879 + " mSystemReady=" + mSystemReady
9880 + " mBooting=" + mBooting
9881 + " mBooted=" + mBooted
9882 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009883 pw.println(" mGoingToSleep=" + mGoingToSleep);
9884 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07009885 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009886 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009887
9888 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009889 }
9890
9891 /**
9892 * There are three ways to call this:
9893 * - no service specified: dump all the services
9894 * - a flattened component name that matched an existing service was specified as the
9895 * first arg: dump that one service
9896 * - the first arg isn't the flattened component name of an existing service:
9897 * dump all services whose component contains the first arg as a substring
9898 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009899 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9900 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901 String[] newArgs;
9902 String componentNameString;
9903 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009904 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 componentNameString = null;
9906 newArgs = EMPTY_STRING_ARRAY;
9907 r = null;
9908 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009909 componentNameString = args[opti];
9910 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009911 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9912 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009913 newArgs = new String[args.length - opti];
9914 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009915 }
9916
9917 if (r != null) {
9918 dumpService(fd, pw, r, newArgs);
9919 } else {
9920 for (ServiceRecord r1 : mServices.values()) {
9921 if (componentNameString == null
9922 || r1.name.flattenToString().contains(componentNameString)) {
9923 dumpService(fd, pw, r1, newArgs);
9924 }
9925 }
9926 }
9927 }
9928
9929 /**
9930 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9931 * there is a thread associated with the service.
9932 */
9933 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9934 pw.println(" Service " + r.name.flattenToString());
9935 if (r.app != null && r.app.thread != null) {
9936 try {
9937 // flush anything that is already in the PrintWriter since the thread is going
9938 // to write to the file descriptor directly
9939 pw.flush();
9940 r.app.thread.dumpService(fd, r, args);
9941 pw.print("\n");
9942 } catch (RemoteException e) {
9943 pw.println("got a RemoteException while dumping the service");
9944 }
9945 }
9946 }
9947
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009948 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9949 int opti, boolean dumpAll) {
9950 boolean needSep = false;
9951
9952 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009953 if (mRegisteredReceivers.size() > 0) {
9954 pw.println(" ");
9955 pw.println(" Registered Receivers:");
9956 Iterator it = mRegisteredReceivers.values().iterator();
9957 while (it.hasNext()) {
9958 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009959 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009960 r.dump(pw, " ");
9961 }
9962 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009964 pw.println(" ");
9965 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009966 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009967 needSep = true;
9968 }
9969
9970 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9971 || mPendingBroadcast != null) {
9972 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009973 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009974 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009975 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009976 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9977 pw.println(" Broadcast #" + i + ":");
9978 mParallelBroadcasts.get(i).dump(pw, " ");
9979 }
9980 if (mOrderedBroadcasts.size() > 0) {
9981 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07009982 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009983 }
9984 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9985 pw.println(" Serialized Broadcast #" + i + ":");
9986 mOrderedBroadcasts.get(i).dump(pw, " ");
9987 }
9988 pw.println(" ");
9989 pw.println(" Pending broadcast:");
9990 if (mPendingBroadcast != null) {
9991 mPendingBroadcast.dump(pw, " ");
9992 } else {
9993 pw.println(" (null)");
9994 }
9995 needSep = true;
9996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009997
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009998 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009999 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -080010000 pw.println(" Historical broadcasts:");
10001 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
10002 BroadcastRecord r = mBroadcastHistory[i];
10003 if (r == null) {
10004 break;
10005 }
10006 pw.println(" Historical Broadcast #" + i + ":");
10007 r.dump(pw, " ");
10008 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010009 needSep = true;
10010 }
10011
10012 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010013 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010014 pw.println(" Sticky broadcasts:");
10015 StringBuilder sb = new StringBuilder(128);
10016 for (Map.Entry<String, ArrayList<Intent>> ent
10017 : mStickyBroadcasts.entrySet()) {
10018 pw.print(" * Sticky action "); pw.print(ent.getKey());
10019 pw.println(":");
10020 ArrayList<Intent> intents = ent.getValue();
10021 final int N = intents.size();
10022 for (int i=0; i<N; i++) {
10023 sb.setLength(0);
10024 sb.append(" Intent: ");
10025 intents.get(i).toShortString(sb, true, false);
10026 pw.println(sb.toString());
10027 Bundle bundle = intents.get(i).getExtras();
10028 if (bundle != null) {
10029 pw.print(" ");
10030 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010031 }
10032 }
10033 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010034 needSep = true;
10035 }
10036
10037 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010039 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010040 pw.println(" mHandler:");
10041 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010042 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010043 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010044
10045 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010046 }
10047
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010048 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10049 int opti, boolean dumpAll) {
10050 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010051
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010052 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053 if (mServices.size() > 0) {
10054 pw.println(" Active services:");
10055 Iterator<ServiceRecord> it = mServices.values().iterator();
10056 while (it.hasNext()) {
10057 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010058 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010059 r.dump(pw, " ");
10060 }
10061 needSep = true;
10062 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010065 if (mPendingServices.size() > 0) {
10066 if (needSep) pw.println(" ");
10067 pw.println(" Pending services:");
10068 for (int i=0; i<mPendingServices.size(); i++) {
10069 ServiceRecord r = mPendingServices.get(i);
10070 pw.print(" * Pending "); pw.println(r);
10071 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010072 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010073 needSep = true;
10074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010076 if (mRestartingServices.size() > 0) {
10077 if (needSep) pw.println(" ");
10078 pw.println(" Restarting services:");
10079 for (int i=0; i<mRestartingServices.size(); i++) {
10080 ServiceRecord r = mRestartingServices.get(i);
10081 pw.print(" * Restarting "); pw.println(r);
10082 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010083 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010084 needSep = true;
10085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010086
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010087 if (mStoppingServices.size() > 0) {
10088 if (needSep) pw.println(" ");
10089 pw.println(" Stopping services:");
10090 for (int i=0; i<mStoppingServices.size(); i++) {
10091 ServiceRecord r = mStoppingServices.get(i);
10092 pw.print(" * Stopping "); pw.println(r);
10093 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010094 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010095 needSep = true;
10096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010097
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010098 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099 if (mServiceConnections.size() > 0) {
10100 if (needSep) pw.println(" ");
10101 pw.println(" Connection bindings to services:");
10102 Iterator<ConnectionRecord> it
10103 = mServiceConnections.values().iterator();
10104 while (it.hasNext()) {
10105 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010106 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010107 r.dump(pw, " ");
10108 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010109 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010110 }
10111 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010112
10113 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 }
10115
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010116 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10117 int opti, boolean dumpAll) {
10118 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010119
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010120 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010121 if (mProvidersByClass.size() > 0) {
10122 if (needSep) pw.println(" ");
10123 pw.println(" Published content providers (by class):");
10124 Iterator it = mProvidersByClass.entrySet().iterator();
10125 while (it.hasNext()) {
10126 Map.Entry e = (Map.Entry)it.next();
10127 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010128 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010129 r.dump(pw, " ");
10130 }
10131 needSep = true;
10132 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010133
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010134 if (mProvidersByName.size() > 0) {
10135 pw.println(" ");
10136 pw.println(" Authority to provider mappings:");
10137 Iterator it = mProvidersByName.entrySet().iterator();
10138 while (it.hasNext()) {
10139 Map.Entry e = (Map.Entry)it.next();
10140 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
10141 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10142 pw.println(r);
10143 }
10144 needSep = true;
10145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010146 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010147
10148 if (mLaunchingProviders.size() > 0) {
10149 if (needSep) pw.println(" ");
10150 pw.println(" Launching content providers:");
10151 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10152 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10153 pw.println(mLaunchingProviders.get(i));
10154 }
10155 needSep = true;
10156 }
10157
10158 if (mGrantedUriPermissions.size() > 0) {
10159 pw.println();
10160 pw.println("Granted Uri Permissions:");
10161 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10162 int uid = mGrantedUriPermissions.keyAt(i);
10163 HashMap<Uri, UriPermission> perms
10164 = mGrantedUriPermissions.valueAt(i);
10165 pw.print(" * UID "); pw.print(uid);
10166 pw.println(" holds:");
10167 for (UriPermission perm : perms.values()) {
10168 pw.print(" "); pw.println(perm);
10169 perm.dump(pw, " ");
10170 }
10171 }
10172 needSep = true;
10173 }
10174
10175 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010176 }
10177
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010178 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10179 int opti, boolean dumpAll) {
10180 boolean needSep = false;
10181
10182 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010183 if (this.mIntentSenderRecords.size() > 0) {
10184 Iterator<WeakReference<PendingIntentRecord>> it
10185 = mIntentSenderRecords.values().iterator();
10186 while (it.hasNext()) {
10187 WeakReference<PendingIntentRecord> ref = it.next();
10188 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010189 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010190 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010191 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010192 rec.dump(pw, " ");
10193 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010194 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010195 }
10196 }
10197 }
10198 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010199
10200 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010201 }
10202
10203 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010204 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010205 TaskRecord lastTask = null;
10206 for (int i=list.size()-1; i>=0; i--) {
10207 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010208 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010209 if (lastTask != r.task) {
10210 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010211 pw.print(prefix);
10212 pw.print(full ? "* " : " ");
10213 pw.println(lastTask);
10214 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010215 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010217 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010218 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10219 pw.print(" #"); pw.print(i); pw.print(": ");
10220 pw.println(r);
10221 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010222 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010224 }
10225 }
10226
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010227 private static String buildOomTag(String prefix, String space, int val, int base) {
10228 if (val == base) {
10229 if (space == null) return prefix;
10230 return prefix + " ";
10231 }
10232 return prefix + "+" + Integer.toString(val-base);
10233 }
10234
10235 private static final int dumpProcessList(PrintWriter pw,
10236 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010237 String prefix, String normalLabel, String persistentLabel,
10238 boolean inclOomAdj) {
10239 int numPers = 0;
10240 for (int i=list.size()-1; i>=0; i--) {
10241 ProcessRecord r = (ProcessRecord)list.get(i);
10242 if (false) {
10243 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10244 + " #" + i + ":");
10245 r.dump(pw, prefix + " ");
10246 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010247 String oomAdj;
10248 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010249 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010250 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010251 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10252 } else if (r.setAdj >= HOME_APP_ADJ) {
10253 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10254 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10255 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10256 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10257 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10258 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10259 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10260 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10261 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010262 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010263 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010264 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010265 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010266 } else {
10267 oomAdj = Integer.toString(r.setAdj);
10268 }
10269 String schedGroup;
10270 switch (r.setSchedGroup) {
10271 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10272 schedGroup = "B";
10273 break;
10274 case Process.THREAD_GROUP_DEFAULT:
10275 schedGroup = "F";
10276 break;
10277 default:
10278 schedGroup = Integer.toString(r.setSchedGroup);
10279 break;
10280 }
10281 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010282 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010283 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010284 if (r.adjSource != null || r.adjTarget != null) {
10285 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010286 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010288 } else {
10289 pw.println(String.format("%s%s #%2d: %s",
10290 prefix, (r.persistent ? persistentLabel : normalLabel),
10291 i, r.toString()));
10292 }
10293 if (r.persistent) {
10294 numPers++;
10295 }
10296 }
10297 return numPers;
10298 }
10299
Dianne Hackborn472ad872010-04-07 17:31:48 -070010300 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010302 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010303 long uptime = SystemClock.uptimeMillis();
10304 long realtime = SystemClock.elapsedRealtime();
10305
10306 if (isCheckinRequest) {
10307 // short checkin version
10308 pw.println(uptime + "," + realtime);
10309 pw.flush();
10310 } else {
10311 pw.println("Applications Memory Usage (kB):");
10312 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10313 }
10314 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10315 ProcessRecord r = (ProcessRecord)list.get(i);
10316 if (r.thread != null) {
10317 if (!isCheckinRequest) {
10318 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10319 pw.flush();
10320 }
10321 try {
10322 r.thread.asBinder().dump(fd, args);
10323 } catch (RemoteException e) {
10324 if (!isCheckinRequest) {
10325 pw.println("Got RemoteException!");
10326 pw.flush();
10327 }
10328 }
10329 }
10330 }
10331 }
10332
10333 /**
10334 * Searches array of arguments for the specified string
10335 * @param args array of argument strings
10336 * @param value value to search for
10337 * @return true if the value is contained in the array
10338 */
10339 private static boolean scanArgs(String[] args, String value) {
10340 if (args != null) {
10341 for (String arg : args) {
10342 if (value.equals(arg)) {
10343 return true;
10344 }
10345 }
10346 }
10347 return false;
10348 }
10349
Dianne Hackborn75b03852009-06-12 15:43:26 -070010350 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010351 int count = mHistory.size();
10352
10353 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 int index = -1;
10355 for (int i=count-1; i>=0; i--) {
10356 Object o = mHistory.get(i);
10357 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010358 index = i;
10359 break;
10360 }
10361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010362
10363 return index;
10364 }
10365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010366 private final void killServicesLocked(ProcessRecord app,
10367 boolean allowRestart) {
10368 // Report disconnected services.
10369 if (false) {
10370 // XXX we are letting the client link to the service for
10371 // death notifications.
10372 if (app.services.size() > 0) {
10373 Iterator it = app.services.iterator();
10374 while (it.hasNext()) {
10375 ServiceRecord r = (ServiceRecord)it.next();
10376 if (r.connections.size() > 0) {
10377 Iterator<ConnectionRecord> jt
10378 = r.connections.values().iterator();
10379 while (jt.hasNext()) {
10380 ConnectionRecord c = jt.next();
10381 if (c.binding.client != app) {
10382 try {
10383 //c.conn.connected(r.className, null);
10384 } catch (Exception e) {
10385 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010386 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010387 + r.shortName
10388 + " from app " + app.processName, e);
10389 }
10390 }
10391 }
10392 }
10393 }
10394 }
10395 }
10396
10397 // Clean up any connections this application has to other services.
10398 if (app.connections.size() > 0) {
10399 Iterator<ConnectionRecord> it = app.connections.iterator();
10400 while (it.hasNext()) {
10401 ConnectionRecord r = it.next();
10402 removeConnectionLocked(r, app, null);
10403 }
10404 }
10405 app.connections.clear();
10406
10407 if (app.services.size() != 0) {
10408 // Any services running in the application need to be placed
10409 // back in the pending list.
10410 Iterator it = app.services.iterator();
10411 while (it.hasNext()) {
10412 ServiceRecord sr = (ServiceRecord)it.next();
10413 synchronized (sr.stats.getBatteryStats()) {
10414 sr.stats.stopLaunchedLocked();
10415 }
10416 sr.app = null;
10417 sr.executeNesting = 0;
10418 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010419
10420 boolean hasClients = sr.bindings.size() > 0;
10421 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010422 Iterator<IntentBindRecord> bindings
10423 = sr.bindings.values().iterator();
10424 while (bindings.hasNext()) {
10425 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010426 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 + ": shouldUnbind=" + b.hasBound);
10428 b.binder = null;
10429 b.requested = b.received = b.hasBound = false;
10430 }
10431 }
10432
10433 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010434 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010436 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010437 sr.crashCount, sr.shortName, app.pid);
10438 bringDownServiceLocked(sr, true);
10439 } else if (!allowRestart) {
10440 bringDownServiceLocked(sr, true);
10441 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010442 boolean canceled = scheduleServiceRestartLocked(sr, true);
10443
10444 // Should the service remain running? Note that in the
10445 // extreme case of so many attempts to deliver a command
10446 // that it failed, that we also will stop it here.
10447 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10448 if (sr.pendingStarts.size() == 0) {
10449 sr.startRequested = false;
10450 if (!hasClients) {
10451 // Whoops, no reason to restart!
10452 bringDownServiceLocked(sr, true);
10453 }
10454 }
10455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 }
10457 }
10458
10459 if (!allowRestart) {
10460 app.services.clear();
10461 }
10462 }
10463
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010464 // Make sure we have no more records on the stopping list.
10465 int i = mStoppingServices.size();
10466 while (i > 0) {
10467 i--;
10468 ServiceRecord sr = mStoppingServices.get(i);
10469 if (sr.app == app) {
10470 mStoppingServices.remove(i);
10471 }
10472 }
10473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010474 app.executingServices.clear();
10475 }
10476
10477 private final void removeDyingProviderLocked(ProcessRecord proc,
10478 ContentProviderRecord cpr) {
10479 synchronized (cpr) {
10480 cpr.launchingApp = null;
10481 cpr.notifyAll();
10482 }
10483
10484 mProvidersByClass.remove(cpr.info.name);
10485 String names[] = cpr.info.authority.split(";");
10486 for (int j = 0; j < names.length; j++) {
10487 mProvidersByName.remove(names[j]);
10488 }
10489
10490 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10491 while (cit.hasNext()) {
10492 ProcessRecord capp = cit.next();
10493 if (!capp.persistent && capp.thread != null
10494 && capp.pid != 0
10495 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010496 Slog.i(TAG, "Kill " + capp.processName
10497 + " (pid " + capp.pid + "): provider " + cpr.info.name
10498 + " in dying process " + proc.processName);
10499 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10500 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010501 Process.killProcess(capp.pid);
10502 }
10503 }
10504
10505 mLaunchingProviders.remove(cpr);
10506 }
10507
10508 /**
10509 * Main code for cleaning up a process when it has gone away. This is
10510 * called both as a result of the process dying, or directly when stopping
10511 * a process when running in single process mode.
10512 */
10513 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10514 boolean restarting, int index) {
10515 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010516 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010517 }
10518
Dianne Hackborn36124872009-10-08 16:22:03 -070010519 mProcessesToGc.remove(app);
10520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010521 // Dismiss any open dialogs.
10522 if (app.crashDialog != null) {
10523 app.crashDialog.dismiss();
10524 app.crashDialog = null;
10525 }
10526 if (app.anrDialog != null) {
10527 app.anrDialog.dismiss();
10528 app.anrDialog = null;
10529 }
10530 if (app.waitDialog != null) {
10531 app.waitDialog.dismiss();
10532 app.waitDialog = null;
10533 }
10534
10535 app.crashing = false;
10536 app.notResponding = false;
10537
10538 app.resetPackageList();
10539 app.thread = null;
10540 app.forcingToForeground = null;
10541 app.foregroundServices = false;
10542
10543 killServicesLocked(app, true);
10544
10545 boolean restart = false;
10546
10547 int NL = mLaunchingProviders.size();
10548
10549 // Remove published content providers.
10550 if (!app.pubProviders.isEmpty()) {
10551 Iterator it = app.pubProviders.values().iterator();
10552 while (it.hasNext()) {
10553 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10554 cpr.provider = null;
10555 cpr.app = null;
10556
10557 // See if someone is waiting for this provider... in which
10558 // case we don't remove it, but just let it restart.
10559 int i = 0;
10560 if (!app.bad) {
10561 for (; i<NL; i++) {
10562 if (mLaunchingProviders.get(i) == cpr) {
10563 restart = true;
10564 break;
10565 }
10566 }
10567 } else {
10568 i = NL;
10569 }
10570
10571 if (i >= NL) {
10572 removeDyingProviderLocked(app, cpr);
10573 NL = mLaunchingProviders.size();
10574 }
10575 }
10576 app.pubProviders.clear();
10577 }
10578
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010579 // Take care of any launching providers waiting for this process.
10580 if (checkAppInLaunchingProvidersLocked(app, false)) {
10581 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010582 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010584 // Unregister from connected content providers.
10585 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010586 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010587 while (it.hasNext()) {
10588 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10589 cpr.clients.remove(app);
10590 }
10591 app.conProviders.clear();
10592 }
10593
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010594 // At this point there may be remaining entries in mLaunchingProviders
10595 // where we were the only one waiting, so they are no longer of use.
10596 // Look for these and clean up if found.
10597 // XXX Commented out for now. Trying to figure out a way to reproduce
10598 // the actual situation to identify what is actually going on.
10599 if (false) {
10600 for (int i=0; i<NL; i++) {
10601 ContentProviderRecord cpr = (ContentProviderRecord)
10602 mLaunchingProviders.get(i);
10603 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10604 synchronized (cpr) {
10605 cpr.launchingApp = null;
10606 cpr.notifyAll();
10607 }
10608 }
10609 }
10610 }
10611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010612 skipCurrentReceiverLocked(app);
10613
10614 // Unregister any receivers.
10615 if (app.receivers.size() > 0) {
10616 Iterator<ReceiverList> it = app.receivers.iterator();
10617 while (it.hasNext()) {
10618 removeReceiverLocked(it.next());
10619 }
10620 app.receivers.clear();
10621 }
10622
Christopher Tate181fafa2009-05-14 11:12:14 -070010623 // If the app is undergoing backup, tell the backup manager about it
10624 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010625 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010626 try {
10627 IBackupManager bm = IBackupManager.Stub.asInterface(
10628 ServiceManager.getService(Context.BACKUP_SERVICE));
10629 bm.agentDisconnected(app.info.packageName);
10630 } catch (RemoteException e) {
10631 // can't happen; backup manager is local
10632 }
10633 }
10634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010635 // If the caller is restarting this app, then leave it in its
10636 // current lists and let the caller take care of it.
10637 if (restarting) {
10638 return;
10639 }
10640
10641 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010642 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010643 "Removing non-persistent process during cleanup: " + app);
10644 mProcessNames.remove(app.processName, app.info.uid);
10645 } else if (!app.removed) {
10646 // This app is persistent, so we need to keep its record around.
10647 // If it is not already on the pending app list, add it there
10648 // and start a new process for it.
10649 app.thread = null;
10650 app.forcingToForeground = null;
10651 app.foregroundServices = false;
10652 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10653 mPersistentStartingProcesses.add(app);
10654 restart = true;
10655 }
10656 }
10657 mProcessesOnHold.remove(app);
10658
The Android Open Source Project4df24232009-03-05 14:34:35 -080010659 if (app == mHomeProcess) {
10660 mHomeProcess = null;
10661 }
10662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010663 if (restart) {
10664 // We have components that still need to be running in the
10665 // process, so re-launch it.
10666 mProcessNames.put(app.processName, app.info.uid, app);
10667 startProcessLocked(app, "restart", app.processName);
10668 } else if (app.pid > 0 && app.pid != MY_PID) {
10669 // Goodbye!
10670 synchronized (mPidsSelfLocked) {
10671 mPidsSelfLocked.remove(app.pid);
10672 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10673 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010674 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010675 }
10676 }
10677
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010678 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10679 // Look through the content providers we are waiting to have launched,
10680 // and if any run in this process then either schedule a restart of
10681 // the process or kill the client waiting for it if this process has
10682 // gone bad.
10683 int NL = mLaunchingProviders.size();
10684 boolean restart = false;
10685 for (int i=0; i<NL; i++) {
10686 ContentProviderRecord cpr = (ContentProviderRecord)
10687 mLaunchingProviders.get(i);
10688 if (cpr.launchingApp == app) {
10689 if (!alwaysBad && !app.bad) {
10690 restart = true;
10691 } else {
10692 removeDyingProviderLocked(app, cpr);
10693 NL = mLaunchingProviders.size();
10694 }
10695 }
10696 }
10697 return restart;
10698 }
10699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010700 // =========================================================
10701 // SERVICES
10702 // =========================================================
10703
10704 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10705 ActivityManager.RunningServiceInfo info =
10706 new ActivityManager.RunningServiceInfo();
10707 info.service = r.name;
10708 if (r.app != null) {
10709 info.pid = r.app.pid;
10710 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010711 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010712 info.process = r.processName;
10713 info.foreground = r.isForeground;
10714 info.activeSince = r.createTime;
10715 info.started = r.startRequested;
10716 info.clientCount = r.connections.size();
10717 info.crashCount = r.crashCount;
10718 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010719 if (r.isForeground) {
10720 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10721 }
10722 if (r.startRequested) {
10723 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10724 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010725 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010726 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10727 }
10728 if (r.app != null && r.app.persistent) {
10729 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10730 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010731 for (ConnectionRecord conn : r.connections.values()) {
10732 if (conn.clientLabel != 0) {
10733 info.clientPackage = conn.binding.client.info.packageName;
10734 info.clientLabel = conn.clientLabel;
10735 break;
10736 }
10737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010738 return info;
10739 }
10740
10741 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10742 int flags) {
10743 synchronized (this) {
10744 ArrayList<ActivityManager.RunningServiceInfo> res
10745 = new ArrayList<ActivityManager.RunningServiceInfo>();
10746
10747 if (mServices.size() > 0) {
10748 Iterator<ServiceRecord> it = mServices.values().iterator();
10749 while (it.hasNext() && res.size() < maxNum) {
10750 res.add(makeRunningServiceInfoLocked(it.next()));
10751 }
10752 }
10753
10754 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10755 ServiceRecord r = mRestartingServices.get(i);
10756 ActivityManager.RunningServiceInfo info =
10757 makeRunningServiceInfoLocked(r);
10758 info.restarting = r.nextRestartTime;
10759 res.add(info);
10760 }
10761
10762 return res;
10763 }
10764 }
10765
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010766 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10767 synchronized (this) {
10768 ServiceRecord r = mServices.get(name);
10769 if (r != null) {
10770 for (ConnectionRecord conn : r.connections.values()) {
10771 if (conn.clientIntent != null) {
10772 return conn.clientIntent;
10773 }
10774 }
10775 }
10776 }
10777 return null;
10778 }
10779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010780 private final ServiceRecord findServiceLocked(ComponentName name,
10781 IBinder token) {
10782 ServiceRecord r = mServices.get(name);
10783 return r == token ? r : null;
10784 }
10785
10786 private final class ServiceLookupResult {
10787 final ServiceRecord record;
10788 final String permission;
10789
10790 ServiceLookupResult(ServiceRecord _record, String _permission) {
10791 record = _record;
10792 permission = _permission;
10793 }
10794 };
10795
10796 private ServiceLookupResult findServiceLocked(Intent service,
10797 String resolvedType) {
10798 ServiceRecord r = null;
10799 if (service.getComponent() != null) {
10800 r = mServices.get(service.getComponent());
10801 }
10802 if (r == null) {
10803 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10804 r = mServicesByIntent.get(filter);
10805 }
10806
10807 if (r == null) {
10808 try {
10809 ResolveInfo rInfo =
10810 ActivityThread.getPackageManager().resolveService(
10811 service, resolvedType, 0);
10812 ServiceInfo sInfo =
10813 rInfo != null ? rInfo.serviceInfo : null;
10814 if (sInfo == null) {
10815 return null;
10816 }
10817
10818 ComponentName name = new ComponentName(
10819 sInfo.applicationInfo.packageName, sInfo.name);
10820 r = mServices.get(name);
10821 } catch (RemoteException ex) {
10822 // pm is in same process, this will never happen.
10823 }
10824 }
10825 if (r != null) {
10826 int callingPid = Binder.getCallingPid();
10827 int callingUid = Binder.getCallingUid();
10828 if (checkComponentPermission(r.permission,
10829 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10830 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010831 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010832 + " from pid=" + callingPid
10833 + ", uid=" + callingUid
10834 + " requires " + r.permission);
10835 return new ServiceLookupResult(null, r.permission);
10836 }
10837 return new ServiceLookupResult(r, null);
10838 }
10839 return null;
10840 }
10841
10842 private class ServiceRestarter implements Runnable {
10843 private ServiceRecord mService;
10844
10845 void setService(ServiceRecord service) {
10846 mService = service;
10847 }
10848
10849 public void run() {
10850 synchronized(ActivityManagerService.this) {
10851 performServiceRestartLocked(mService);
10852 }
10853 }
10854 }
10855
10856 private ServiceLookupResult retrieveServiceLocked(Intent service,
10857 String resolvedType, int callingPid, int callingUid) {
10858 ServiceRecord r = null;
10859 if (service.getComponent() != null) {
10860 r = mServices.get(service.getComponent());
10861 }
10862 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10863 r = mServicesByIntent.get(filter);
10864 if (r == null) {
10865 try {
10866 ResolveInfo rInfo =
10867 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010868 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010869 ServiceInfo sInfo =
10870 rInfo != null ? rInfo.serviceInfo : null;
10871 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010872 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010873 ": not found");
10874 return null;
10875 }
10876
10877 ComponentName name = new ComponentName(
10878 sInfo.applicationInfo.packageName, sInfo.name);
10879 r = mServices.get(name);
10880 if (r == null) {
10881 filter = new Intent.FilterComparison(service.cloneFilter());
10882 ServiceRestarter res = new ServiceRestarter();
10883 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10884 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10885 synchronized (stats) {
10886 ss = stats.getServiceStatsLocked(
10887 sInfo.applicationInfo.uid, sInfo.packageName,
10888 sInfo.name);
10889 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010890 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 res.setService(r);
10892 mServices.put(name, r);
10893 mServicesByIntent.put(filter, r);
10894
10895 // Make sure this component isn't in the pending list.
10896 int N = mPendingServices.size();
10897 for (int i=0; i<N; i++) {
10898 ServiceRecord pr = mPendingServices.get(i);
10899 if (pr.name.equals(name)) {
10900 mPendingServices.remove(i);
10901 i--;
10902 N--;
10903 }
10904 }
10905 }
10906 } catch (RemoteException ex) {
10907 // pm is in same process, this will never happen.
10908 }
10909 }
10910 if (r != null) {
10911 if (checkComponentPermission(r.permission,
10912 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10913 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010914 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010915 + " from pid=" + Binder.getCallingPid()
10916 + ", uid=" + Binder.getCallingUid()
10917 + " requires " + r.permission);
10918 return new ServiceLookupResult(null, r.permission);
10919 }
10920 return new ServiceLookupResult(r, null);
10921 }
10922 return null;
10923 }
10924
10925 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10926 long now = SystemClock.uptimeMillis();
10927 if (r.executeNesting == 0 && r.app != null) {
10928 if (r.app.executingServices.size() == 0) {
10929 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10930 msg.obj = r.app;
10931 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10932 }
10933 r.app.executingServices.add(r);
10934 }
10935 r.executeNesting++;
10936 r.executingStart = now;
10937 }
10938
10939 private final void sendServiceArgsLocked(ServiceRecord r,
10940 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010941 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010942 if (N == 0) {
10943 return;
10944 }
10945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010946 int i = 0;
10947 while (i < N) {
10948 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010949 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010950 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010951 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010952 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010953 // If somehow we got a dummy start at the front, then
10954 // just drop it here.
10955 i++;
10956 continue;
10957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010958 bumpServiceExecutingLocked(r);
10959 if (!oomAdjusted) {
10960 oomAdjusted = true;
10961 updateOomAdjLocked(r.app);
10962 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010963 int flags = 0;
10964 if (si.deliveryCount > 0) {
10965 flags |= Service.START_FLAG_RETRY;
10966 }
10967 if (si.doneExecutingCount > 0) {
10968 flags |= Service.START_FLAG_REDELIVERY;
10969 }
10970 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10971 si.deliveredTime = SystemClock.uptimeMillis();
10972 r.deliveredStarts.add(si);
10973 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010974 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010975 } catch (RemoteException e) {
10976 // Remote process gone... we'll let the normal cleanup take
10977 // care of this.
10978 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010980 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010981 break;
10982 }
10983 }
10984 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010985 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010986 } else {
10987 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010988 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010989 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010990 }
10991 }
10992 }
10993
10994 private final boolean requestServiceBindingLocked(ServiceRecord r,
10995 IntentBindRecord i, boolean rebind) {
10996 if (r.app == null || r.app.thread == null) {
10997 // If service is not currently running, can't yet bind.
10998 return false;
10999 }
11000 if ((!i.requested || rebind) && i.apps.size() > 0) {
11001 try {
11002 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011003 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011004 + ": shouldUnbind=" + i.hasBound);
11005 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11006 if (!rebind) {
11007 i.requested = true;
11008 }
11009 i.hasBound = true;
11010 i.doRebind = false;
11011 } catch (RemoteException e) {
11012 return false;
11013 }
11014 }
11015 return true;
11016 }
11017
11018 private final void requestServiceBindingsLocked(ServiceRecord r) {
11019 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11020 while (bindings.hasNext()) {
11021 IntentBindRecord i = bindings.next();
11022 if (!requestServiceBindingLocked(r, i, false)) {
11023 break;
11024 }
11025 }
11026 }
11027
11028 private final void realStartServiceLocked(ServiceRecord r,
11029 ProcessRecord app) throws RemoteException {
11030 if (app.thread == null) {
11031 throw new RemoteException();
11032 }
11033
11034 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011035 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036
11037 app.services.add(r);
11038 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011039 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011040
11041 boolean created = false;
11042 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011043 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011045 mStringBuilder.setLength(0);
11046 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011047 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011048 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011049 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011050 synchronized (r.stats.getBatteryStats()) {
11051 r.stats.startLaunchedLocked();
11052 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011053 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011054 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011055 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 created = true;
11057 } finally {
11058 if (!created) {
11059 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011060 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011061 }
11062 }
11063
11064 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011065
11066 // If the service is in the started state, and there are no
11067 // pending arguments, then fake up one so its onStartCommand() will
11068 // be called.
11069 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11070 r.lastStartId++;
11071 if (r.lastStartId < 1) {
11072 r.lastStartId = 1;
11073 }
11074 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11075 }
11076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077 sendServiceArgsLocked(r, true);
11078 }
11079
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011080 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11081 boolean allowCancel) {
11082 boolean canceled = false;
11083
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011084 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011085 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011086 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011087
11088 // Any delivered but not yet finished starts should be put back
11089 // on the pending list.
11090 final int N = r.deliveredStarts.size();
11091 if (N > 0) {
11092 for (int i=N-1; i>=0; i--) {
11093 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11094 if (si.intent == null) {
11095 // We'll generate this again if needed.
11096 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11097 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11098 r.pendingStarts.add(0, si);
11099 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11100 dur *= 2;
11101 if (minDuration < dur) minDuration = dur;
11102 if (resetTime < dur) resetTime = dur;
11103 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011104 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011105 + r.name);
11106 canceled = true;
11107 }
11108 }
11109 r.deliveredStarts.clear();
11110 }
11111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011112 r.totalRestartCount++;
11113 if (r.restartDelay == 0) {
11114 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011115 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011116 } else {
11117 // If it has been a "reasonably long time" since the service
11118 // was started, then reset our restart duration back to
11119 // the beginning, so we don't infinitely increase the duration
11120 // on a service that just occasionally gets killed (which is
11121 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011122 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011123 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011124 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011125 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011126 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011127 if (r.restartDelay < minDuration) {
11128 r.restartDelay = minDuration;
11129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011130 }
11131 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011132
11133 r.nextRestartTime = now + r.restartDelay;
11134
11135 // Make sure that we don't end up restarting a bunch of services
11136 // all at the same time.
11137 boolean repeat;
11138 do {
11139 repeat = false;
11140 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11141 ServiceRecord r2 = mRestartingServices.get(i);
11142 if (r2 != r && r.nextRestartTime
11143 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11144 && r.nextRestartTime
11145 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11146 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11147 r.restartDelay = r.nextRestartTime - now;
11148 repeat = true;
11149 break;
11150 }
11151 }
11152 } while (repeat);
11153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 if (!mRestartingServices.contains(r)) {
11155 mRestartingServices.add(r);
11156 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011157
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011158 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011160 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011161 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011162 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011163 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011165 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011166 r.shortName, r.restartDelay);
11167
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011168 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011169 }
11170
11171 final void performServiceRestartLocked(ServiceRecord r) {
11172 if (!mRestartingServices.contains(r)) {
11173 return;
11174 }
11175 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11176 }
11177
11178 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11179 if (r.restartDelay == 0) {
11180 return false;
11181 }
11182 r.resetRestartCounter();
11183 mRestartingServices.remove(r);
11184 mHandler.removeCallbacks(r.restarter);
11185 return true;
11186 }
11187
11188 private final boolean bringUpServiceLocked(ServiceRecord r,
11189 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011190 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011191 //r.dump(" ");
11192
Dianne Hackborn36124872009-10-08 16:22:03 -070011193 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 sendServiceArgsLocked(r, false);
11195 return true;
11196 }
11197
11198 if (!whileRestarting && r.restartDelay > 0) {
11199 // If waiting for a restart, then do nothing.
11200 return true;
11201 }
11202
Joe Onorato8a9b2202010-02-26 18:56:32 -080011203 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 + " " + r.intent);
11205
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011206 // We are now bringing the service up, so no longer in the
11207 // restarting state.
11208 mRestartingServices.remove(r);
11209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 final String appName = r.processName;
11211 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11212 if (app != null && app.thread != null) {
11213 try {
11214 realStartServiceLocked(r, app);
11215 return true;
11216 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011217 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011218 }
11219
11220 // If a dead object exception was thrown -- fall through to
11221 // restart the application.
11222 }
11223
Dianne Hackborn36124872009-10-08 16:22:03 -070011224 // Not running -- get it started, and enqueue this service record
11225 // to be executed when the app comes up.
11226 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11227 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011228 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011229 + r.appInfo.packageName + "/"
11230 + r.appInfo.uid + " for service "
11231 + r.intent.getIntent() + ": process is bad");
11232 bringDownServiceLocked(r, true);
11233 return false;
11234 }
11235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011236 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 mPendingServices.add(r);
11238 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011240 return true;
11241 }
11242
11243 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011244 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011245 //r.dump(" ");
11246
11247 // Does it still need to run?
11248 if (!force && r.startRequested) {
11249 return;
11250 }
11251 if (r.connections.size() > 0) {
11252 if (!force) {
11253 // XXX should probably keep a count of the number of auto-create
11254 // connections directly in the service.
11255 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11256 while (it.hasNext()) {
11257 ConnectionRecord cr = it.next();
11258 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11259 return;
11260 }
11261 }
11262 }
11263
11264 // Report to all of the connections that the service is no longer
11265 // available.
11266 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11267 while (it.hasNext()) {
11268 ConnectionRecord c = it.next();
11269 try {
11270 // todo: shouldn't be a synchronous call!
11271 c.conn.connected(r.name, null);
11272 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011273 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 " to connection " + c.conn.asBinder() +
11275 " (in " + c.binding.client.processName + ")", e);
11276 }
11277 }
11278 }
11279
11280 // Tell the service that it has been unbound.
11281 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11282 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11283 while (it.hasNext()) {
11284 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011285 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011286 + ": hasBound=" + ibr.hasBound);
11287 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11288 try {
11289 bumpServiceExecutingLocked(r);
11290 updateOomAdjLocked(r.app);
11291 ibr.hasBound = false;
11292 r.app.thread.scheduleUnbindService(r,
11293 ibr.intent.getIntent());
11294 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011295 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011296 + r.shortName, e);
11297 serviceDoneExecutingLocked(r, true);
11298 }
11299 }
11300 }
11301 }
11302
Joe Onorato8a9b2202010-02-26 18:56:32 -080011303 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011304 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011305 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011306 System.identityHashCode(r), r.shortName,
11307 (r.app != null) ? r.app.pid : -1);
11308
11309 mServices.remove(r.name);
11310 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011311 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 r.totalRestartCount = 0;
11313 unscheduleServiceRestartLocked(r);
11314
11315 // Also make sure it is not on the pending list.
11316 int N = mPendingServices.size();
11317 for (int i=0; i<N; i++) {
11318 if (mPendingServices.get(i) == r) {
11319 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011320 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011321 TAG, "Removed pending service: " + r.shortName);
11322 i--;
11323 N--;
11324 }
11325 }
11326
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011327 r.cancelNotification();
11328 r.isForeground = false;
11329 r.foregroundId = 0;
11330 r.foregroundNoti = null;
11331
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011332 // Clear start entries.
11333 r.deliveredStarts.clear();
11334 r.pendingStarts.clear();
11335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011336 if (r.app != null) {
11337 synchronized (r.stats.getBatteryStats()) {
11338 r.stats.stopLaunchedLocked();
11339 }
11340 r.app.services.remove(r);
11341 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011342 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011343 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011344 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011345 bumpServiceExecutingLocked(r);
11346 mStoppingServices.add(r);
11347 updateOomAdjLocked(r.app);
11348 r.app.thread.scheduleStopService(r);
11349 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011350 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011351 + r.shortName, e);
11352 serviceDoneExecutingLocked(r, true);
11353 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011354 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011355 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011356 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 TAG, "Removed service that has no process: " + r.shortName);
11358 }
11359 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011360 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011361 TAG, "Removed service that is not running: " + r.shortName);
11362 }
11363 }
11364
11365 ComponentName startServiceLocked(IApplicationThread caller,
11366 Intent service, String resolvedType,
11367 int callingPid, int callingUid) {
11368 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011369 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 + " type=" + resolvedType + " args=" + service.getExtras());
11371
11372 if (caller != null) {
11373 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11374 if (callerApp == null) {
11375 throw new SecurityException(
11376 "Unable to find app for caller " + caller
11377 + " (pid=" + Binder.getCallingPid()
11378 + ") when starting service " + service);
11379 }
11380 }
11381
11382 ServiceLookupResult res =
11383 retrieveServiceLocked(service, resolvedType,
11384 callingPid, callingUid);
11385 if (res == null) {
11386 return null;
11387 }
11388 if (res.record == null) {
11389 return new ComponentName("!", res.permission != null
11390 ? res.permission : "private to package");
11391 }
11392 ServiceRecord r = res.record;
11393 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011394 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011395 + r.shortName);
11396 }
11397 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011398 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 r.lastStartId++;
11400 if (r.lastStartId < 1) {
11401 r.lastStartId = 1;
11402 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011403 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011404 r.lastActivity = SystemClock.uptimeMillis();
11405 synchronized (r.stats.getBatteryStats()) {
11406 r.stats.startRunningLocked();
11407 }
11408 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11409 return new ComponentName("!", "Service process is bad");
11410 }
11411 return r.name;
11412 }
11413 }
11414
11415 public ComponentName startService(IApplicationThread caller, Intent service,
11416 String resolvedType) {
11417 // Refuse possible leaked file descriptors
11418 if (service != null && service.hasFileDescriptors() == true) {
11419 throw new IllegalArgumentException("File descriptors passed in Intent");
11420 }
11421
11422 synchronized(this) {
11423 final int callingPid = Binder.getCallingPid();
11424 final int callingUid = Binder.getCallingUid();
11425 final long origId = Binder.clearCallingIdentity();
11426 ComponentName res = startServiceLocked(caller, service,
11427 resolvedType, callingPid, callingUid);
11428 Binder.restoreCallingIdentity(origId);
11429 return res;
11430 }
11431 }
11432
11433 ComponentName startServiceInPackage(int uid,
11434 Intent service, String resolvedType) {
11435 synchronized(this) {
11436 final long origId = Binder.clearCallingIdentity();
11437 ComponentName res = startServiceLocked(null, service,
11438 resolvedType, -1, uid);
11439 Binder.restoreCallingIdentity(origId);
11440 return res;
11441 }
11442 }
11443
11444 public int stopService(IApplicationThread caller, Intent service,
11445 String resolvedType) {
11446 // Refuse possible leaked file descriptors
11447 if (service != null && service.hasFileDescriptors() == true) {
11448 throw new IllegalArgumentException("File descriptors passed in Intent");
11449 }
11450
11451 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011452 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011453 + " type=" + resolvedType);
11454
11455 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11456 if (caller != null && callerApp == null) {
11457 throw new SecurityException(
11458 "Unable to find app for caller " + caller
11459 + " (pid=" + Binder.getCallingPid()
11460 + ") when stopping service " + service);
11461 }
11462
11463 // If this service is active, make sure it is stopped.
11464 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11465 if (r != null) {
11466 if (r.record != null) {
11467 synchronized (r.record.stats.getBatteryStats()) {
11468 r.record.stats.stopRunningLocked();
11469 }
11470 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011471 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 final long origId = Binder.clearCallingIdentity();
11473 bringDownServiceLocked(r.record, false);
11474 Binder.restoreCallingIdentity(origId);
11475 return 1;
11476 }
11477 return -1;
11478 }
11479 }
11480
11481 return 0;
11482 }
11483
11484 public IBinder peekService(Intent service, String resolvedType) {
11485 // Refuse possible leaked file descriptors
11486 if (service != null && service.hasFileDescriptors() == true) {
11487 throw new IllegalArgumentException("File descriptors passed in Intent");
11488 }
11489
11490 IBinder ret = null;
11491
11492 synchronized(this) {
11493 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11494
11495 if (r != null) {
11496 // r.record is null if findServiceLocked() failed the caller permission check
11497 if (r.record == null) {
11498 throw new SecurityException(
11499 "Permission Denial: Accessing service " + r.record.name
11500 + " from pid=" + Binder.getCallingPid()
11501 + ", uid=" + Binder.getCallingUid()
11502 + " requires " + r.permission);
11503 }
11504 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11505 if (ib != null) {
11506 ret = ib.binder;
11507 }
11508 }
11509 }
11510
11511 return ret;
11512 }
11513
11514 public boolean stopServiceToken(ComponentName className, IBinder token,
11515 int startId) {
11516 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011517 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518 + " " + token + " startId=" + startId);
11519 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011520 if (r != null) {
11521 if (startId >= 0) {
11522 // Asked to only stop if done with all work. Note that
11523 // to avoid leaks, we will take this as dropping all
11524 // start items up to and including this one.
11525 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11526 if (si != null) {
11527 while (r.deliveredStarts.size() > 0) {
11528 if (r.deliveredStarts.remove(0) == si) {
11529 break;
11530 }
11531 }
11532 }
11533
11534 if (r.lastStartId != startId) {
11535 return false;
11536 }
11537
11538 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011539 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011540 + " is last, but have " + r.deliveredStarts.size()
11541 + " remaining args");
11542 }
11543 }
11544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545 synchronized (r.stats.getBatteryStats()) {
11546 r.stats.stopRunningLocked();
11547 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011548 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011549 }
11550 final long origId = Binder.clearCallingIdentity();
11551 bringDownServiceLocked(r, false);
11552 Binder.restoreCallingIdentity(origId);
11553 return true;
11554 }
11555 }
11556 return false;
11557 }
11558
11559 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011560 int id, Notification notification, boolean removeNotification) {
11561 final long origId = Binder.clearCallingIdentity();
11562 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 synchronized(this) {
11564 ServiceRecord r = findServiceLocked(className, token);
11565 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011566 if (id != 0) {
11567 if (notification == null) {
11568 throw new IllegalArgumentException("null notification");
11569 }
11570 if (r.foregroundId != id) {
11571 r.cancelNotification();
11572 r.foregroundId = id;
11573 }
11574 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11575 r.foregroundNoti = notification;
11576 r.isForeground = true;
11577 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 if (r.app != null) {
11579 updateServiceForegroundLocked(r.app, true);
11580 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011581 } else {
11582 if (r.isForeground) {
11583 r.isForeground = false;
11584 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011585 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011586 updateServiceForegroundLocked(r.app, true);
11587 }
11588 }
11589 if (removeNotification) {
11590 r.cancelNotification();
11591 r.foregroundId = 0;
11592 r.foregroundNoti = null;
11593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 }
11595 }
11596 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011597 } finally {
11598 Binder.restoreCallingIdentity(origId);
11599 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011600 }
11601
11602 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11603 boolean anyForeground = false;
11604 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11605 if (sr.isForeground) {
11606 anyForeground = true;
11607 break;
11608 }
11609 }
11610 if (anyForeground != proc.foregroundServices) {
11611 proc.foregroundServices = anyForeground;
11612 if (oomAdj) {
11613 updateOomAdjLocked();
11614 }
11615 }
11616 }
11617
11618 public int bindService(IApplicationThread caller, IBinder token,
11619 Intent service, String resolvedType,
11620 IServiceConnection connection, int flags) {
11621 // Refuse possible leaked file descriptors
11622 if (service != null && service.hasFileDescriptors() == true) {
11623 throw new IllegalArgumentException("File descriptors passed in Intent");
11624 }
11625
11626 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011627 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 + " type=" + resolvedType + " conn=" + connection.asBinder()
11629 + " flags=0x" + Integer.toHexString(flags));
11630 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11631 if (callerApp == null) {
11632 throw new SecurityException(
11633 "Unable to find app for caller " + caller
11634 + " (pid=" + Binder.getCallingPid()
11635 + ") when binding service " + service);
11636 }
11637
11638 HistoryRecord activity = null;
11639 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011640 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011641 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011642 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 return 0;
11644 }
11645 activity = (HistoryRecord)mHistory.get(aindex);
11646 }
11647
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011648 int clientLabel = 0;
11649 PendingIntent clientIntent = null;
11650
11651 if (callerApp.info.uid == Process.SYSTEM_UID) {
11652 // Hacky kind of thing -- allow system stuff to tell us
11653 // what they are, so we can report this elsewhere for
11654 // others to know why certain services are running.
11655 try {
11656 clientIntent = (PendingIntent)service.getParcelableExtra(
11657 Intent.EXTRA_CLIENT_INTENT);
11658 } catch (RuntimeException e) {
11659 }
11660 if (clientIntent != null) {
11661 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11662 if (clientLabel != 0) {
11663 // There are no useful extras in the intent, trash them.
11664 // System code calling with this stuff just needs to know
11665 // this will happen.
11666 service = service.cloneFilter();
11667 }
11668 }
11669 }
11670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011671 ServiceLookupResult res =
11672 retrieveServiceLocked(service, resolvedType,
11673 Binder.getCallingPid(), Binder.getCallingUid());
11674 if (res == null) {
11675 return 0;
11676 }
11677 if (res.record == null) {
11678 return -1;
11679 }
11680 ServiceRecord s = res.record;
11681
11682 final long origId = Binder.clearCallingIdentity();
11683
11684 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011685 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011686 + s.shortName);
11687 }
11688
11689 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11690 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011691 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011692
11693 IBinder binder = connection.asBinder();
11694 s.connections.put(binder, c);
11695 b.connections.add(c);
11696 if (activity != null) {
11697 if (activity.connections == null) {
11698 activity.connections = new HashSet<ConnectionRecord>();
11699 }
11700 activity.connections.add(c);
11701 }
11702 b.client.connections.add(c);
11703 mServiceConnections.put(binder, c);
11704
11705 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11706 s.lastActivity = SystemClock.uptimeMillis();
11707 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11708 return 0;
11709 }
11710 }
11711
11712 if (s.app != null) {
11713 // This could have made the service more important.
11714 updateOomAdjLocked(s.app);
11715 }
11716
Joe Onorato8a9b2202010-02-26 18:56:32 -080011717 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011718 + ": received=" + b.intent.received
11719 + " apps=" + b.intent.apps.size()
11720 + " doRebind=" + b.intent.doRebind);
11721
11722 if (s.app != null && b.intent.received) {
11723 // Service is already running, so we can immediately
11724 // publish the connection.
11725 try {
11726 c.conn.connected(s.name, b.intent.binder);
11727 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011728 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011729 + " to connection " + c.conn.asBinder()
11730 + " (in " + c.binding.client.processName + ")", e);
11731 }
11732
11733 // If this is the first app connected back to this binding,
11734 // and the service had previously asked to be told when
11735 // rebound, then do so.
11736 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11737 requestServiceBindingLocked(s, b.intent, true);
11738 }
11739 } else if (!b.intent.requested) {
11740 requestServiceBindingLocked(s, b.intent, false);
11741 }
11742
11743 Binder.restoreCallingIdentity(origId);
11744 }
11745
11746 return 1;
11747 }
11748
11749 private void removeConnectionLocked(
11750 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11751 IBinder binder = c.conn.asBinder();
11752 AppBindRecord b = c.binding;
11753 ServiceRecord s = b.service;
11754 s.connections.remove(binder);
11755 b.connections.remove(c);
11756 if (c.activity != null && c.activity != skipAct) {
11757 if (c.activity.connections != null) {
11758 c.activity.connections.remove(c);
11759 }
11760 }
11761 if (b.client != skipApp) {
11762 b.client.connections.remove(c);
11763 }
11764 mServiceConnections.remove(binder);
11765
11766 if (b.connections.size() == 0) {
11767 b.intent.apps.remove(b.client);
11768 }
11769
Joe Onorato8a9b2202010-02-26 18:56:32 -080011770 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 + ": shouldUnbind=" + b.intent.hasBound);
11772 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11773 && b.intent.hasBound) {
11774 try {
11775 bumpServiceExecutingLocked(s);
11776 updateOomAdjLocked(s.app);
11777 b.intent.hasBound = false;
11778 // Assume the client doesn't want to know about a rebind;
11779 // we will deal with that later if it asks for one.
11780 b.intent.doRebind = false;
11781 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11782 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011783 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011784 serviceDoneExecutingLocked(s, true);
11785 }
11786 }
11787
11788 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11789 bringDownServiceLocked(s, false);
11790 }
11791 }
11792
11793 public boolean unbindService(IServiceConnection connection) {
11794 synchronized (this) {
11795 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011796 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 ConnectionRecord r = mServiceConnections.get(binder);
11798 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011799 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011800 + connection.asBinder());
11801 return false;
11802 }
11803
11804 final long origId = Binder.clearCallingIdentity();
11805
11806 removeConnectionLocked(r, null, null);
11807
11808 if (r.binding.service.app != null) {
11809 // This could have made the service less important.
11810 updateOomAdjLocked(r.binding.service.app);
11811 }
11812
11813 Binder.restoreCallingIdentity(origId);
11814 }
11815
11816 return true;
11817 }
11818
11819 public void publishService(IBinder token, Intent intent, IBinder service) {
11820 // Refuse possible leaked file descriptors
11821 if (intent != null && intent.hasFileDescriptors() == true) {
11822 throw new IllegalArgumentException("File descriptors passed in Intent");
11823 }
11824
11825 synchronized(this) {
11826 if (!(token instanceof ServiceRecord)) {
11827 throw new IllegalArgumentException("Invalid service token");
11828 }
11829 ServiceRecord r = (ServiceRecord)token;
11830
11831 final long origId = Binder.clearCallingIdentity();
11832
Joe Onorato8a9b2202010-02-26 18:56:32 -080011833 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011834 + " " + intent + ": " + service);
11835 if (r != null) {
11836 Intent.FilterComparison filter
11837 = new Intent.FilterComparison(intent);
11838 IntentBindRecord b = r.bindings.get(filter);
11839 if (b != null && !b.received) {
11840 b.binder = service;
11841 b.requested = true;
11842 b.received = true;
11843 if (r.connections.size() > 0) {
11844 Iterator<ConnectionRecord> it
11845 = r.connections.values().iterator();
11846 while (it.hasNext()) {
11847 ConnectionRecord c = it.next();
11848 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011849 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011851 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011852 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011853 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011854 TAG, "Published intent: " + intent);
11855 continue;
11856 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011857 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011858 try {
11859 c.conn.connected(r.name, service);
11860 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011861 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011862 " to connection " + c.conn.asBinder() +
11863 " (in " + c.binding.client.processName + ")", e);
11864 }
11865 }
11866 }
11867 }
11868
11869 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11870
11871 Binder.restoreCallingIdentity(origId);
11872 }
11873 }
11874 }
11875
11876 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11877 // Refuse possible leaked file descriptors
11878 if (intent != null && intent.hasFileDescriptors() == true) {
11879 throw new IllegalArgumentException("File descriptors passed in Intent");
11880 }
11881
11882 synchronized(this) {
11883 if (!(token instanceof ServiceRecord)) {
11884 throw new IllegalArgumentException("Invalid service token");
11885 }
11886 ServiceRecord r = (ServiceRecord)token;
11887
11888 final long origId = Binder.clearCallingIdentity();
11889
11890 if (r != null) {
11891 Intent.FilterComparison filter
11892 = new Intent.FilterComparison(intent);
11893 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011894 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011895 + " at " + b + ": apps="
11896 + (b != null ? b.apps.size() : 0));
11897 if (b != null) {
11898 if (b.apps.size() > 0) {
11899 // Applications have already bound since the last
11900 // unbind, so just rebind right here.
11901 requestServiceBindingLocked(r, b, true);
11902 } else {
11903 // Note to tell the service the next time there is
11904 // a new client.
11905 b.doRebind = true;
11906 }
11907 }
11908
11909 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11910
11911 Binder.restoreCallingIdentity(origId);
11912 }
11913 }
11914 }
11915
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011916 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011917 synchronized(this) {
11918 if (!(token instanceof ServiceRecord)) {
11919 throw new IllegalArgumentException("Invalid service token");
11920 }
11921 ServiceRecord r = (ServiceRecord)token;
11922 boolean inStopping = mStoppingServices.contains(token);
11923 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011924 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011925 + ": nesting=" + r.executeNesting
11926 + ", inStopping=" + inStopping);
11927 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011928 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011929 + " with incorrect token: given " + token
11930 + ", expected " + r);
11931 return;
11932 }
11933
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011934 if (type == 1) {
11935 // This is a call from a service start... take care of
11936 // book-keeping.
11937 r.callStart = true;
11938 switch (res) {
11939 case Service.START_STICKY_COMPATIBILITY:
11940 case Service.START_STICKY: {
11941 // We are done with the associated start arguments.
11942 r.findDeliveredStart(startId, true);
11943 // Don't stop if killed.
11944 r.stopIfKilled = false;
11945 break;
11946 }
11947 case Service.START_NOT_STICKY: {
11948 // We are done with the associated start arguments.
11949 r.findDeliveredStart(startId, true);
11950 if (r.lastStartId == startId) {
11951 // There is no more work, and this service
11952 // doesn't want to hang around if killed.
11953 r.stopIfKilled = true;
11954 }
11955 break;
11956 }
11957 case Service.START_REDELIVER_INTENT: {
11958 // We'll keep this item until they explicitly
11959 // call stop for it, but keep track of the fact
11960 // that it was delivered.
11961 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11962 if (si != null) {
11963 si.deliveryCount = 0;
11964 si.doneExecutingCount++;
11965 // Don't stop if killed.
11966 r.stopIfKilled = true;
11967 }
11968 break;
11969 }
11970 default:
11971 throw new IllegalArgumentException(
11972 "Unknown service start result: " + res);
11973 }
11974 if (res == Service.START_STICKY_COMPATIBILITY) {
11975 r.callStart = false;
11976 }
11977 }
11978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011979 final long origId = Binder.clearCallingIdentity();
11980 serviceDoneExecutingLocked(r, inStopping);
11981 Binder.restoreCallingIdentity(origId);
11982 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011983 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011984 + " with token " + token);
11985 }
11986 }
11987 }
11988
11989 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11990 r.executeNesting--;
11991 if (r.executeNesting <= 0 && r.app != null) {
11992 r.app.executingServices.remove(r);
11993 if (r.app.executingServices.size() == 0) {
11994 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11995 }
11996 if (inStopping) {
11997 mStoppingServices.remove(r);
11998 }
11999 updateOomAdjLocked(r.app);
12000 }
12001 }
12002
12003 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012004 String anrMessage = null;
12005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012006 synchronized(this) {
12007 if (proc.executingServices.size() == 0 || proc.thread == null) {
12008 return;
12009 }
12010 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12011 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12012 ServiceRecord timeout = null;
12013 long nextTime = 0;
12014 while (it.hasNext()) {
12015 ServiceRecord sr = it.next();
12016 if (sr.executingStart < maxTime) {
12017 timeout = sr;
12018 break;
12019 }
12020 if (sr.executingStart > nextTime) {
12021 nextTime = sr.executingStart;
12022 }
12023 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012024 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012025 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012026 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012027 } else {
12028 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12029 msg.obj = proc;
12030 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12031 }
12032 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012033
12034 if (anrMessage != null) {
12035 appNotResponding(proc, null, null, anrMessage);
12036 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012037 }
12038
12039 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012040 // BACKUP AND RESTORE
12041 // =========================================================
12042
12043 // Cause the target app to be launched if necessary and its backup agent
12044 // instantiated. The backup agent will invoke backupAgentCreated() on the
12045 // activity manager to announce its creation.
12046 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012047 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012048 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12049
12050 synchronized(this) {
12051 // !!! TODO: currently no check here that we're already bound
12052 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12053 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12054 synchronized (stats) {
12055 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12056 }
12057
12058 BackupRecord r = new BackupRecord(ss, app, backupMode);
12059 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12060 // startProcessLocked() returns existing proc's record if it's already running
12061 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012062 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012063 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012064 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012065 return false;
12066 }
12067
12068 r.app = proc;
12069 mBackupTarget = r;
12070 mBackupAppName = app.packageName;
12071
Christopher Tate6fa95972009-06-05 18:43:55 -070012072 // Try not to kill the process during backup
12073 updateOomAdjLocked(proc);
12074
Christopher Tate181fafa2009-05-14 11:12:14 -070012075 // If the process is already attached, schedule the creation of the backup agent now.
12076 // If it is not yet live, this will be done when it attaches to the framework.
12077 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012078 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012079 try {
12080 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12081 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012082 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012083 }
12084 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012085 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012086 }
12087 // Invariants: at this point, the target app process exists and the application
12088 // is either already running or in the process of coming up. mBackupTarget and
12089 // mBackupAppName describe the app, so that when it binds back to the AM we
12090 // know that it's scheduled for a backup-agent operation.
12091 }
12092
12093 return true;
12094 }
12095
12096 // A backup agent has just come up
12097 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012098 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012099 + " = " + agent);
12100
12101 synchronized(this) {
12102 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012103 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012104 return;
12105 }
12106
Christopher Tate043dadc2009-06-02 16:11:00 -070012107 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012108 try {
12109 IBackupManager bm = IBackupManager.Stub.asInterface(
12110 ServiceManager.getService(Context.BACKUP_SERVICE));
12111 bm.agentConnected(agentPackageName, agent);
12112 } catch (RemoteException e) {
12113 // can't happen; the backup manager service is local
12114 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012115 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012116 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012117 } finally {
12118 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012119 }
12120 }
12121 }
12122
12123 // done with this agent
12124 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012125 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012126 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012127 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012128 return;
12129 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012130
12131 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012132 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012133 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012134 return;
12135 }
12136
Christopher Tate181fafa2009-05-14 11:12:14 -070012137 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012138 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012139 return;
12140 }
12141
Christopher Tate6fa95972009-06-05 18:43:55 -070012142 ProcessRecord proc = mBackupTarget.app;
12143 mBackupTarget = null;
12144 mBackupAppName = null;
12145
12146 // Not backing this app up any more; reset its OOM adjustment
12147 updateOomAdjLocked(proc);
12148
Christopher Tatec7b31e32009-06-10 15:49:30 -070012149 // If the app crashed during backup, 'thread' will be null here
12150 if (proc.thread != null) {
12151 try {
12152 proc.thread.scheduleDestroyBackupAgent(appInfo);
12153 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012154 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012155 e.printStackTrace();
12156 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012157 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012158 }
12159 }
12160 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012161 // BROADCASTS
12162 // =========================================================
12163
Josh Bartel7f208742010-02-25 11:01:44 -060012164 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012165 List cur) {
12166 final ContentResolver resolver = mContext.getContentResolver();
12167 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12168 if (list == null) {
12169 return cur;
12170 }
12171 int N = list.size();
12172 for (int i=0; i<N; i++) {
12173 Intent intent = list.get(i);
12174 if (filter.match(resolver, intent, true, TAG) >= 0) {
12175 if (cur == null) {
12176 cur = new ArrayList<Intent>();
12177 }
12178 cur.add(intent);
12179 }
12180 }
12181 return cur;
12182 }
12183
12184 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012185 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012186 + mBroadcastsScheduled);
12187
12188 if (mBroadcastsScheduled) {
12189 return;
12190 }
12191 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12192 mBroadcastsScheduled = true;
12193 }
12194
12195 public Intent registerReceiver(IApplicationThread caller,
12196 IIntentReceiver receiver, IntentFilter filter, String permission) {
12197 synchronized(this) {
12198 ProcessRecord callerApp = null;
12199 if (caller != null) {
12200 callerApp = getRecordForAppLocked(caller);
12201 if (callerApp == null) {
12202 throw new SecurityException(
12203 "Unable to find app for caller " + caller
12204 + " (pid=" + Binder.getCallingPid()
12205 + ") when registering receiver " + receiver);
12206 }
12207 }
12208
12209 List allSticky = null;
12210
12211 // Look for any matching sticky broadcasts...
12212 Iterator actions = filter.actionsIterator();
12213 if (actions != null) {
12214 while (actions.hasNext()) {
12215 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012216 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012217 }
12218 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012219 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012220 }
12221
12222 // The first sticky in the list is returned directly back to
12223 // the client.
12224 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12225
Joe Onorato8a9b2202010-02-26 18:56:32 -080012226 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012227 + ": " + sticky);
12228
12229 if (receiver == null) {
12230 return sticky;
12231 }
12232
12233 ReceiverList rl
12234 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12235 if (rl == null) {
12236 rl = new ReceiverList(this, callerApp,
12237 Binder.getCallingPid(),
12238 Binder.getCallingUid(), receiver);
12239 if (rl.app != null) {
12240 rl.app.receivers.add(rl);
12241 } else {
12242 try {
12243 receiver.asBinder().linkToDeath(rl, 0);
12244 } catch (RemoteException e) {
12245 return sticky;
12246 }
12247 rl.linkedToDeath = true;
12248 }
12249 mRegisteredReceivers.put(receiver.asBinder(), rl);
12250 }
12251 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12252 rl.add(bf);
12253 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012254 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012255 }
12256 mReceiverResolver.addFilter(bf);
12257
12258 // Enqueue broadcasts for all existing stickies that match
12259 // this filter.
12260 if (allSticky != null) {
12261 ArrayList receivers = new ArrayList();
12262 receivers.add(bf);
12263
12264 int N = allSticky.size();
12265 for (int i=0; i<N; i++) {
12266 Intent intent = (Intent)allSticky.get(i);
12267 BroadcastRecord r = new BroadcastRecord(intent, null,
12268 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012269 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012270 if (mParallelBroadcasts.size() == 0) {
12271 scheduleBroadcastsLocked();
12272 }
12273 mParallelBroadcasts.add(r);
12274 }
12275 }
12276
12277 return sticky;
12278 }
12279 }
12280
12281 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012282 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012283
12284 boolean doNext = false;
12285
12286 synchronized(this) {
12287 ReceiverList rl
12288 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12289 if (rl != null) {
12290 if (rl.curBroadcast != null) {
12291 BroadcastRecord r = rl.curBroadcast;
12292 doNext = finishReceiverLocked(
12293 receiver.asBinder(), r.resultCode, r.resultData,
12294 r.resultExtras, r.resultAbort, true);
12295 }
12296
12297 if (rl.app != null) {
12298 rl.app.receivers.remove(rl);
12299 }
12300 removeReceiverLocked(rl);
12301 if (rl.linkedToDeath) {
12302 rl.linkedToDeath = false;
12303 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12304 }
12305 }
12306 }
12307
12308 if (!doNext) {
12309 return;
12310 }
12311
12312 final long origId = Binder.clearCallingIdentity();
12313 processNextBroadcast(false);
12314 trimApplications();
12315 Binder.restoreCallingIdentity(origId);
12316 }
12317
12318 void removeReceiverLocked(ReceiverList rl) {
12319 mRegisteredReceivers.remove(rl.receiver.asBinder());
12320 int N = rl.size();
12321 for (int i=0; i<N; i++) {
12322 mReceiverResolver.removeFilter(rl.get(i));
12323 }
12324 }
12325
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012326 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12327 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12328 ProcessRecord r = mLruProcesses.get(i);
12329 if (r.thread != null) {
12330 try {
12331 r.thread.dispatchPackageBroadcast(cmd, packages);
12332 } catch (RemoteException ex) {
12333 }
12334 }
12335 }
12336 }
12337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012338 private final int broadcastIntentLocked(ProcessRecord callerApp,
12339 String callerPackage, Intent intent, String resolvedType,
12340 IIntentReceiver resultTo, int resultCode, String resultData,
12341 Bundle map, String requiredPermission,
12342 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12343 intent = new Intent(intent);
12344
Joe Onorato8a9b2202010-02-26 18:56:32 -080012345 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012346 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12347 + " ordered=" + ordered);
12348 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012349 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012350 }
12351
12352 // Handle special intents: if this broadcast is from the package
12353 // manager about a package being removed, we need to remove all of
12354 // its activities from the history stack.
12355 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12356 intent.getAction());
12357 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12358 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012359 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012360 || uidRemoved) {
12361 if (checkComponentPermission(
12362 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12363 callingPid, callingUid, -1)
12364 == PackageManager.PERMISSION_GRANTED) {
12365 if (uidRemoved) {
12366 final Bundle intentExtras = intent.getExtras();
12367 final int uid = intentExtras != null
12368 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12369 if (uid >= 0) {
12370 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12371 synchronized (bs) {
12372 bs.removeUidStatsLocked(uid);
12373 }
12374 }
12375 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012376 // If resources are unvailble just force stop all
12377 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012378 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012379 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12380 if (list != null && (list.length > 0)) {
12381 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012382 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012383 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012384 sendPackageBroadcastLocked(
12385 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012386 }
12387 } else {
12388 Uri data = intent.getData();
12389 String ssp;
12390 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12391 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12392 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012393 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012394 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012395 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12396 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12397 new String[] {ssp});
12398 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012399 }
12400 }
12401 }
12402 } else {
12403 String msg = "Permission Denial: " + intent.getAction()
12404 + " broadcast from " + callerPackage + " (pid=" + callingPid
12405 + ", uid=" + callingUid + ")"
12406 + " requires "
12407 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012408 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012409 throw new SecurityException(msg);
12410 }
12411 }
12412
12413 /*
12414 * If this is the time zone changed action, queue up a message that will reset the timezone
12415 * of all currently running processes. This message will get queued up before the broadcast
12416 * happens.
12417 */
12418 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12419 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12420 }
12421
Dianne Hackborn854060af2009-07-09 18:14:31 -070012422 /*
12423 * Prevent non-system code (defined here to be non-persistent
12424 * processes) from sending protected broadcasts.
12425 */
12426 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12427 || callingUid == Process.SHELL_UID || callingUid == 0) {
12428 // Always okay.
12429 } else if (callerApp == null || !callerApp.persistent) {
12430 try {
12431 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12432 intent.getAction())) {
12433 String msg = "Permission Denial: not allowed to send broadcast "
12434 + intent.getAction() + " from pid="
12435 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012436 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012437 throw new SecurityException(msg);
12438 }
12439 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012440 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012441 return BROADCAST_SUCCESS;
12442 }
12443 }
12444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012445 // Add to the sticky list if requested.
12446 if (sticky) {
12447 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12448 callingPid, callingUid)
12449 != PackageManager.PERMISSION_GRANTED) {
12450 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12451 + callingPid + ", uid=" + callingUid
12452 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012453 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012454 throw new SecurityException(msg);
12455 }
12456 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012457 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012458 + " and enforce permission " + requiredPermission);
12459 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12460 }
12461 if (intent.getComponent() != null) {
12462 throw new SecurityException(
12463 "Sticky broadcasts can't target a specific component");
12464 }
12465 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12466 if (list == null) {
12467 list = new ArrayList<Intent>();
12468 mStickyBroadcasts.put(intent.getAction(), list);
12469 }
12470 int N = list.size();
12471 int i;
12472 for (i=0; i<N; i++) {
12473 if (intent.filterEquals(list.get(i))) {
12474 // This sticky already exists, replace it.
12475 list.set(i, new Intent(intent));
12476 break;
12477 }
12478 }
12479 if (i >= N) {
12480 list.add(new Intent(intent));
12481 }
12482 }
12483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012484 // Figure out who all will receive this broadcast.
12485 List receivers = null;
12486 List<BroadcastFilter> registeredReceivers = null;
12487 try {
12488 if (intent.getComponent() != null) {
12489 // Broadcast is going to one specific receiver class...
12490 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012491 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012492 if (ai != null) {
12493 receivers = new ArrayList();
12494 ResolveInfo ri = new ResolveInfo();
12495 ri.activityInfo = ai;
12496 receivers.add(ri);
12497 }
12498 } else {
12499 // Need to resolve the intent to interested receivers...
12500 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12501 == 0) {
12502 receivers =
12503 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012504 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012505 }
Mihai Preda074edef2009-05-18 17:13:31 +020012506 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012507 }
12508 } catch (RemoteException ex) {
12509 // pm is in same process, this will never happen.
12510 }
12511
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012512 final boolean replacePending =
12513 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12514
Joe Onorato8a9b2202010-02-26 18:56:32 -080012515 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012516 + " replacePending=" + replacePending);
12517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012518 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12519 if (!ordered && NR > 0) {
12520 // If we are not serializing this broadcast, then send the
12521 // registered receivers separately so they don't wait for the
12522 // components to be launched.
12523 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12524 callerPackage, callingPid, callingUid, requiredPermission,
12525 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012526 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012527 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012528 TAG, "Enqueueing parallel broadcast " + r
12529 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012530 boolean replaced = false;
12531 if (replacePending) {
12532 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12533 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012534 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012535 "***** DROPPING PARALLEL: " + intent);
12536 mParallelBroadcasts.set(i, r);
12537 replaced = true;
12538 break;
12539 }
12540 }
12541 }
12542 if (!replaced) {
12543 mParallelBroadcasts.add(r);
12544 scheduleBroadcastsLocked();
12545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012546 registeredReceivers = null;
12547 NR = 0;
12548 }
12549
12550 // Merge into one list.
12551 int ir = 0;
12552 if (receivers != null) {
12553 // A special case for PACKAGE_ADDED: do not allow the package
12554 // being added to see this broadcast. This prevents them from
12555 // using this as a back door to get run as soon as they are
12556 // installed. Maybe in the future we want to have a special install
12557 // broadcast or such for apps, but we'd like to deliberately make
12558 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012559 String skipPackages[] = null;
12560 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12561 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12562 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12563 Uri data = intent.getData();
12564 if (data != null) {
12565 String pkgName = data.getSchemeSpecificPart();
12566 if (pkgName != null) {
12567 skipPackages = new String[] { pkgName };
12568 }
12569 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012570 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012571 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012572 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012573 if (skipPackages != null && (skipPackages.length > 0)) {
12574 for (String skipPackage : skipPackages) {
12575 if (skipPackage != null) {
12576 int NT = receivers.size();
12577 for (int it=0; it<NT; it++) {
12578 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12579 if (curt.activityInfo.packageName.equals(skipPackage)) {
12580 receivers.remove(it);
12581 it--;
12582 NT--;
12583 }
12584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012585 }
12586 }
12587 }
12588
12589 int NT = receivers != null ? receivers.size() : 0;
12590 int it = 0;
12591 ResolveInfo curt = null;
12592 BroadcastFilter curr = null;
12593 while (it < NT && ir < NR) {
12594 if (curt == null) {
12595 curt = (ResolveInfo)receivers.get(it);
12596 }
12597 if (curr == null) {
12598 curr = registeredReceivers.get(ir);
12599 }
12600 if (curr.getPriority() >= curt.priority) {
12601 // Insert this broadcast record into the final list.
12602 receivers.add(it, curr);
12603 ir++;
12604 curr = null;
12605 it++;
12606 NT++;
12607 } else {
12608 // Skip to the next ResolveInfo in the final list.
12609 it++;
12610 curt = null;
12611 }
12612 }
12613 }
12614 while (ir < NR) {
12615 if (receivers == null) {
12616 receivers = new ArrayList();
12617 }
12618 receivers.add(registeredReceivers.get(ir));
12619 ir++;
12620 }
12621
12622 if ((receivers != null && receivers.size() > 0)
12623 || resultTo != null) {
12624 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12625 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012626 receivers, resultTo, resultCode, resultData, map, ordered,
12627 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012628 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012629 TAG, "Enqueueing ordered broadcast " + r
12630 + ": prev had " + mOrderedBroadcasts.size());
12631 if (DEBUG_BROADCAST) {
12632 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012633 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012634 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012635 boolean replaced = false;
12636 if (replacePending) {
12637 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12638 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012639 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012640 "***** DROPPING ORDERED: " + intent);
12641 mOrderedBroadcasts.set(i, r);
12642 replaced = true;
12643 break;
12644 }
12645 }
12646 }
12647 if (!replaced) {
12648 mOrderedBroadcasts.add(r);
12649 scheduleBroadcastsLocked();
12650 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012651 }
12652
12653 return BROADCAST_SUCCESS;
12654 }
12655
12656 public final int broadcastIntent(IApplicationThread caller,
12657 Intent intent, String resolvedType, IIntentReceiver resultTo,
12658 int resultCode, String resultData, Bundle map,
12659 String requiredPermission, boolean serialized, boolean sticky) {
12660 // Refuse possible leaked file descriptors
12661 if (intent != null && intent.hasFileDescriptors() == true) {
12662 throw new IllegalArgumentException("File descriptors passed in Intent");
12663 }
12664
12665 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012666 int flags = intent.getFlags();
12667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012668 if (!mSystemReady) {
12669 // if the caller really truly claims to know what they're doing, go
12670 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012671 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12672 intent = new Intent(intent);
12673 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12674 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012675 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012676 + " before boot completion");
12677 throw new IllegalStateException("Cannot broadcast before boot completed");
12678 }
12679 }
12680
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012681 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12682 throw new IllegalArgumentException(
12683 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12684 }
12685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012686 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12687 final int callingPid = Binder.getCallingPid();
12688 final int callingUid = Binder.getCallingUid();
12689 final long origId = Binder.clearCallingIdentity();
12690 int res = broadcastIntentLocked(callerApp,
12691 callerApp != null ? callerApp.info.packageName : null,
12692 intent, resolvedType, resultTo,
12693 resultCode, resultData, map, requiredPermission, serialized,
12694 sticky, callingPid, callingUid);
12695 Binder.restoreCallingIdentity(origId);
12696 return res;
12697 }
12698 }
12699
12700 int broadcastIntentInPackage(String packageName, int uid,
12701 Intent intent, String resolvedType, IIntentReceiver resultTo,
12702 int resultCode, String resultData, Bundle map,
12703 String requiredPermission, boolean serialized, boolean sticky) {
12704 synchronized(this) {
12705 final long origId = Binder.clearCallingIdentity();
12706 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12707 resultTo, resultCode, resultData, map, requiredPermission,
12708 serialized, sticky, -1, uid);
12709 Binder.restoreCallingIdentity(origId);
12710 return res;
12711 }
12712 }
12713
12714 public final void unbroadcastIntent(IApplicationThread caller,
12715 Intent intent) {
12716 // Refuse possible leaked file descriptors
12717 if (intent != null && intent.hasFileDescriptors() == true) {
12718 throw new IllegalArgumentException("File descriptors passed in Intent");
12719 }
12720
12721 synchronized(this) {
12722 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12723 != PackageManager.PERMISSION_GRANTED) {
12724 String msg = "Permission Denial: unbroadcastIntent() from pid="
12725 + Binder.getCallingPid()
12726 + ", uid=" + Binder.getCallingUid()
12727 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012728 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012729 throw new SecurityException(msg);
12730 }
12731 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12732 if (list != null) {
12733 int N = list.size();
12734 int i;
12735 for (i=0; i<N; i++) {
12736 if (intent.filterEquals(list.get(i))) {
12737 list.remove(i);
12738 break;
12739 }
12740 }
12741 }
12742 }
12743 }
12744
12745 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12746 String resultData, Bundle resultExtras, boolean resultAbort,
12747 boolean explicit) {
12748 if (mOrderedBroadcasts.size() == 0) {
12749 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012750 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012751 }
12752 return false;
12753 }
12754 BroadcastRecord r = mOrderedBroadcasts.get(0);
12755 if (r.receiver == null) {
12756 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012757 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012758 }
12759 return false;
12760 }
12761 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012762 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012763 return false;
12764 }
12765 int state = r.state;
12766 r.state = r.IDLE;
12767 if (state == r.IDLE) {
12768 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012769 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012770 }
12771 }
12772 r.receiver = null;
12773 r.intent.setComponent(null);
12774 if (r.curApp != null) {
12775 r.curApp.curReceiver = null;
12776 }
12777 if (r.curFilter != null) {
12778 r.curFilter.receiverList.curBroadcast = null;
12779 }
12780 r.curFilter = null;
12781 r.curApp = null;
12782 r.curComponent = null;
12783 r.curReceiver = null;
12784 mPendingBroadcast = null;
12785
12786 r.resultCode = resultCode;
12787 r.resultData = resultData;
12788 r.resultExtras = resultExtras;
12789 r.resultAbort = resultAbort;
12790
12791 // We will process the next receiver right now if this is finishing
12792 // an app receiver (which is always asynchronous) or after we have
12793 // come back from calling a receiver.
12794 return state == BroadcastRecord.APP_RECEIVE
12795 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12796 }
12797
12798 public void finishReceiver(IBinder who, int resultCode, String resultData,
12799 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012800 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012801
12802 // Refuse possible leaked file descriptors
12803 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12804 throw new IllegalArgumentException("File descriptors passed in Bundle");
12805 }
12806
12807 boolean doNext;
12808
12809 final long origId = Binder.clearCallingIdentity();
12810
12811 synchronized(this) {
12812 doNext = finishReceiverLocked(
12813 who, resultCode, resultData, resultExtras, resultAbort, true);
12814 }
12815
12816 if (doNext) {
12817 processNextBroadcast(false);
12818 }
12819 trimApplications();
12820
12821 Binder.restoreCallingIdentity(origId);
12822 }
12823
12824 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12825 if (r.nextReceiver > 0) {
12826 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12827 if (curReceiver instanceof BroadcastFilter) {
12828 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012829 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012830 System.identityHashCode(r),
12831 r.intent.getAction(),
12832 r.nextReceiver - 1,
12833 System.identityHashCode(bf));
12834 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012835 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012836 System.identityHashCode(r),
12837 r.intent.getAction(),
12838 r.nextReceiver - 1,
12839 ((ResolveInfo)curReceiver).toString());
12840 }
12841 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012842 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012843 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012844 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012845 System.identityHashCode(r),
12846 r.intent.getAction(),
12847 r.nextReceiver,
12848 "NONE");
12849 }
12850 }
12851
12852 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012853 ProcessRecord app = null;
12854 String anrMessage = null;
12855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012856 synchronized (this) {
12857 if (mOrderedBroadcasts.size() == 0) {
12858 return;
12859 }
12860 long now = SystemClock.uptimeMillis();
12861 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012862 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012863 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012864 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012865 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012866 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012867 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012868 return;
12869 }
12870
Joe Onorato8a9b2202010-02-26 18:56:32 -080012871 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012872 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012873 r.anrCount++;
12874
12875 // Current receiver has passed its expiration date.
12876 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012877 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012878 return;
12879 }
12880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012881 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012882 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012883 logBroadcastReceiverDiscard(r);
12884 if (curReceiver instanceof BroadcastFilter) {
12885 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12886 if (bf.receiverList.pid != 0
12887 && bf.receiverList.pid != MY_PID) {
12888 synchronized (this.mPidsSelfLocked) {
12889 app = this.mPidsSelfLocked.get(
12890 bf.receiverList.pid);
12891 }
12892 }
12893 } else {
12894 app = r.curApp;
12895 }
12896
12897 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012898 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012899 }
12900
12901 if (mPendingBroadcast == r) {
12902 mPendingBroadcast = null;
12903 }
12904
12905 // Move on to the next receiver.
12906 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12907 r.resultExtras, r.resultAbort, true);
12908 scheduleBroadcastsLocked();
12909 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012910
12911 if (anrMessage != null) {
12912 appNotResponding(app, null, null, anrMessage);
12913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012914 }
12915
12916 private final void processCurBroadcastLocked(BroadcastRecord r,
12917 ProcessRecord app) throws RemoteException {
12918 if (app.thread == null) {
12919 throw new RemoteException();
12920 }
12921 r.receiver = app.thread.asBinder();
12922 r.curApp = app;
12923 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012924 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012925
12926 // Tell the application to launch this receiver.
12927 r.intent.setComponent(r.curComponent);
12928
12929 boolean started = false;
12930 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012931 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012932 "Delivering to component " + r.curComponent
12933 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012934 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012935 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12936 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12937 started = true;
12938 } finally {
12939 if (!started) {
12940 r.receiver = null;
12941 r.curApp = null;
12942 app.curReceiver = null;
12943 }
12944 }
12945
12946 }
12947
12948 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012949 Intent intent, int resultCode, String data, Bundle extras,
12950 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012951 if (app != null && app.thread != null) {
12952 // If we have an app thread, do the call through that so it is
12953 // correctly ordered with other one-way calls.
12954 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012955 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012956 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012957 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012958 }
12959 }
12960
12961 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12962 BroadcastFilter filter, boolean ordered) {
12963 boolean skip = false;
12964 if (filter.requiredPermission != null) {
12965 int perm = checkComponentPermission(filter.requiredPermission,
12966 r.callingPid, r.callingUid, -1);
12967 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012968 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012969 + r.intent.toString()
12970 + " from " + r.callerPackage + " (pid="
12971 + r.callingPid + ", uid=" + r.callingUid + ")"
12972 + " requires " + filter.requiredPermission
12973 + " due to registered receiver " + filter);
12974 skip = true;
12975 }
12976 }
12977 if (r.requiredPermission != null) {
12978 int perm = checkComponentPermission(r.requiredPermission,
12979 filter.receiverList.pid, filter.receiverList.uid, -1);
12980 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012981 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012982 + r.intent.toString()
12983 + " to " + filter.receiverList.app
12984 + " (pid=" + filter.receiverList.pid
12985 + ", uid=" + filter.receiverList.uid + ")"
12986 + " requires " + r.requiredPermission
12987 + " due to sender " + r.callerPackage
12988 + " (uid " + r.callingUid + ")");
12989 skip = true;
12990 }
12991 }
12992
12993 if (!skip) {
12994 // If this is not being sent as an ordered broadcast, then we
12995 // don't want to touch the fields that keep track of the current
12996 // state of ordered broadcasts.
12997 if (ordered) {
12998 r.receiver = filter.receiverList.receiver.asBinder();
12999 r.curFilter = filter;
13000 filter.receiverList.curBroadcast = r;
13001 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013002 if (filter.receiverList.app != null) {
13003 // Bump hosting application to no longer be in background
13004 // scheduling class. Note that we can't do that if there
13005 // isn't an app... but we can only be in that case for
13006 // things that directly call the IActivityManager API, which
13007 // are already core system stuff so don't matter for this.
13008 r.curApp = filter.receiverList.app;
13009 filter.receiverList.app.curReceiver = r;
13010 updateOomAdjLocked();
13011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013012 }
13013 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013014 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013015 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013016 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013017 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013018 }
13019 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13020 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013021 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013022 if (ordered) {
13023 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13024 }
13025 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013026 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013027 if (ordered) {
13028 r.receiver = null;
13029 r.curFilter = null;
13030 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013031 if (filter.receiverList.app != null) {
13032 filter.receiverList.app.curReceiver = null;
13033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013034 }
13035 }
13036 }
13037 }
13038
Dianne Hackborn12527f92009-11-11 17:39:50 -080013039 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13040 if (r.callingUid < 0) {
13041 // This was from a registerReceiver() call; ignore it.
13042 return;
13043 }
13044 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13045 MAX_BROADCAST_HISTORY-1);
13046 r.finishTime = SystemClock.uptimeMillis();
13047 mBroadcastHistory[0] = r;
13048 }
13049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013050 private final void processNextBroadcast(boolean fromMsg) {
13051 synchronized(this) {
13052 BroadcastRecord r;
13053
Joe Onorato8a9b2202010-02-26 18:56:32 -080013054 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013055 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013056 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013057
13058 updateCpuStats();
13059
13060 if (fromMsg) {
13061 mBroadcastsScheduled = false;
13062 }
13063
13064 // First, deliver any non-serialized broadcasts right away.
13065 while (mParallelBroadcasts.size() > 0) {
13066 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013067 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013068 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013069 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013070 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013071 for (int i=0; i<N; i++) {
13072 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013073 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013074 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013075 + target + ": " + r);
13076 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13077 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013078 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013079 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013080 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013081 }
13082
13083 // Now take care of the next serialized one...
13084
13085 // If we are waiting for a process to come up to handle the next
13086 // broadcast, then do nothing at this point. Just in case, we
13087 // check that the process we're waiting for still exists.
13088 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013089 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013090 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013091 + mPendingBroadcast.curApp);
13092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013093
13094 boolean isDead;
13095 synchronized (mPidsSelfLocked) {
13096 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13097 }
13098 if (!isDead) {
13099 // It's still alive, so keep waiting
13100 return;
13101 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013102 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013103 + " died before responding to broadcast");
13104 mPendingBroadcast = null;
13105 }
13106 }
13107
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013108 boolean looped = false;
13109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013110 do {
13111 if (mOrderedBroadcasts.size() == 0) {
13112 // No more broadcasts pending, so all done!
13113 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013114 if (looped) {
13115 // If we had finished the last ordered broadcast, then
13116 // make sure all processes have correct oom and sched
13117 // adjustments.
13118 updateOomAdjLocked();
13119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013120 return;
13121 }
13122 r = mOrderedBroadcasts.get(0);
13123 boolean forceReceive = false;
13124
13125 // Ensure that even if something goes awry with the timeout
13126 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013127 // and continue to make progress.
13128 //
13129 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
13130 // receivers don't get executed with with timeouts. They're intended for
13131 // one time heavy lifting after system upgrades and can take
13132 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013133 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013134 if (mSystemReady && r.dispatchTime > 0) {
13135 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013136 if ((numReceivers > 0) &&
13137 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013138 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013139 + " now=" + now
13140 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013141 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013142 + " intent=" + r.intent
13143 + " numReceivers=" + numReceivers
13144 + " nextReceiver=" + r.nextReceiver
13145 + " state=" + r.state);
13146 broadcastTimeout(); // forcibly finish this broadcast
13147 forceReceive = true;
13148 r.state = BroadcastRecord.IDLE;
13149 }
13150 }
13151
13152 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013153 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013154 "processNextBroadcast() called when not idle (state="
13155 + r.state + ")");
13156 return;
13157 }
13158
13159 if (r.receivers == null || r.nextReceiver >= numReceivers
13160 || r.resultAbort || forceReceive) {
13161 // No more receivers for this broadcast! Send the final
13162 // result if requested...
13163 if (r.resultTo != null) {
13164 try {
13165 if (DEBUG_BROADCAST) {
13166 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013167 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013168 + " seq=" + seq + " app=" + r.callerApp);
13169 }
13170 performReceive(r.callerApp, r.resultTo,
13171 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013172 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013173 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013174 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013175 }
13176 }
13177
Joe Onorato8a9b2202010-02-26 18:56:32 -080013178 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013179 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13180
Joe Onorato8a9b2202010-02-26 18:56:32 -080013181 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013182 + r);
13183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013184 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013185 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013186 mOrderedBroadcasts.remove(0);
13187 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013188 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013189 continue;
13190 }
13191 } while (r == null);
13192
13193 // Get the next receiver...
13194 int recIdx = r.nextReceiver++;
13195
13196 // Keep track of when this receiver started, and make sure there
13197 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013198 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013199 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013200 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013201
Joe Onorato8a9b2202010-02-26 18:56:32 -080013202 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013203 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013204 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013205 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013206 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013207 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013208 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013209 }
13210
13211 Object nextReceiver = r.receivers.get(recIdx);
13212 if (nextReceiver instanceof BroadcastFilter) {
13213 // Simple case: this is a registered receiver who gets
13214 // a direct call.
13215 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013216 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013217 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013218 + filter + ": " + r);
13219 deliverToRegisteredReceiver(r, filter, r.ordered);
13220 if (r.receiver == null || !r.ordered) {
13221 // The receiver has already finished, so schedule to
13222 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013223 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13224 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013225 r.state = BroadcastRecord.IDLE;
13226 scheduleBroadcastsLocked();
13227 }
13228 return;
13229 }
13230
13231 // Hard case: need to instantiate the receiver, possibly
13232 // starting its application process to host it.
13233
13234 ResolveInfo info =
13235 (ResolveInfo)nextReceiver;
13236
13237 boolean skip = false;
13238 int perm = checkComponentPermission(info.activityInfo.permission,
13239 r.callingPid, r.callingUid,
13240 info.activityInfo.exported
13241 ? -1 : info.activityInfo.applicationInfo.uid);
13242 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013243 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013244 + r.intent.toString()
13245 + " from " + r.callerPackage + " (pid=" + r.callingPid
13246 + ", uid=" + r.callingUid + ")"
13247 + " requires " + info.activityInfo.permission
13248 + " due to receiver " + info.activityInfo.packageName
13249 + "/" + info.activityInfo.name);
13250 skip = true;
13251 }
13252 if (r.callingUid != Process.SYSTEM_UID &&
13253 r.requiredPermission != null) {
13254 try {
13255 perm = ActivityThread.getPackageManager().
13256 checkPermission(r.requiredPermission,
13257 info.activityInfo.applicationInfo.packageName);
13258 } catch (RemoteException e) {
13259 perm = PackageManager.PERMISSION_DENIED;
13260 }
13261 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013262 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013263 + r.intent + " to "
13264 + info.activityInfo.applicationInfo.packageName
13265 + " requires " + r.requiredPermission
13266 + " due to sender " + r.callerPackage
13267 + " (uid " + r.callingUid + ")");
13268 skip = true;
13269 }
13270 }
13271 if (r.curApp != null && r.curApp.crashing) {
13272 // If the target process is crashing, just skip it.
13273 skip = true;
13274 }
13275
13276 if (skip) {
13277 r.receiver = null;
13278 r.curFilter = null;
13279 r.state = BroadcastRecord.IDLE;
13280 scheduleBroadcastsLocked();
13281 return;
13282 }
13283
13284 r.state = BroadcastRecord.APP_RECEIVE;
13285 String targetProcess = info.activityInfo.processName;
13286 r.curComponent = new ComponentName(
13287 info.activityInfo.applicationInfo.packageName,
13288 info.activityInfo.name);
13289 r.curReceiver = info.activityInfo;
13290
13291 // Is this receiver's application already running?
13292 ProcessRecord app = getProcessRecordLocked(targetProcess,
13293 info.activityInfo.applicationInfo.uid);
13294 if (app != null && app.thread != null) {
13295 try {
13296 processCurBroadcastLocked(r, app);
13297 return;
13298 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013299 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013300 + r.curComponent, e);
13301 }
13302
13303 // If a dead object exception was thrown -- fall through to
13304 // restart the application.
13305 }
13306
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013307 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013308 if ((r.curApp=startProcessLocked(targetProcess,
13309 info.activityInfo.applicationInfo, true,
13310 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013311 "broadcast", r.curComponent,
13312 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13313 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013314 // Ah, this recipient is unavailable. Finish it if necessary,
13315 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013316 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013317 + info.activityInfo.applicationInfo.packageName + "/"
13318 + info.activityInfo.applicationInfo.uid + " for broadcast "
13319 + r.intent + ": process is bad");
13320 logBroadcastReceiverDiscard(r);
13321 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13322 r.resultExtras, r.resultAbort, true);
13323 scheduleBroadcastsLocked();
13324 r.state = BroadcastRecord.IDLE;
13325 return;
13326 }
13327
13328 mPendingBroadcast = r;
13329 }
13330 }
13331
13332 // =========================================================
13333 // INSTRUMENTATION
13334 // =========================================================
13335
13336 public boolean startInstrumentation(ComponentName className,
13337 String profileFile, int flags, Bundle arguments,
13338 IInstrumentationWatcher watcher) {
13339 // Refuse possible leaked file descriptors
13340 if (arguments != null && arguments.hasFileDescriptors()) {
13341 throw new IllegalArgumentException("File descriptors passed in Bundle");
13342 }
13343
13344 synchronized(this) {
13345 InstrumentationInfo ii = null;
13346 ApplicationInfo ai = null;
13347 try {
13348 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013349 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013350 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013351 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013352 } catch (PackageManager.NameNotFoundException e) {
13353 }
13354 if (ii == null) {
13355 reportStartInstrumentationFailure(watcher, className,
13356 "Unable to find instrumentation info for: " + className);
13357 return false;
13358 }
13359 if (ai == null) {
13360 reportStartInstrumentationFailure(watcher, className,
13361 "Unable to find instrumentation target package: " + ii.targetPackage);
13362 return false;
13363 }
13364
13365 int match = mContext.getPackageManager().checkSignatures(
13366 ii.targetPackage, ii.packageName);
13367 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13368 String msg = "Permission Denial: starting instrumentation "
13369 + className + " from pid="
13370 + Binder.getCallingPid()
13371 + ", uid=" + Binder.getCallingPid()
13372 + " not allowed because package " + ii.packageName
13373 + " does not have a signature matching the target "
13374 + ii.targetPackage;
13375 reportStartInstrumentationFailure(watcher, className, msg);
13376 throw new SecurityException(msg);
13377 }
13378
13379 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013380 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381 ProcessRecord app = addAppLocked(ai);
13382 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013383 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013384 app.instrumentationProfileFile = profileFile;
13385 app.instrumentationArguments = arguments;
13386 app.instrumentationWatcher = watcher;
13387 app.instrumentationResultClass = className;
13388 Binder.restoreCallingIdentity(origId);
13389 }
13390
13391 return true;
13392 }
13393
13394 /**
13395 * Report errors that occur while attempting to start Instrumentation. Always writes the
13396 * error to the logs, but if somebody is watching, send the report there too. This enables
13397 * the "am" command to report errors with more information.
13398 *
13399 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13400 * @param cn The component name of the instrumentation.
13401 * @param report The error report.
13402 */
13403 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13404 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013405 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013406 try {
13407 if (watcher != null) {
13408 Bundle results = new Bundle();
13409 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13410 results.putString("Error", report);
13411 watcher.instrumentationStatus(cn, -1, results);
13412 }
13413 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013414 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013415 }
13416 }
13417
13418 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13419 if (app.instrumentationWatcher != null) {
13420 try {
13421 // NOTE: IInstrumentationWatcher *must* be oneway here
13422 app.instrumentationWatcher.instrumentationFinished(
13423 app.instrumentationClass,
13424 resultCode,
13425 results);
13426 } catch (RemoteException e) {
13427 }
13428 }
13429 app.instrumentationWatcher = null;
13430 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013431 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013432 app.instrumentationProfileFile = null;
13433 app.instrumentationArguments = null;
13434
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013435 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013436 }
13437
13438 public void finishInstrumentation(IApplicationThread target,
13439 int resultCode, Bundle results) {
13440 // Refuse possible leaked file descriptors
13441 if (results != null && results.hasFileDescriptors()) {
13442 throw new IllegalArgumentException("File descriptors passed in Intent");
13443 }
13444
13445 synchronized(this) {
13446 ProcessRecord app = getRecordForAppLocked(target);
13447 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013448 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013449 return;
13450 }
13451 final long origId = Binder.clearCallingIdentity();
13452 finishInstrumentationLocked(app, resultCode, results);
13453 Binder.restoreCallingIdentity(origId);
13454 }
13455 }
13456
13457 // =========================================================
13458 // CONFIGURATION
13459 // =========================================================
13460
13461 public ConfigurationInfo getDeviceConfigurationInfo() {
13462 ConfigurationInfo config = new ConfigurationInfo();
13463 synchronized (this) {
13464 config.reqTouchScreen = mConfiguration.touchscreen;
13465 config.reqKeyboardType = mConfiguration.keyboard;
13466 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013467 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13468 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013469 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13470 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013471 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13472 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013473 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13474 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013475 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013476 }
13477 return config;
13478 }
13479
13480 public Configuration getConfiguration() {
13481 Configuration ci;
13482 synchronized(this) {
13483 ci = new Configuration(mConfiguration);
13484 }
13485 return ci;
13486 }
13487
13488 public void updateConfiguration(Configuration values) {
13489 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13490 "updateConfiguration()");
13491
13492 synchronized(this) {
13493 if (values == null && mWindowManager != null) {
13494 // sentinel: fetch the current configuration from the window manager
13495 values = mWindowManager.computeNewConfiguration();
13496 }
13497
13498 final long origId = Binder.clearCallingIdentity();
13499 updateConfigurationLocked(values, null);
13500 Binder.restoreCallingIdentity(origId);
13501 }
13502 }
13503
13504 /**
13505 * Do either or both things: (1) change the current configuration, and (2)
13506 * make sure the given activity is running with the (now) current
13507 * configuration. Returns true if the activity has been left running, or
13508 * false if <var>starting</var> is being destroyed to match the new
13509 * configuration.
13510 */
13511 public boolean updateConfigurationLocked(Configuration values,
13512 HistoryRecord starting) {
13513 int changes = 0;
13514
13515 boolean kept = true;
13516
13517 if (values != null) {
13518 Configuration newConfig = new Configuration(mConfiguration);
13519 changes = newConfig.updateFrom(values);
13520 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013521 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013522 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013523 }
13524
Doug Zongker2bec3d42009-12-04 12:52:44 -080013525 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013526
13527 if (values.locale != null) {
13528 saveLocaleLocked(values.locale,
13529 !values.locale.equals(mConfiguration.locale),
13530 values.userSetLocale);
13531 }
13532
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013533 mConfigurationSeq++;
13534 if (mConfigurationSeq <= 0) {
13535 mConfigurationSeq = 1;
13536 }
13537 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013538 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013539 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013540
13541 AttributeCache ac = AttributeCache.instance();
13542 if (ac != null) {
13543 ac.updateConfiguration(mConfiguration);
13544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013545
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013546 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13547 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13548 msg.obj = new Configuration(mConfiguration);
13549 mHandler.sendMessage(msg);
13550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013551
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013552 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13553 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013554 try {
13555 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013556 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013557 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013558 app.thread.scheduleConfigurationChanged(mConfiguration);
13559 }
13560 } catch (Exception e) {
13561 }
13562 }
13563 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013564 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13565 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013566 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13567 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013568 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13569 broadcastIntentLocked(null, null,
13570 new Intent(Intent.ACTION_LOCALE_CHANGED),
13571 null, null, 0, null, null,
13572 null, false, false, MY_PID, Process.SYSTEM_UID);
13573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013574 }
13575 }
13576
13577 if (changes != 0 && starting == null) {
13578 // If the configuration changed, and the caller is not already
13579 // in the process of starting an activity, then find the top
13580 // activity to check if its configuration needs to change.
13581 starting = topRunningActivityLocked(null);
13582 }
13583
13584 if (starting != null) {
13585 kept = ensureActivityConfigurationLocked(starting, changes);
13586 if (kept) {
13587 // If this didn't result in the starting activity being
13588 // destroyed, then we need to make sure at this point that all
13589 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013590 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013591 + ", ensuring others are correct.");
13592 ensureActivitiesVisibleLocked(starting, changes);
13593 }
13594 }
13595
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013596 if (values != null && mWindowManager != null) {
13597 mWindowManager.setNewConfiguration(mConfiguration);
13598 }
13599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013600 return kept;
13601 }
13602
13603 private final boolean relaunchActivityLocked(HistoryRecord r,
13604 int changes, boolean andResume) {
13605 List<ResultInfo> results = null;
13606 List<Intent> newIntents = null;
13607 if (andResume) {
13608 results = r.results;
13609 newIntents = r.newIntents;
13610 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013611 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013612 + " with results=" + results + " newIntents=" + newIntents
13613 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013614 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13615 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013616 r.task.taskId, r.shortComponentName);
13617
13618 r.startFreezingScreenLocked(r.app, 0);
13619
13620 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013621 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013622 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013623 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013624 // Note: don't need to call pauseIfSleepingLocked() here, because
13625 // the caller will only pass in 'andResume' if this activity is
13626 // currently resumed, which implies we aren't sleeping.
13627 } catch (RemoteException e) {
13628 return false;
13629 }
13630
13631 if (andResume) {
13632 r.results = null;
13633 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013634 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013635 }
13636
13637 return true;
13638 }
13639
13640 /**
13641 * Make sure the given activity matches the current configuration. Returns
13642 * false if the activity had to be destroyed. Returns true if the
13643 * configuration is the same, or the activity will remain running as-is
13644 * for whatever reason. Ensures the HistoryRecord is updated with the
13645 * correct configuration and all other bookkeeping is handled.
13646 */
13647 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13648 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013649 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013650 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13651 "Skipping config check (will change): " + r);
13652 return true;
13653 }
13654
Joe Onorato8a9b2202010-02-26 18:56:32 -080013655 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013656 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013657
13658 // Short circuit: if the two configurations are the exact same
13659 // object (the common case), then there is nothing to do.
13660 Configuration newConfig = mConfiguration;
13661 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013662 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013663 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013664 return true;
13665 }
13666
13667 // We don't worry about activities that are finishing.
13668 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013669 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013670 "Configuration doesn't matter in finishing " + r);
13671 r.stopFreezingScreenLocked(false);
13672 return true;
13673 }
13674
13675 // Okay we now are going to make this activity have the new config.
13676 // But then we need to figure out how it needs to deal with that.
13677 Configuration oldConfig = r.configuration;
13678 r.configuration = newConfig;
13679
13680 // If the activity isn't currently running, just leave the new
13681 // configuration and it will pick that up next time it starts.
13682 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013683 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013684 "Configuration doesn't matter not running " + r);
13685 r.stopFreezingScreenLocked(false);
13686 return true;
13687 }
13688
13689 // If the activity isn't persistent, there is a chance we will
13690 // need to restart it.
13691 if (!r.persistent) {
13692
13693 // Figure out what has changed between the two configurations.
13694 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013695 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013696 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013697 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013698 + Integer.toHexString(r.info.configChanges)
13699 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013700 }
13701 if ((changes&(~r.info.configChanges)) != 0) {
13702 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13703 r.configChangeFlags |= changes;
13704 r.startFreezingScreenLocked(r.app, globalChanges);
13705 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013706 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013707 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013708 destroyActivityLocked(r, true);
13709 } else if (r.state == ActivityState.PAUSING) {
13710 // A little annoying: we are waiting for this activity to
13711 // finish pausing. Let's not do anything now, but just
13712 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013713 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013714 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013715 r.configDestroy = true;
13716 return true;
13717 } else if (r.state == ActivityState.RESUMED) {
13718 // Try to optimize this case: the configuration is changing
13719 // and we need to restart the top, resumed activity.
13720 // Instead of doing the normal handshaking, just say
13721 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013722 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013723 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013724 relaunchActivityLocked(r, r.configChangeFlags, true);
13725 r.configChangeFlags = 0;
13726 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013727 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013728 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013729 relaunchActivityLocked(r, r.configChangeFlags, false);
13730 r.configChangeFlags = 0;
13731 }
13732
13733 // All done... tell the caller we weren't able to keep this
13734 // activity around.
13735 return false;
13736 }
13737 }
13738
13739 // Default case: the activity can handle this new configuration, so
13740 // hand it over. Note that we don't need to give it the new
13741 // configuration, since we always send configuration changes to all
13742 // process when they happen so it can just use whatever configuration
13743 // it last got.
13744 if (r.app != null && r.app.thread != null) {
13745 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013746 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013747 r.app.thread.scheduleActivityConfigurationChanged(r);
13748 } catch (RemoteException e) {
13749 // If process died, whatever.
13750 }
13751 }
13752 r.stopFreezingScreenLocked(false);
13753
13754 return true;
13755 }
13756
13757 /**
13758 * Save the locale. You must be inside a synchronized (this) block.
13759 */
13760 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13761 if(isDiff) {
13762 SystemProperties.set("user.language", l.getLanguage());
13763 SystemProperties.set("user.region", l.getCountry());
13764 }
13765
13766 if(isPersist) {
13767 SystemProperties.set("persist.sys.language", l.getLanguage());
13768 SystemProperties.set("persist.sys.country", l.getCountry());
13769 SystemProperties.set("persist.sys.localevar", l.getVariant());
13770 }
13771 }
13772
13773 // =========================================================
13774 // LIFETIME MANAGEMENT
13775 // =========================================================
13776
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013777 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13778 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013779 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013780 // This adjustment has already been computed. If we are calling
13781 // from the top, we may have already computed our adjustment with
13782 // an earlier hidden adjustment that isn't really for us... if
13783 // so, use the new hidden adjustment.
13784 if (!recursed && app.hidden) {
13785 app.curAdj = hiddenAdj;
13786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013787 return app.curAdj;
13788 }
13789
13790 if (app.thread == null) {
13791 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013792 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013793 return (app.curAdj=EMPTY_APP_ADJ);
13794 }
13795
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013796 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13797 // The max adjustment doesn't allow this app to be anything
13798 // below foreground, so it is not worth doing work for it.
13799 app.adjType = "fixed";
13800 app.adjSeq = mAdjSeq;
13801 app.curRawAdj = app.maxAdj;
13802 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13803 return (app.curAdj=app.maxAdj);
13804 }
13805
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013806 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013807 app.adjSource = null;
13808 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013809 app.empty = false;
13810 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013811
The Android Open Source Project4df24232009-03-05 14:34:35 -080013812 // Determine the importance of the process, starting with most
13813 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013814 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013815 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013816 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013817 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013818 // The last app on the list is the foreground app.
13819 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013820 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013821 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013822 } else if (app.instrumentationClass != null) {
13823 // Don't want to kill running instrumentation.
13824 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013825 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013826 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013827 } else if (app.persistentActivities > 0) {
13828 // Special persistent activities... shouldn't be used these days.
13829 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013830 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013831 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013832 } else if (app.curReceiver != null ||
13833 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13834 // An app that is currently receiving a broadcast also
13835 // counts as being in the foreground.
13836 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013837 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013838 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013839 } else if (app.executingServices.size() > 0) {
13840 // An app that is currently executing a service callback also
13841 // counts as being in the foreground.
13842 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013843 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013844 app.adjType = "exec-service";
13845 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013846 // The user is aware of this app, so make it visible.
13847 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013848 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013849 app.adjType = "foreground-service";
13850 } else if (app.forcingToForeground != null) {
13851 // The user is aware of this app, so make it visible.
13852 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013853 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013854 app.adjType = "force-foreground";
13855 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013856 } else if (app == mHomeProcess) {
13857 // This process is hosting what we currently consider to be the
13858 // home app, so we don't want to let it go into the background.
13859 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013860 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013861 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013862 } else if ((N=app.activities.size()) != 0) {
13863 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013864 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013865 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013866 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013867 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013868 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013869 for (int j=0; j<N; j++) {
13870 if (((HistoryRecord)app.activities.get(j)).visible) {
13871 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013872 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013873 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013874 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013875 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013876 break;
13877 }
13878 }
13879 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013880 // A very not-needed process. If this is lower in the lru list,
13881 // we will push it in to the empty bucket.
13882 app.hidden = true;
13883 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013884 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013885 adj = hiddenAdj;
13886 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013887 }
13888
Joe Onorato8a9b2202010-02-26 18:56:32 -080013889 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013890
The Android Open Source Project4df24232009-03-05 14:34:35 -080013891 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013892 // there are applications dependent on our services or providers, but
13893 // this gives us a baseline and makes sure we don't get into an
13894 // infinite recursion.
13895 app.adjSeq = mAdjSeq;
13896 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013897
Christopher Tate6fa95972009-06-05 18:43:55 -070013898 if (mBackupTarget != null && app == mBackupTarget.app) {
13899 // If possible we want to avoid killing apps while they're being backed up
13900 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013901 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013902 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013903 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013904 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013905 }
13906 }
13907
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013908 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13909 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013910 final long now = SystemClock.uptimeMillis();
13911 // This process is more important if the top activity is
13912 // bound to the service.
13913 Iterator jt = app.services.iterator();
13914 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13915 ServiceRecord s = (ServiceRecord)jt.next();
13916 if (s.startRequested) {
13917 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13918 // This service has seen some activity within
13919 // recent memory, so we will keep its process ahead
13920 // of the background processes.
13921 if (adj > SECONDARY_SERVER_ADJ) {
13922 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013923 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013924 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013925 }
13926 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013927 // If we have let the service slide into the background
13928 // state, still have some text describing what it is doing
13929 // even though the service no longer has an impact.
13930 if (adj > SECONDARY_SERVER_ADJ) {
13931 app.adjType = "started-bg-services";
13932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013933 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013934 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13935 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013936 Iterator<ConnectionRecord> kt
13937 = s.connections.values().iterator();
13938 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13939 // XXX should compute this based on the max of
13940 // all connected clients.
13941 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013942 if (cr.binding.client == app) {
13943 // Binding to ourself is not interesting.
13944 continue;
13945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013946 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13947 ProcessRecord client = cr.binding.client;
13948 int myHiddenAdj = hiddenAdj;
13949 if (myHiddenAdj > client.hiddenAdj) {
13950 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13951 myHiddenAdj = client.hiddenAdj;
13952 } else {
13953 myHiddenAdj = VISIBLE_APP_ADJ;
13954 }
13955 }
13956 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013957 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013958 if (adj > clientAdj) {
13959 adj = clientAdj > VISIBLE_APP_ADJ
13960 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013961 if (!client.hidden) {
13962 app.hidden = false;
13963 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013964 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013965 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13966 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013967 app.adjSource = cr.binding.client;
13968 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013969 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013970 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13971 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13972 schedGroup = Process.THREAD_GROUP_DEFAULT;
13973 }
13974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013975 }
13976 HistoryRecord a = cr.activity;
13977 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013978 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013979 //}
13980 if (a != null && adj > FOREGROUND_APP_ADJ &&
13981 (a.state == ActivityState.RESUMED
13982 || a.state == ActivityState.PAUSING)) {
13983 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013984 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013985 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013986 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013987 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13988 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013989 app.adjSource = a;
13990 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013991 }
13992 }
13993 }
13994 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013995
13996 // Finally, f this process has active services running in it, we
13997 // would like to avoid killing it unless it would prevent the current
13998 // application from running. By default we put the process in
13999 // with the rest of the background processes; as we scan through
14000 // its services we may bump it up from there.
14001 if (adj > hiddenAdj) {
14002 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014003 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014004 app.adjType = "bg-services";
14005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014006 }
14007
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014008 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
14009 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014010 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014011 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
14012 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014013 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
14014 if (cpr.clients.size() != 0) {
14015 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14016 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14017 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014018 if (client == app) {
14019 // Being our own client is not interesting.
14020 continue;
14021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014022 int myHiddenAdj = hiddenAdj;
14023 if (myHiddenAdj > client.hiddenAdj) {
14024 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14025 myHiddenAdj = client.hiddenAdj;
14026 } else {
14027 myHiddenAdj = FOREGROUND_APP_ADJ;
14028 }
14029 }
14030 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014031 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014032 if (adj > clientAdj) {
14033 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014034 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014035 if (!client.hidden) {
14036 app.hidden = false;
14037 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014038 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014039 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14040 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014041 app.adjSource = client;
14042 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014043 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014044 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14045 schedGroup = Process.THREAD_GROUP_DEFAULT;
14046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014047 }
14048 }
14049 // If the provider has external (non-framework) process
14050 // dependencies, ensure that its adjustment is at least
14051 // FOREGROUND_APP_ADJ.
14052 if (cpr.externals != 0) {
14053 if (adj > FOREGROUND_APP_ADJ) {
14054 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014055 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014056 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014057 app.adjType = "provider";
14058 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014059 }
14060 }
14061 }
14062 }
14063
14064 app.curRawAdj = adj;
14065
Joe Onorato8a9b2202010-02-26 18:56:32 -080014066 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014067 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14068 if (adj > app.maxAdj) {
14069 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014070 if (app.maxAdj <= VISIBLE_APP_ADJ) {
14071 schedGroup = Process.THREAD_GROUP_DEFAULT;
14072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014073 }
14074
14075 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014076 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014078 return adj;
14079 }
14080
14081 /**
14082 * Ask a given process to GC right now.
14083 */
14084 final void performAppGcLocked(ProcessRecord app) {
14085 try {
14086 app.lastRequestedGc = SystemClock.uptimeMillis();
14087 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014088 if (app.reportLowMemory) {
14089 app.reportLowMemory = false;
14090 app.thread.scheduleLowMemory();
14091 } else {
14092 app.thread.processInBackground();
14093 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014094 }
14095 } catch (Exception e) {
14096 // whatever.
14097 }
14098 }
14099
14100 /**
14101 * Returns true if things are idle enough to perform GCs.
14102 */
Josh Bartel7f208742010-02-25 11:01:44 -060014103 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014104 return mParallelBroadcasts.size() == 0
14105 && mOrderedBroadcasts.size() == 0
14106 && (mSleeping || (mResumedActivity != null &&
14107 mResumedActivity.idle));
14108 }
14109
14110 /**
14111 * Perform GCs on all processes that are waiting for it, but only
14112 * if things are idle.
14113 */
14114 final void performAppGcsLocked() {
14115 final int N = mProcessesToGc.size();
14116 if (N <= 0) {
14117 return;
14118 }
Josh Bartel7f208742010-02-25 11:01:44 -060014119 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014120 while (mProcessesToGc.size() > 0) {
14121 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014122 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
14123 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14124 <= SystemClock.uptimeMillis()) {
14125 // To avoid spamming the system, we will GC processes one
14126 // at a time, waiting a few seconds between each.
14127 performAppGcLocked(proc);
14128 scheduleAppGcsLocked();
14129 return;
14130 } else {
14131 // It hasn't been long enough since we last GCed this
14132 // process... put it in the list to wait for its time.
14133 addProcessToGcListLocked(proc);
14134 break;
14135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014136 }
14137 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014138
14139 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014140 }
14141 }
14142
14143 /**
14144 * If all looks good, perform GCs on all processes waiting for them.
14145 */
14146 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014147 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014148 performAppGcsLocked();
14149 return;
14150 }
14151 // Still not idle, wait some more.
14152 scheduleAppGcsLocked();
14153 }
14154
14155 /**
14156 * Schedule the execution of all pending app GCs.
14157 */
14158 final void scheduleAppGcsLocked() {
14159 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014160
14161 if (mProcessesToGc.size() > 0) {
14162 // Schedule a GC for the time to the next process.
14163 ProcessRecord proc = mProcessesToGc.get(0);
14164 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14165
14166 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14167 long now = SystemClock.uptimeMillis();
14168 if (when < (now+GC_TIMEOUT)) {
14169 when = now + GC_TIMEOUT;
14170 }
14171 mHandler.sendMessageAtTime(msg, when);
14172 }
14173 }
14174
14175 /**
14176 * Add a process to the array of processes waiting to be GCed. Keeps the
14177 * list in sorted order by the last GC time. The process can't already be
14178 * on the list.
14179 */
14180 final void addProcessToGcListLocked(ProcessRecord proc) {
14181 boolean added = false;
14182 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14183 if (mProcessesToGc.get(i).lastRequestedGc <
14184 proc.lastRequestedGc) {
14185 added = true;
14186 mProcessesToGc.add(i+1, proc);
14187 break;
14188 }
14189 }
14190 if (!added) {
14191 mProcessesToGc.add(0, proc);
14192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014193 }
14194
14195 /**
14196 * Set up to ask a process to GC itself. This will either do it
14197 * immediately, or put it on the list of processes to gc the next
14198 * time things are idle.
14199 */
14200 final void scheduleAppGcLocked(ProcessRecord app) {
14201 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014202 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014203 return;
14204 }
14205 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014206 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014207 scheduleAppGcsLocked();
14208 }
14209 }
14210
14211 private final boolean updateOomAdjLocked(
14212 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14213 app.hiddenAdj = hiddenAdj;
14214
14215 if (app.thread == null) {
14216 return true;
14217 }
14218
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014219 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014220
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014221 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014222 if (app.curRawAdj != app.setRawAdj) {
14223 if (app.curRawAdj > FOREGROUND_APP_ADJ
14224 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14225 // If this app is transitioning from foreground to
14226 // non-foreground, have it do a gc.
14227 scheduleAppGcLocked(app);
14228 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14229 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14230 // Likewise do a gc when an app is moving in to the
14231 // background (such as a service stopping).
14232 scheduleAppGcLocked(app);
14233 }
14234 app.setRawAdj = app.curRawAdj;
14235 }
14236 if (adj != app.setAdj) {
14237 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014238 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014239 TAG, "Set app " + app.processName +
14240 " oom adj to " + adj);
14241 app.setAdj = adj;
14242 } else {
14243 return false;
14244 }
14245 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014246 if (app.setSchedGroup != app.curSchedGroup) {
14247 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014248 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014249 "Setting process group of " + app.processName
14250 + " to " + app.curSchedGroup);
14251 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014252 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014253 try {
14254 Process.setProcessGroup(app.pid, app.curSchedGroup);
14255 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014256 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014257 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014258 e.printStackTrace();
14259 } finally {
14260 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014261 }
14262 }
14263 if (false) {
14264 if (app.thread != null) {
14265 try {
14266 app.thread.setSchedulingGroup(app.curSchedGroup);
14267 } catch (RemoteException e) {
14268 }
14269 }
14270 }
14271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014272 }
14273
14274 return true;
14275 }
14276
14277 private final HistoryRecord resumedAppLocked() {
14278 HistoryRecord resumedActivity = mResumedActivity;
14279 if (resumedActivity == null || resumedActivity.app == null) {
14280 resumedActivity = mPausingActivity;
14281 if (resumedActivity == null || resumedActivity.app == null) {
14282 resumedActivity = topRunningActivityLocked(null);
14283 }
14284 }
14285 return resumedActivity;
14286 }
14287
14288 private final boolean updateOomAdjLocked(ProcessRecord app) {
14289 final HistoryRecord TOP_ACT = resumedAppLocked();
14290 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14291 int curAdj = app.curAdj;
14292 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14293 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14294
14295 mAdjSeq++;
14296
14297 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14298 if (res) {
14299 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14300 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14301 if (nowHidden != wasHidden) {
14302 // Changed to/from hidden state, so apps after it in the LRU
14303 // list may also be changed.
14304 updateOomAdjLocked();
14305 }
14306 }
14307 return res;
14308 }
14309
14310 private final boolean updateOomAdjLocked() {
14311 boolean didOomAdj = true;
14312 final HistoryRecord TOP_ACT = resumedAppLocked();
14313 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14314
14315 if (false) {
14316 RuntimeException e = new RuntimeException();
14317 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014318 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014319 }
14320
14321 mAdjSeq++;
14322
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014323 // Let's determine how many processes we have running vs.
14324 // how many slots we have for background processes; we may want
14325 // to put multiple processes in a slot of there are enough of
14326 // them.
14327 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14328 int factor = (mLruProcesses.size()-4)/numSlots;
14329 if (factor < 1) factor = 1;
14330 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014331 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014333 // First try updating the OOM adjustment for each of the
14334 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014335 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014336 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14337 while (i > 0) {
14338 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014339 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014340 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014341 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014342 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014343 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014344 step++;
14345 if (step >= factor) {
14346 step = 0;
14347 curHiddenAdj++;
14348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014349 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014350 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014351 if (!app.killedBackground) {
14352 numHidden++;
14353 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014354 Slog.i(TAG, "No longer want " + app.processName
14355 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014356 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14357 app.processName, app.setAdj, "too many background");
14358 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014359 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014360 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014361 }
14362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014363 } else {
14364 didOomAdj = false;
14365 }
14366 }
14367
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014368 // If we return false, we will fall back on killing processes to
14369 // have a fixed limit. Do this if a limit has been requested; else
14370 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014371 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14372 }
14373
14374 private final void trimApplications() {
14375 synchronized (this) {
14376 int i;
14377
14378 // First remove any unused application processes whose package
14379 // has been removed.
14380 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14381 final ProcessRecord app = mRemovedProcesses.get(i);
14382 if (app.activities.size() == 0
14383 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014384 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014385 TAG, "Exiting empty application process "
14386 + app.processName + " ("
14387 + (app.thread != null ? app.thread.asBinder() : null)
14388 + ")\n");
14389 if (app.pid > 0 && app.pid != MY_PID) {
14390 Process.killProcess(app.pid);
14391 } else {
14392 try {
14393 app.thread.scheduleExit();
14394 } catch (Exception e) {
14395 // Ignore exceptions.
14396 }
14397 }
14398 cleanUpApplicationRecordLocked(app, false, -1);
14399 mRemovedProcesses.remove(i);
14400
14401 if (app.persistent) {
14402 if (app.persistent) {
14403 addAppLocked(app.info);
14404 }
14405 }
14406 }
14407 }
14408
14409 // Now try updating the OOM adjustment for each of the
14410 // application processes based on their current state.
14411 // If the setOomAdj() API is not supported, then go with our
14412 // back-up plan...
14413 if (!updateOomAdjLocked()) {
14414
14415 // Count how many processes are running services.
14416 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014417 for (i=mLruProcesses.size()-1; i>=0; i--) {
14418 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014419
14420 if (app.persistent || app.services.size() != 0
14421 || app.curReceiver != null
14422 || app.persistentActivities > 0) {
14423 // Don't count processes holding services against our
14424 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014425 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014426 TAG, "Not trimming app " + app + " with services: "
14427 + app.services);
14428 numServiceProcs++;
14429 }
14430 }
14431
14432 int curMaxProcs = mProcessLimit;
14433 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14434 if (mAlwaysFinishActivities) {
14435 curMaxProcs = 1;
14436 }
14437 curMaxProcs += numServiceProcs;
14438
14439 // Quit as many processes as we can to get down to the desired
14440 // process count. First remove any processes that no longer
14441 // have activites running in them.
14442 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014443 i<mLruProcesses.size()
14444 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014445 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014446 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014447 // Quit an application only if it is not currently
14448 // running any activities.
14449 if (!app.persistent && app.activities.size() == 0
14450 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014451 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014452 TAG, "Exiting empty application process "
14453 + app.processName + " ("
14454 + (app.thread != null ? app.thread.asBinder() : null)
14455 + ")\n");
14456 if (app.pid > 0 && app.pid != MY_PID) {
14457 Process.killProcess(app.pid);
14458 } else {
14459 try {
14460 app.thread.scheduleExit();
14461 } catch (Exception e) {
14462 // Ignore exceptions.
14463 }
14464 }
14465 // todo: For now we assume the application is not buggy
14466 // or evil, and will quit as a result of our request.
14467 // Eventually we need to drive this off of the death
14468 // notification, and kill the process if it takes too long.
14469 cleanUpApplicationRecordLocked(app, false, i);
14470 i--;
14471 }
14472 }
14473
14474 // If we still have too many processes, now from the least
14475 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014476 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014477 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014478 " of " + curMaxProcs + " processes");
14479 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014480 i<mLruProcesses.size()
14481 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014482 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014483 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014484 // Quit the application only if we have a state saved for
14485 // all of its activities.
14486 boolean canQuit = !app.persistent && app.curReceiver == null
14487 && app.services.size() == 0
14488 && app.persistentActivities == 0;
14489 int NUMA = app.activities.size();
14490 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014491 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014492 TAG, "Looking to quit " + app.processName);
14493 for (j=0; j<NUMA && canQuit; j++) {
14494 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014495 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014496 TAG, " " + r.intent.getComponent().flattenToShortString()
14497 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14498 canQuit = (r.haveState || !r.stateNotNeeded)
14499 && !r.visible && r.stopped;
14500 }
14501 if (canQuit) {
14502 // Finish all of the activities, and then the app itself.
14503 for (j=0; j<NUMA; j++) {
14504 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14505 if (!r.finishing) {
14506 destroyActivityLocked(r, false);
14507 }
14508 r.resultTo = null;
14509 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014510 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014511 + app.processName + " ("
14512 + (app.thread != null ? app.thread.asBinder() : null)
14513 + ")\n");
14514 if (app.pid > 0 && app.pid != MY_PID) {
14515 Process.killProcess(app.pid);
14516 } else {
14517 try {
14518 app.thread.scheduleExit();
14519 } catch (Exception e) {
14520 // Ignore exceptions.
14521 }
14522 }
14523 // todo: For now we assume the application is not buggy
14524 // or evil, and will quit as a result of our request.
14525 // Eventually we need to drive this off of the death
14526 // notification, and kill the process if it takes too long.
14527 cleanUpApplicationRecordLocked(app, false, i);
14528 i--;
14529 //dump();
14530 }
14531 }
14532
14533 }
14534
14535 int curMaxActivities = MAX_ACTIVITIES;
14536 if (mAlwaysFinishActivities) {
14537 curMaxActivities = 1;
14538 }
14539
14540 // Finally, if there are too many activities now running, try to
14541 // finish as many as we can to get back down to the limit.
14542 for ( i=0;
14543 i<mLRUActivities.size()
14544 && mLRUActivities.size() > curMaxActivities;
14545 i++) {
14546 final HistoryRecord r
14547 = (HistoryRecord)mLRUActivities.get(i);
14548
14549 // We can finish this one if we have its icicle saved and
14550 // it is not persistent.
14551 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14552 && r.stopped && !r.persistent && !r.finishing) {
14553 final int origSize = mLRUActivities.size();
14554 destroyActivityLocked(r, true);
14555
14556 // This will remove it from the LRU list, so keep
14557 // our index at the same value. Note that this check to
14558 // see if the size changes is just paranoia -- if
14559 // something unexpected happens, we don't want to end up
14560 // in an infinite loop.
14561 if (origSize > mLRUActivities.size()) {
14562 i--;
14563 }
14564 }
14565 }
14566 }
14567 }
14568
14569 /** This method sends the specified signal to each of the persistent apps */
14570 public void signalPersistentProcesses(int sig) throws RemoteException {
14571 if (sig != Process.SIGNAL_USR1) {
14572 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14573 }
14574
14575 synchronized (this) {
14576 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14577 != PackageManager.PERMISSION_GRANTED) {
14578 throw new SecurityException("Requires permission "
14579 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14580 }
14581
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014582 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14583 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014584 if (r.thread != null && r.persistent) {
14585 Process.sendSignal(r.pid, sig);
14586 }
14587 }
14588 }
14589 }
14590
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014591 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014592 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014593
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014594 try {
14595 synchronized (this) {
14596 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14597 // its own permission.
14598 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14599 != PackageManager.PERMISSION_GRANTED) {
14600 throw new SecurityException("Requires permission "
14601 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014602 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014603
14604 if (start && fd == null) {
14605 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014606 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014607
14608 ProcessRecord proc = null;
14609 try {
14610 int pid = Integer.parseInt(process);
14611 synchronized (mPidsSelfLocked) {
14612 proc = mPidsSelfLocked.get(pid);
14613 }
14614 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014615 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014616
14617 if (proc == null) {
14618 HashMap<String, SparseArray<ProcessRecord>> all
14619 = mProcessNames.getMap();
14620 SparseArray<ProcessRecord> procs = all.get(process);
14621 if (procs != null && procs.size() > 0) {
14622 proc = procs.valueAt(0);
14623 }
14624 }
14625
14626 if (proc == null || proc.thread == null) {
14627 throw new IllegalArgumentException("Unknown process: " + process);
14628 }
14629
14630 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14631 if (isSecure) {
14632 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14633 throw new SecurityException("Process not debuggable: " + proc);
14634 }
14635 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014636
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014637 proc.thread.profilerControl(start, path, fd);
14638 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014639 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014640 }
14641 } catch (RemoteException e) {
14642 throw new IllegalStateException("Process disappeared");
14643 } finally {
14644 if (fd != null) {
14645 try {
14646 fd.close();
14647 } catch (IOException e) {
14648 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014649 }
14650 }
14651 }
14652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014653 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14654 public void monitor() {
14655 synchronized (this) { }
14656 }
14657}