blob: 022eccff19b13a51ca0a563ed8fa1f0fdba1b501 [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 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 broadcastTimeout();
1110 } break;
1111 case PAUSE_TIMEOUT_MSG: {
1112 IBinder token = (IBinder)msg.obj;
1113 // We don't at this point know if the activity is fullscreen,
1114 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001115 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 activityPaused(token, null, true);
1117 } break;
1118 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001119 if (mDidDexOpt) {
1120 mDidDexOpt = false;
1121 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1122 nmsg.obj = msg.obj;
1123 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1124 return;
1125 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001126 // We don't at this point know if the activity is fullscreen,
1127 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001128 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001129 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001130 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 } break;
1132 case DESTROY_TIMEOUT_MSG: {
1133 IBinder token = (IBinder)msg.obj;
1134 // We don't at this point know if the activity is fullscreen,
1135 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001136 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 activityDestroyed(token);
1138 } break;
1139 case IDLE_NOW_MSG: {
1140 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001141 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 } break;
1143 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001144 if (mDidDexOpt) {
1145 mDidDexOpt = false;
1146 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1147 nmsg.obj = msg.obj;
1148 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1149 return;
1150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 serviceTimeout((ProcessRecord)msg.obj);
1152 } break;
1153 case UPDATE_TIME_ZONE: {
1154 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001155 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1156 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 if (r.thread != null) {
1158 try {
1159 r.thread.updateTimeZone();
1160 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001161 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 }
1163 }
1164 }
1165 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001166 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 case SHOW_UID_ERROR_MSG: {
1168 // XXX This is a temporary dialog, no need to localize.
1169 AlertDialog d = new BaseErrorDialog(mContext);
1170 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1171 d.setCancelable(false);
1172 d.setTitle("System UIDs Inconsistent");
1173 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1174 d.setButton("I'm Feeling Lucky",
1175 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1176 mUidAlert = d;
1177 d.show();
1178 } break;
1179 case IM_FEELING_LUCKY_MSG: {
1180 if (mUidAlert != null) {
1181 mUidAlert.dismiss();
1182 mUidAlert = null;
1183 }
1184 } break;
1185 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001186 if (mDidDexOpt) {
1187 mDidDexOpt = false;
1188 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1189 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1190 return;
1191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 synchronized (ActivityManagerService.this) {
1193 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001194 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 mLaunchingActivity.release();
1196 }
1197 }
1198 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 case RESUME_TOP_ACTIVITY_MSG: {
1200 synchronized (ActivityManagerService.this) {
1201 resumeTopActivityLocked(null);
1202 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001203 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001205 if (mDidDexOpt) {
1206 mDidDexOpt = false;
1207 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1208 nmsg.obj = msg.obj;
1209 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1210 return;
1211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 ProcessRecord app = (ProcessRecord)msg.obj;
1213 synchronized (ActivityManagerService.this) {
1214 processStartTimedOutLocked(app);
1215 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001216 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001217 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1218 synchronized (ActivityManagerService.this) {
1219 doPendingActivityLaunchesLocked(true);
1220 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001221 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001222 case KILL_APPLICATION_MSG: {
1223 synchronized (ActivityManagerService.this) {
1224 int uid = msg.arg1;
1225 boolean restart = (msg.arg2 == 1);
1226 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001227 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001228 }
1229 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001230 case FINALIZE_PENDING_INTENT_MSG: {
1231 ((PendingIntentRecord)msg.obj).completeFinalize();
1232 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001233 }
1234 }
1235 };
1236
1237 public static void setSystemProcess() {
1238 try {
1239 ActivityManagerService m = mSelf;
1240
1241 ServiceManager.addService("activity", m);
1242 ServiceManager.addService("meminfo", new MemBinder(m));
1243 if (MONITOR_CPU_USAGE) {
1244 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001246 ServiceManager.addService("permission", new PermissionController(m));
1247
1248 ApplicationInfo info =
1249 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001250 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001251 mSystemThread.installSystemApplicationInfo(info);
1252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 synchronized (mSelf) {
1254 ProcessRecord app = mSelf.newProcessRecordLocked(
1255 mSystemThread.getApplicationThread(), info,
1256 info.processName);
1257 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001258 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 app.maxAdj = SYSTEM_ADJ;
1260 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1261 synchronized (mSelf.mPidsSelfLocked) {
1262 mSelf.mPidsSelfLocked.put(app.pid, app);
1263 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001264 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 }
1266 } catch (PackageManager.NameNotFoundException e) {
1267 throw new RuntimeException(
1268 "Unable to find android system package", e);
1269 }
1270 }
1271
1272 public void setWindowManager(WindowManagerService wm) {
1273 mWindowManager = wm;
1274 }
1275
1276 public static final Context main(int factoryTest) {
1277 AThread thr = new AThread();
1278 thr.start();
1279
1280 synchronized (thr) {
1281 while (thr.mService == null) {
1282 try {
1283 thr.wait();
1284 } catch (InterruptedException e) {
1285 }
1286 }
1287 }
1288
1289 ActivityManagerService m = thr.mService;
1290 mSelf = m;
1291 ActivityThread at = ActivityThread.systemMain();
1292 mSystemThread = at;
1293 Context context = at.getSystemContext();
1294 m.mContext = context;
1295 m.mFactoryTest = factoryTest;
1296 PowerManager pm =
1297 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1298 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1299 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1300 m.mLaunchingActivity.setReferenceCounted(false);
1301
1302 m.mBatteryStatsService.publish(context);
1303 m.mUsageStatsService.publish(context);
1304
1305 synchronized (thr) {
1306 thr.mReady = true;
1307 thr.notifyAll();
1308 }
1309
1310 m.startRunning(null, null, null, null);
1311
1312 return context;
1313 }
1314
1315 public static ActivityManagerService self() {
1316 return mSelf;
1317 }
1318
1319 static class AThread extends Thread {
1320 ActivityManagerService mService;
1321 boolean mReady = false;
1322
1323 public AThread() {
1324 super("ActivityManager");
1325 }
1326
1327 public void run() {
1328 Looper.prepare();
1329
1330 android.os.Process.setThreadPriority(
1331 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1332
1333 ActivityManagerService m = new ActivityManagerService();
1334
1335 synchronized (this) {
1336 mService = m;
1337 notifyAll();
1338 }
1339
1340 synchronized (this) {
1341 while (!mReady) {
1342 try {
1343 wait();
1344 } catch (InterruptedException e) {
1345 }
1346 }
1347 }
1348
1349 Looper.loop();
1350 }
1351 }
1352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 static class MemBinder extends Binder {
1354 ActivityManagerService mActivityManagerService;
1355 MemBinder(ActivityManagerService activityManagerService) {
1356 mActivityManagerService = activityManagerService;
1357 }
1358
1359 @Override
1360 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1361 ActivityManagerService service = mActivityManagerService;
1362 ArrayList<ProcessRecord> procs;
1363 synchronized (mActivityManagerService) {
1364 if (args != null && args.length > 0
1365 && args[0].charAt(0) != '-') {
1366 procs = new ArrayList<ProcessRecord>();
1367 int pid = -1;
1368 try {
1369 pid = Integer.parseInt(args[0]);
1370 } catch (NumberFormatException e) {
1371
1372 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001373 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1374 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 if (proc.pid == pid) {
1376 procs.add(proc);
1377 } else if (proc.processName.equals(args[0])) {
1378 procs.add(proc);
1379 }
1380 }
1381 if (procs.size() <= 0) {
1382 pw.println("No process found for: " + args[0]);
1383 return;
1384 }
1385 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001386 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387 }
1388 }
1389 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1390 }
1391 }
1392
1393 static class CpuBinder extends Binder {
1394 ActivityManagerService mActivityManagerService;
1395 CpuBinder(ActivityManagerService activityManagerService) {
1396 mActivityManagerService = activityManagerService;
1397 }
1398
1399 @Override
1400 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1401 synchronized (mActivityManagerService.mProcessStatsThread) {
1402 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1403 }
1404 }
1405 }
1406
1407 private ActivityManagerService() {
1408 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1409 if (v != null && Integer.getInteger(v) != 0) {
1410 mSimpleProcessManagement = true;
1411 }
1412 v = System.getenv("ANDROID_DEBUG_APP");
1413 if (v != null) {
1414 mSimpleProcessManagement = true;
1415 }
1416
Joe Onorato8a9b2202010-02-26 18:56:32 -08001417 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 File dataDir = Environment.getDataDirectory();
1420 File systemDir = new File(dataDir, "system");
1421 systemDir.mkdirs();
1422 mBatteryStatsService = new BatteryStatsService(new File(
1423 systemDir, "batterystats.bin").toString());
1424 mBatteryStatsService.getActiveStatistics().readLocked();
1425 mBatteryStatsService.getActiveStatistics().writeLocked();
1426
1427 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001428 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429
Jack Palevichb90d28c2009-07-22 15:35:24 -07001430 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1431 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1432
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001433 mConfiguration.setToDefaults();
1434 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 mProcessStats.init();
1436
1437 // Add ourself to the Watchdog monitors.
1438 Watchdog.getInstance().addMonitor(this);
1439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 mProcessStatsThread = new Thread("ProcessStats") {
1441 public void run() {
1442 while (true) {
1443 try {
1444 try {
1445 synchronized(this) {
1446 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001447 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001449 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 // + ", write delay=" + nextWriteDelay);
1451 if (nextWriteDelay < nextCpuDelay) {
1452 nextCpuDelay = nextWriteDelay;
1453 }
1454 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001455 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 this.wait(nextCpuDelay);
1457 }
1458 }
1459 } catch (InterruptedException e) {
1460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 updateCpuStatsNow();
1462 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001463 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 }
1465 }
1466 }
1467 };
1468 mProcessStatsThread.start();
1469 }
1470
1471 @Override
1472 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1473 throws RemoteException {
1474 try {
1475 return super.onTransact(code, data, reply, flags);
1476 } catch (RuntimeException e) {
1477 // The activity manager only throws security exceptions, so let's
1478 // log all others.
1479 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001480 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 }
1482 throw e;
1483 }
1484 }
1485
1486 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001487 final long now = SystemClock.uptimeMillis();
1488 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1489 return;
1490 }
1491 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1492 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 mProcessStatsThread.notify();
1494 }
1495 }
1496 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 void updateCpuStatsNow() {
1499 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001500 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 final long now = SystemClock.uptimeMillis();
1502 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001505 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1506 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 haveNewCpuStats = true;
1508 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001509 //Slog.i(TAG, mProcessStats.printCurrentState());
1510 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 // + mProcessStats.getTotalCpuPercent() + "%");
1512
Joe Onorato8a9b2202010-02-26 18:56:32 -08001513 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 if ("true".equals(SystemProperties.get("events.cpu"))) {
1515 int user = mProcessStats.getLastUserTime();
1516 int system = mProcessStats.getLastSystemTime();
1517 int iowait = mProcessStats.getLastIoWaitTime();
1518 int irq = mProcessStats.getLastIrqTime();
1519 int softIrq = mProcessStats.getLastSoftIrqTime();
1520 int idle = mProcessStats.getLastIdleTime();
1521
1522 int total = user + system + iowait + irq + softIrq + idle;
1523 if (total == 0) total = 1;
1524
Doug Zongker2bec3d42009-12-04 12:52:44 -08001525 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 ((user+system+iowait+irq+softIrq) * 100) / total,
1527 (user * 100) / total,
1528 (system * 100) / total,
1529 (iowait * 100) / total,
1530 (irq * 100) / total,
1531 (softIrq * 100) / total);
1532 }
1533 }
1534
Amith Yamasanie43530a2009-08-21 13:11:37 -07001535 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001536 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001537 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 synchronized(mPidsSelfLocked) {
1539 if (haveNewCpuStats) {
1540 if (mBatteryStatsService.isOnBattery()) {
1541 final int N = mProcessStats.countWorkingStats();
1542 for (int i=0; i<N; i++) {
1543 ProcessStats.Stats st
1544 = mProcessStats.getWorkingStats(i);
1545 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1546 if (pr != null) {
1547 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1548 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001549 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001550 } else {
1551 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001552 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001553 if (ps != null) {
1554 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001555 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 }
1558 }
1559 }
1560 }
1561 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1564 mLastWriteTime = now;
1565 mBatteryStatsService.getActiveStatistics().writeLocked();
1566 }
1567 }
1568 }
1569 }
1570
1571 /**
1572 * Initialize the application bind args. These are passed to each
1573 * process when the bindApplication() IPC is sent to the process. They're
1574 * lazily setup to make sure the services are running when they're asked for.
1575 */
1576 private HashMap<String, IBinder> getCommonServicesLocked() {
1577 if (mAppBindArgs == null) {
1578 mAppBindArgs = new HashMap<String, IBinder>();
1579
1580 // Setup the application init args
1581 mAppBindArgs.put("package", ServiceManager.getService("package"));
1582 mAppBindArgs.put("window", ServiceManager.getService("window"));
1583 mAppBindArgs.put(Context.ALARM_SERVICE,
1584 ServiceManager.getService(Context.ALARM_SERVICE));
1585 }
1586 return mAppBindArgs;
1587 }
1588
1589 private final void setFocusedActivityLocked(HistoryRecord r) {
1590 if (mFocusedActivity != r) {
1591 mFocusedActivity = r;
1592 mWindowManager.setFocusedApp(r, true);
1593 }
1594 }
1595
Dianne Hackborn906497c2010-05-10 15:57:38 -07001596 private final void updateLruProcessInternalLocked(ProcessRecord app,
1597 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001599 int lrui = mLruProcesses.indexOf(app);
1600 if (lrui >= 0) mLruProcesses.remove(lrui);
1601
1602 int i = mLruProcesses.size()-1;
1603 int skipTop = 0;
1604
Dianne Hackborn906497c2010-05-10 15:57:38 -07001605 app.lruSeq = mLruSeq;
1606
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001607 // compute the new weight for this process.
1608 if (updateActivityTime) {
1609 app.lastActivityTime = SystemClock.uptimeMillis();
1610 }
1611 if (app.activities.size() > 0) {
1612 // If this process has activities, we more strongly want to keep
1613 // it around.
1614 app.lruWeight = app.lastActivityTime;
1615 } else if (app.pubProviders.size() > 0) {
1616 // If this process contains content providers, we want to keep
1617 // it a little more strongly.
1618 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1619 // Also don't let it kick out the first few "real" hidden processes.
1620 skipTop = MIN_HIDDEN_APPS;
1621 } else {
1622 // If this process doesn't have activities, we less strongly
1623 // want to keep it around, and generally want to avoid getting
1624 // in front of any very recently used activities.
1625 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1626 // Also don't let it kick out the first few "real" hidden processes.
1627 skipTop = MIN_HIDDEN_APPS;
1628 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001629
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001630 while (i >= 0) {
1631 ProcessRecord p = mLruProcesses.get(i);
1632 // If this app shouldn't be in front of the first N background
1633 // apps, then skip over that many that are currently hidden.
1634 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1635 skipTop--;
1636 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001637 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001638 mLruProcesses.add(i+1, app);
1639 break;
1640 }
1641 i--;
1642 }
1643 if (i < 0) {
1644 mLruProcesses.add(0, app);
1645 }
1646
Dianne Hackborn906497c2010-05-10 15:57:38 -07001647 // If the app is currently using a content provider or service,
1648 // bump those processes as well.
1649 if (app.connections.size() > 0) {
1650 for (ConnectionRecord cr : app.connections) {
1651 if (cr.binding != null && cr.binding.service != null
1652 && cr.binding.service.app != null
1653 && cr.binding.service.app.lruSeq != mLruSeq) {
1654 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1655 updateActivityTime, i+1);
1656 }
1657 }
1658 }
1659 if (app.conProviders.size() > 0) {
1660 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1661 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1662 updateLruProcessInternalLocked(cpr.app, oomAdj,
1663 updateActivityTime, i+1);
1664 }
1665 }
1666 }
1667
Joe Onorato8a9b2202010-02-26 18:56:32 -08001668 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669 if (oomAdj) {
1670 updateOomAdjLocked();
1671 }
1672 }
1673
Dianne Hackborn906497c2010-05-10 15:57:38 -07001674 private final void updateLruProcessLocked(ProcessRecord app,
1675 boolean oomAdj, boolean updateActivityTime) {
1676 mLruSeq++;
1677 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1678 }
1679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 private final boolean updateLRUListLocked(HistoryRecord r) {
1681 final boolean hadit = mLRUActivities.remove(r);
1682 mLRUActivities.add(r);
1683 return hadit;
1684 }
1685
1686 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1687 int i = mHistory.size()-1;
1688 while (i >= 0) {
1689 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1690 if (!r.finishing && r != notTop) {
1691 return r;
1692 }
1693 i--;
1694 }
1695 return null;
1696 }
1697
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001698 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1699 int i = mHistory.size()-1;
1700 while (i >= 0) {
1701 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1702 if (!r.finishing && !r.delayedResume && r != notTop) {
1703 return r;
1704 }
1705 i--;
1706 }
1707 return null;
1708 }
1709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 /**
1711 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001712 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 *
1714 * @param token If non-null, any history records matching this token will be skipped.
1715 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1716 *
1717 * @return Returns the HistoryRecord of the next activity on the stack.
1718 */
1719 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1720 int i = mHistory.size()-1;
1721 while (i >= 0) {
1722 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1723 // Note: the taskId check depends on real taskId fields being non-zero
1724 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1725 return r;
1726 }
1727 i--;
1728 }
1729 return null;
1730 }
1731
1732 private final ProcessRecord getProcessRecordLocked(
1733 String processName, int uid) {
1734 if (uid == Process.SYSTEM_UID) {
1735 // The system gets to run in any process. If there are multiple
1736 // processes with the same uid, just pick the first (this
1737 // should never happen).
1738 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1739 processName);
1740 return procs != null ? procs.valueAt(0) : null;
1741 }
1742 ProcessRecord proc = mProcessNames.get(processName, uid);
1743 return proc;
1744 }
1745
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001746 private void ensurePackageDexOpt(String packageName) {
1747 IPackageManager pm = ActivityThread.getPackageManager();
1748 try {
1749 if (pm.performDexOpt(packageName)) {
1750 mDidDexOpt = true;
1751 }
1752 } catch (RemoteException e) {
1753 }
1754 }
1755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 private boolean isNextTransitionForward() {
1757 int transit = mWindowManager.getPendingAppTransition();
1758 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1759 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1760 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1761 }
1762
1763 private final boolean realStartActivityLocked(HistoryRecord r,
1764 ProcessRecord app, boolean andResume, boolean checkConfig)
1765 throws RemoteException {
1766
1767 r.startFreezingScreenLocked(app, 0);
1768 mWindowManager.setAppVisibility(r, true);
1769
1770 // Have the window manager re-evaluate the orientation of
1771 // the screen based on the new activity order. Note that
1772 // as a result of this, it can call back into the activity
1773 // manager with a new orientation. We don't care about that,
1774 // because the activity is not currently running so we are
1775 // just restarting it anyway.
1776 if (checkConfig) {
1777 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001778 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 r.mayFreezeScreenLocked(app) ? r : null);
1780 updateConfigurationLocked(config, r);
1781 }
1782
1783 r.app = app;
1784
Joe Onorato8a9b2202010-02-26 18:56:32 -08001785 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786
1787 int idx = app.activities.indexOf(r);
1788 if (idx < 0) {
1789 app.activities.add(r);
1790 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001791 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792
1793 try {
1794 if (app.thread == null) {
1795 throw new RemoteException();
1796 }
1797 List<ResultInfo> results = null;
1798 List<Intent> newIntents = null;
1799 if (andResume) {
1800 results = r.results;
1801 newIntents = r.newIntents;
1802 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001803 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 + " icicle=" + r.icicle
1805 + " with results=" + results + " newIntents=" + newIntents
1806 + " andResume=" + andResume);
1807 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001808 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 System.identityHashCode(r),
1810 r.task.taskId, r.shortComponentName);
1811 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001812 if (r.isHomeActivity) {
1813 mHomeProcess = app;
1814 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001815 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001817 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 r.info, r.icicle, results, newIntents, !andResume,
1819 isNextTransitionForward());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 } catch (RemoteException e) {
1821 if (r.launchFailed) {
1822 // This is the second time we failed -- finish activity
1823 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001824 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 + r.intent.getComponent().flattenToShortString()
1826 + ", giving up", e);
1827 appDiedLocked(app, app.pid, app.thread);
1828 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1829 "2nd-crash");
1830 return false;
1831 }
1832
1833 // This is the first time we failed -- restart process and
1834 // retry.
1835 app.activities.remove(r);
1836 throw e;
1837 }
1838
1839 r.launchFailed = false;
1840 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001841 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001842 + " being launched, but already in LRU list");
1843 }
1844
1845 if (andResume) {
1846 // As part of the process of launching, ActivityThread also performs
1847 // a resume.
1848 r.state = ActivityState.RESUMED;
1849 r.icicle = null;
1850 r.haveState = false;
1851 r.stopped = false;
1852 mResumedActivity = r;
1853 r.task.touchActiveTime();
1854 completeResumeLocked(r);
1855 pauseIfSleepingLocked();
1856 } else {
1857 // This activity is not starting in the resumed state... which
1858 // should look like we asked it to pause+stop (but remain visible),
1859 // and it has done so and reported back the current icicle and
1860 // other state.
1861 r.state = ActivityState.STOPPED;
1862 r.stopped = true;
1863 }
1864
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001865 // Launch the new version setup screen if needed. We do this -after-
1866 // launching the initial activity (that is, home), so that it can have
1867 // a chance to initialize itself while in the background, making the
1868 // switch back to it faster and look better.
1869 startSetupActivityLocked();
1870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 return true;
1872 }
1873
1874 private final void startSpecificActivityLocked(HistoryRecord r,
1875 boolean andResume, boolean checkConfig) {
1876 // Is this activity's application already running?
1877 ProcessRecord app = getProcessRecordLocked(r.processName,
1878 r.info.applicationInfo.uid);
1879
1880 if (r.startTime == 0) {
1881 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001882 if (mInitialStartTime == 0) {
1883 mInitialStartTime = r.startTime;
1884 }
1885 } else if (mInitialStartTime == 0) {
1886 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 }
1888
1889 if (app != null && app.thread != null) {
1890 try {
1891 realStartActivityLocked(r, app, andResume, checkConfig);
1892 return;
1893 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001894 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 + r.intent.getComponent().flattenToShortString(), e);
1896 }
1897
1898 // If a dead object exception was thrown -- fall through to
1899 // restart the application.
1900 }
1901
1902 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001903 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001904 }
1905
1906 private final ProcessRecord startProcessLocked(String processName,
1907 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001908 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1910 // We don't have to do anything more if:
1911 // (1) There is an existing application record; and
1912 // (2) The caller doesn't think it is dead, OR there is no thread
1913 // object attached to it so we know it couldn't have crashed; and
1914 // (3) There is a pid assigned to it, so it is either starting or
1915 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001916 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 + " app=" + app + " knownToBeDead=" + knownToBeDead
1918 + " thread=" + (app != null ? app.thread : null)
1919 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001920 if (app != null && app.pid > 0) {
1921 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001922 // We already have the app running, or are waiting for it to
1923 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001924 return app;
1925 } else {
1926 // An application record is attached to a previous process,
1927 // clean it up now.
1928 handleAppDiedLocked(app, true);
1929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001932 String hostingNameStr = hostingName != null
1933 ? hostingName.flattenToShortString() : null;
1934
1935 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1936 // If we are in the background, then check to see if this process
1937 // is bad. If so, we will just silently fail.
1938 if (mBadProcesses.get(info.processName, info.uid) != null) {
1939 return null;
1940 }
1941 } else {
1942 // When the user is explicitly starting a process, then clear its
1943 // crash count so that we won't make it bad until they see at
1944 // least one crash dialog again, and make the process good again
1945 // if it had been bad.
1946 mProcessCrashTimes.remove(info.processName, info.uid);
1947 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001948 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 info.processName);
1950 mBadProcesses.remove(info.processName, info.uid);
1951 if (app != null) {
1952 app.bad = false;
1953 }
1954 }
1955 }
1956
1957 if (app == null) {
1958 app = newProcessRecordLocked(null, info, processName);
1959 mProcessNames.put(processName, info.uid, app);
1960 } else {
1961 // If this is a new package in the process, add the package to the list
1962 app.addPackage(info.packageName);
1963 }
1964
1965 // If the system is not ready yet, then hold off on starting this
1966 // process until it is.
1967 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001968 && !isAllowedWhileBooting(info)
1969 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 if (!mProcessesOnHold.contains(app)) {
1971 mProcessesOnHold.add(app);
1972 }
1973 return app;
1974 }
1975
1976 startProcessLocked(app, hostingType, hostingNameStr);
1977 return (app.pid != 0) ? app : null;
1978 }
1979
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001980 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1981 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1982 }
1983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001984 private final void startProcessLocked(ProcessRecord app,
1985 String hostingType, String hostingNameStr) {
1986 if (app.pid > 0 && app.pid != MY_PID) {
1987 synchronized (mPidsSelfLocked) {
1988 mPidsSelfLocked.remove(app.pid);
1989 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1990 }
1991 app.pid = 0;
1992 }
1993
1994 mProcessesOnHold.remove(app);
1995
1996 updateCpuStats();
1997
1998 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1999 mProcDeaths[0] = 0;
2000
2001 try {
2002 int uid = app.info.uid;
2003 int[] gids = null;
2004 try {
2005 gids = mContext.getPackageManager().getPackageGids(
2006 app.info.packageName);
2007 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002008 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002009 }
2010 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2011 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2012 && mTopComponent != null
2013 && app.processName.equals(mTopComponent.getPackageName())) {
2014 uid = 0;
2015 }
2016 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2017 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2018 uid = 0;
2019 }
2020 }
2021 int debugFlags = 0;
2022 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2023 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
2024 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002025 // Run the app in safe mode if its manifest requests so or the
2026 // system is booted in safe mode.
2027 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2028 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002029 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2032 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2033 }
2034 if ("1".equals(SystemProperties.get("debug.assert"))) {
2035 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2036 }
2037 int pid = Process.start("android.app.ActivityThread",
2038 mSimpleProcessManagement ? app.processName : null, uid, uid,
2039 gids, debugFlags, null);
2040 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2041 synchronized (bs) {
2042 if (bs.isOnBattery()) {
2043 app.batteryStats.incStartsLocked();
2044 }
2045 }
2046
Doug Zongker2bec3d42009-12-04 12:52:44 -08002047 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 app.processName, hostingType,
2049 hostingNameStr != null ? hostingNameStr : "");
2050
2051 if (app.persistent) {
2052 Watchdog.getInstance().processStarted(app, app.processName, pid);
2053 }
2054
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002055 StringBuilder buf = mStringBuilder;
2056 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 buf.append("Start proc ");
2058 buf.append(app.processName);
2059 buf.append(" for ");
2060 buf.append(hostingType);
2061 if (hostingNameStr != null) {
2062 buf.append(" ");
2063 buf.append(hostingNameStr);
2064 }
2065 buf.append(": pid=");
2066 buf.append(pid);
2067 buf.append(" uid=");
2068 buf.append(uid);
2069 buf.append(" gids={");
2070 if (gids != null) {
2071 for (int gi=0; gi<gids.length; gi++) {
2072 if (gi != 0) buf.append(", ");
2073 buf.append(gids[gi]);
2074
2075 }
2076 }
2077 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002078 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 if (pid == 0 || pid == MY_PID) {
2080 // Processes are being emulated with threads.
2081 app.pid = MY_PID;
2082 app.removed = false;
2083 mStartingProcesses.add(app);
2084 } else if (pid > 0) {
2085 app.pid = pid;
2086 app.removed = false;
2087 synchronized (mPidsSelfLocked) {
2088 this.mPidsSelfLocked.put(pid, app);
2089 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2090 msg.obj = app;
2091 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2092 }
2093 } else {
2094 app.pid = 0;
2095 RuntimeException e = new RuntimeException(
2096 "Failure starting process " + app.processName
2097 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002098 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 }
2100 } catch (RuntimeException e) {
2101 // XXX do better error recovery.
2102 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002103 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002104 }
2105 }
2106
2107 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2108 if (mPausingActivity != null) {
2109 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002110 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002111 + mPausingActivity, e);
2112 }
2113 HistoryRecord prev = mResumedActivity;
2114 if (prev == null) {
2115 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002116 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 resumeTopActivityLocked(null);
2118 return;
2119 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002120 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 mResumedActivity = null;
2122 mPausingActivity = prev;
2123 mLastPausedActivity = prev;
2124 prev.state = ActivityState.PAUSING;
2125 prev.task.touchActiveTime();
2126
2127 updateCpuStats();
2128
2129 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002130 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002132 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 System.identityHashCode(prev),
2134 prev.shortComponentName);
2135 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2136 prev.configChangeFlags);
2137 updateUsageStats(prev, false);
2138 } catch (Exception e) {
2139 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002140 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 mPausingActivity = null;
2142 mLastPausedActivity = null;
2143 }
2144 } else {
2145 mPausingActivity = null;
2146 mLastPausedActivity = null;
2147 }
2148
2149 // If we are not going to sleep, we want to ensure the device is
2150 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002151 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 mLaunchingActivity.acquire();
2153 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2154 // To be safe, don't allow the wake lock to be held for too long.
2155 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2156 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2157 }
2158 }
2159
2160
2161 if (mPausingActivity != null) {
2162 // Have the window manager pause its key dispatching until the new
2163 // activity has started. If we're pausing the activity just because
2164 // the screen is being turned off and the UI is sleeping, don't interrupt
2165 // key dispatch; the same activity will pick it up again on wakeup.
2166 if (!uiSleeping) {
2167 prev.pauseKeyDispatchingLocked();
2168 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002169 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 }
2171
2172 // Schedule a pause timeout in case the app doesn't respond.
2173 // We don't give it much time because this directly impacts the
2174 // responsiveness seen by the user.
2175 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2176 msg.obj = prev;
2177 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002178 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 } else {
2180 // This activity failed to schedule the
2181 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002182 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 resumeTopActivityLocked(null);
2184 }
2185 }
2186
2187 private final void completePauseLocked() {
2188 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002189 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190
2191 if (prev != null) {
2192 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002193 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002194 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2195 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002196 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002197 if (prev.waitingVisible) {
2198 prev.waitingVisible = false;
2199 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002200 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 TAG, "Complete pause, no longer waiting: " + prev);
2202 }
2203 if (prev.configDestroy) {
2204 // The previous is being paused because the configuration
2205 // is changing, which means it is actually stopping...
2206 // To juggle the fact that we are also starting a new
2207 // instance right now, we need to first completely stop
2208 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002209 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 destroyActivityLocked(prev, true);
2211 } else {
2212 mStoppingActivities.add(prev);
2213 if (mStoppingActivities.size() > 3) {
2214 // If we already have a few activities waiting to stop,
2215 // then give up on things going idle and start clearing
2216 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002217 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 Message msg = Message.obtain();
2219 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2220 mHandler.sendMessage(msg);
2221 }
2222 }
2223 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002224 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002225 prev = null;
2226 }
2227 mPausingActivity = null;
2228 }
2229
Dianne Hackborn55280a92009-05-07 15:53:46 -07002230 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 resumeTopActivityLocked(prev);
2232 } else {
2233 if (mGoingToSleep.isHeld()) {
2234 mGoingToSleep.release();
2235 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002236 if (mShuttingDown) {
2237 notifyAll();
2238 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002239 }
2240
2241 if (prev != null) {
2242 prev.resumeKeyDispatchingLocked();
2243 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002244
2245 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2246 long diff = 0;
2247 synchronized (mProcessStatsThread) {
2248 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2249 }
2250 if (diff > 0) {
2251 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2252 synchronized (bsi) {
2253 BatteryStatsImpl.Uid.Proc ps =
2254 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2255 prev.info.packageName);
2256 if (ps != null) {
2257 ps.addForegroundTimeLocked(diff);
2258 }
2259 }
2260 }
2261 }
2262 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263 }
2264
2265 /**
2266 * Once we know that we have asked an application to put an activity in
2267 * the resumed state (either by launching it or explicitly telling it),
2268 * this function updates the rest of our state to match that fact.
2269 */
2270 private final void completeResumeLocked(HistoryRecord next) {
2271 next.idle = false;
2272 next.results = null;
2273 next.newIntents = null;
2274
2275 // schedule an idle timeout in case the app doesn't do it for us.
2276 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2277 msg.obj = next;
2278 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2279
2280 if (false) {
2281 // The activity was never told to pause, so just keep
2282 // things going as-is. To maintain our own state,
2283 // we need to emulate it coming back and saying it is
2284 // idle.
2285 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2286 msg.obj = next;
2287 mHandler.sendMessage(msg);
2288 }
2289
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002290 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292 next.thumbnail = null;
2293 setFocusedActivityLocked(next);
2294 next.resumeKeyDispatchingLocked();
2295 ensureActivitiesVisibleLocked(null, 0);
2296 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002297 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002298
2299 // Mark the point when the activity is resuming
2300 // TODO: To be more accurate, the mark should be before the onCreate,
2301 // not after the onResume. But for subsequent starts, onResume is fine.
2302 if (next.app != null) {
2303 synchronized (mProcessStatsThread) {
2304 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2305 }
2306 } else {
2307 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 }
2310
2311 /**
2312 * Make sure that all activities that need to be visible (that is, they
2313 * currently can be seen by the user) actually are.
2314 */
2315 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2316 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002317 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 TAG, "ensureActivitiesVisible behind " + top
2319 + " configChanges=0x" + Integer.toHexString(configChanges));
2320
2321 // If the top activity is not fullscreen, then we need to
2322 // make sure any activities under it are now visible.
2323 final int count = mHistory.size();
2324 int i = count-1;
2325 while (mHistory.get(i) != top) {
2326 i--;
2327 }
2328 HistoryRecord r;
2329 boolean behindFullscreen = false;
2330 for (; i>=0; i--) {
2331 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002332 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 TAG, "Make visible? " + r + " finishing=" + r.finishing
2334 + " state=" + r.state);
2335 if (r.finishing) {
2336 continue;
2337 }
2338
2339 final boolean doThisProcess = onlyThisProcess == null
2340 || onlyThisProcess.equals(r.processName);
2341
2342 // First: if this is not the current activity being started, make
2343 // sure it matches the current configuration.
2344 if (r != starting && doThisProcess) {
2345 ensureActivityConfigurationLocked(r, 0);
2346 }
2347
2348 if (r.app == null || r.app.thread == null) {
2349 if (onlyThisProcess == null
2350 || onlyThisProcess.equals(r.processName)) {
2351 // This activity needs to be visible, but isn't even
2352 // running... get it started, but don't resume it
2353 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002354 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002355 TAG, "Start and freeze screen for " + r);
2356 if (r != starting) {
2357 r.startFreezingScreenLocked(r.app, configChanges);
2358 }
2359 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002360 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 TAG, "Starting and making visible: " + r);
2362 mWindowManager.setAppVisibility(r, true);
2363 }
2364 if (r != starting) {
2365 startSpecificActivityLocked(r, false, false);
2366 }
2367 }
2368
2369 } else if (r.visible) {
2370 // If this activity is already visible, then there is nothing
2371 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002372 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 TAG, "Skipping: already visible at " + r);
2374 r.stopFreezingScreenLocked(false);
2375
2376 } else if (onlyThisProcess == null) {
2377 // This activity is not currently visible, but is running.
2378 // Tell it to become visible.
2379 r.visible = true;
2380 if (r.state != ActivityState.RESUMED && r != starting) {
2381 // If this activity is paused, tell it
2382 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002383 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002384 TAG, "Making visible and scheduling visibility: " + r);
2385 try {
2386 mWindowManager.setAppVisibility(r, true);
2387 r.app.thread.scheduleWindowVisibility(r, true);
2388 r.stopFreezingScreenLocked(false);
2389 } catch (Exception e) {
2390 // Just skip on any failure; we'll make it
2391 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002392 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393 + r.intent.getComponent(), e);
2394 }
2395 }
2396 }
2397
2398 // Aggregate current change flags.
2399 configChanges |= r.configChangeFlags;
2400
2401 if (r.fullscreen) {
2402 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002403 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404 TAG, "Stopping: fullscreen at " + r);
2405 behindFullscreen = true;
2406 i--;
2407 break;
2408 }
2409 }
2410
2411 // Now for any activities that aren't visible to the user, make
2412 // sure they no longer are keeping the screen frozen.
2413 while (i >= 0) {
2414 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002415 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002416 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2417 + " state=" + r.state
2418 + " behindFullscreen=" + behindFullscreen);
2419 if (!r.finishing) {
2420 if (behindFullscreen) {
2421 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002422 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002423 TAG, "Making invisible: " + r);
2424 r.visible = false;
2425 try {
2426 mWindowManager.setAppVisibility(r, false);
2427 if ((r.state == ActivityState.STOPPING
2428 || r.state == ActivityState.STOPPED)
2429 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002430 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002431 TAG, "Scheduling invisibility: " + r);
2432 r.app.thread.scheduleWindowVisibility(r, false);
2433 }
2434 } catch (Exception e) {
2435 // Just skip on any failure; we'll make it
2436 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002437 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002438 + r.intent.getComponent(), e);
2439 }
2440 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002441 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 TAG, "Already invisible: " + r);
2443 }
2444 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002445 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002446 TAG, "Now behindFullscreen: " + r);
2447 behindFullscreen = true;
2448 }
2449 }
2450 i--;
2451 }
2452 }
2453
2454 /**
2455 * Version of ensureActivitiesVisible that can easily be called anywhere.
2456 */
2457 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2458 int configChanges) {
2459 HistoryRecord r = topRunningActivityLocked(null);
2460 if (r != null) {
2461 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2462 }
2463 }
2464
2465 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2466 if (resumed) {
2467 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2468 } else {
2469 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2470 }
2471 }
2472
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002473 private boolean startHomeActivityLocked() {
2474 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2475 && mTopAction == null) {
2476 // We are running in factory test mode, but unable to find
2477 // the factory test app, so just sit around displaying the
2478 // error message and don't try to start anything.
2479 return false;
2480 }
2481 Intent intent = new Intent(
2482 mTopAction,
2483 mTopData != null ? Uri.parse(mTopData) : null);
2484 intent.setComponent(mTopComponent);
2485 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2486 intent.addCategory(Intent.CATEGORY_HOME);
2487 }
2488 ActivityInfo aInfo =
2489 intent.resolveActivityInfo(mContext.getPackageManager(),
2490 STOCK_PM_FLAGS);
2491 if (aInfo != null) {
2492 intent.setComponent(new ComponentName(
2493 aInfo.applicationInfo.packageName, aInfo.name));
2494 // Don't do this if the home app is currently being
2495 // instrumented.
2496 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2497 aInfo.applicationInfo.uid);
2498 if (app == null || app.instrumentationClass == null) {
2499 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2500 startActivityLocked(null, intent, null, null, 0, aInfo,
2501 null, null, 0, 0, 0, false, false);
2502 }
2503 }
2504
2505
2506 return true;
2507 }
2508
2509 /**
2510 * Starts the "new version setup screen" if appropriate.
2511 */
2512 private void startSetupActivityLocked() {
2513 // Only do this once per boot.
2514 if (mCheckedForSetup) {
2515 return;
2516 }
2517
2518 // We will show this screen if the current one is a different
2519 // version than the last one shown, and we are not running in
2520 // low-level factory test mode.
2521 final ContentResolver resolver = mContext.getContentResolver();
2522 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2523 Settings.Secure.getInt(resolver,
2524 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2525 mCheckedForSetup = true;
2526
2527 // See if we should be showing the platform update setup UI.
2528 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2529 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2530 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2531
2532 // We don't allow third party apps to replace this.
2533 ResolveInfo ri = null;
2534 for (int i=0; ris != null && i<ris.size(); i++) {
2535 if ((ris.get(i).activityInfo.applicationInfo.flags
2536 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2537 ri = ris.get(i);
2538 break;
2539 }
2540 }
2541
2542 if (ri != null) {
2543 String vers = ri.activityInfo.metaData != null
2544 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2545 : null;
2546 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2547 vers = ri.activityInfo.applicationInfo.metaData.getString(
2548 Intent.METADATA_SETUP_VERSION);
2549 }
2550 String lastVers = Settings.Secure.getString(
2551 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2552 if (vers != null && !vers.equals(lastVers)) {
2553 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2554 intent.setComponent(new ComponentName(
2555 ri.activityInfo.packageName, ri.activityInfo.name));
2556 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2557 null, null, 0, 0, 0, false, false);
2558 }
2559 }
2560 }
2561 }
2562
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002563 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002564 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002565
2566 final int identHash = System.identityHashCode(r);
2567 updateUsageStats(r, true);
2568
2569 int i = mWatchers.beginBroadcast();
2570 while (i > 0) {
2571 i--;
2572 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2573 if (w != null) {
2574 try {
2575 w.activityResuming(identHash);
2576 } catch (RemoteException e) {
2577 }
2578 }
2579 }
2580 mWatchers.finishBroadcast();
2581 }
2582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 /**
2584 * Ensure that the top activity in the stack is resumed.
2585 *
2586 * @param prev The previously resumed activity, for when in the process
2587 * of pausing; can be null to call from elsewhere.
2588 *
2589 * @return Returns true if something is being resumed, or false if
2590 * nothing happened.
2591 */
2592 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2593 // Find the first activity that is not finishing.
2594 HistoryRecord next = topRunningActivityLocked(null);
2595
2596 // Remember how we'll process this pause/resume situation, and ensure
2597 // that the state is reset however we wind up proceeding.
2598 final boolean userLeaving = mUserLeaving;
2599 mUserLeaving = false;
2600
2601 if (next == null) {
2602 // There are no more activities! Let's just start up the
2603 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002604 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 }
2606
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002607 next.delayedResume = false;
2608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 // If the top activity is the resumed one, nothing to do.
2610 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2611 // Make sure we have executed any pending transitions, since there
2612 // should be nothing left to do at this point.
2613 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002614 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 return false;
2616 }
2617
2618 // If we are sleeping, and there is no resumed activity, and the top
2619 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002620 if ((mSleeping || mShuttingDown)
2621 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 // Make sure we have executed any pending transitions, since there
2623 // should be nothing left to do at this point.
2624 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002625 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 return false;
2627 }
2628
2629 // The activity may be waiting for stop, but that is no longer
2630 // appropriate for it.
2631 mStoppingActivities.remove(next);
2632 mWaitingVisibleActivities.remove(next);
2633
Joe Onorato8a9b2202010-02-26 18:56:32 -08002634 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635
2636 // If we are currently pausing an activity, then don't do anything
2637 // until that is done.
2638 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002639 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640 return false;
2641 }
2642
2643 // We need to start pausing the current activity so the top one
2644 // can be resumed...
2645 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002646 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002647 startPausingLocked(userLeaving, false);
2648 return true;
2649 }
2650
2651 if (prev != null && prev != next) {
2652 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2653 prev.waitingVisible = true;
2654 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002655 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002656 TAG, "Resuming top, waiting visible to hide: " + prev);
2657 } else {
2658 // The next activity is already visible, so hide the previous
2659 // activity's windows right now so we can show the new one ASAP.
2660 // We only do this if the previous is finishing, which should mean
2661 // it is on top of the one being resumed so hiding it quickly
2662 // is good. Otherwise, we want to do the normal route of allowing
2663 // the resumed activity to be shown so we can decide if the
2664 // previous should actually be hidden depending on whether the
2665 // new one is found to be full-screen or not.
2666 if (prev.finishing) {
2667 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002668 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002669 + prev + ", waitingVisible="
2670 + (prev != null ? prev.waitingVisible : null)
2671 + ", nowVisible=" + next.nowVisible);
2672 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002673 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting 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 }
2678 }
2679 }
2680
2681 // We are starting up the next activity, so tell the window manager
2682 // that the previous one will be hidden soon. This way it can know
2683 // to ignore it when computing the desired screen orientation.
2684 if (prev != null) {
2685 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002686 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002687 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002688 if (mNoAnimActivities.contains(prev)) {
2689 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2690 } else {
2691 mWindowManager.prepareAppTransition(prev.task == next.task
2692 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2693 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002695 mWindowManager.setAppWillBeHidden(prev);
2696 mWindowManager.setAppVisibility(prev, false);
2697 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002698 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002700 if (mNoAnimActivities.contains(next)) {
2701 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2702 } else {
2703 mWindowManager.prepareAppTransition(prev.task == next.task
2704 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2705 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002707 }
2708 if (false) {
2709 mWindowManager.setAppWillBeHidden(prev);
2710 mWindowManager.setAppVisibility(prev, false);
2711 }
2712 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002713 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002715 if (mNoAnimActivities.contains(next)) {
2716 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2717 } else {
2718 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720 }
2721
2722 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002723 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724
2725 // This activity is now becoming visible.
2726 mWindowManager.setAppVisibility(next, true);
2727
2728 HistoryRecord lastResumedActivity = mResumedActivity;
2729 ActivityState lastState = next.state;
2730
2731 updateCpuStats();
2732
2733 next.state = ActivityState.RESUMED;
2734 mResumedActivity = next;
2735 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002736 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 updateLRUListLocked(next);
2738
2739 // Have the window manager re-evaluate the orientation of
2740 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002741 boolean updated;
2742 synchronized (this) {
2743 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2744 mConfiguration,
2745 next.mayFreezeScreenLocked(next.app) ? next : null);
2746 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002747 next.frozenBeforeDestroy = true;
2748 }
2749 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002751 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 // The configuration update wasn't able to keep the existing
2753 // instance of the activity, and instead started a new one.
2754 // We should be all done, but let's just make sure our activity
2755 // is still at the top and schedule another run if something
2756 // weird happened.
2757 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002758 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002759 "Activity config changed during resume: " + next
2760 + ", new next: " + nextNext);
2761 if (nextNext != next) {
2762 // Do over!
2763 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2764 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002765 setFocusedActivityLocked(next);
2766 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002768 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002769 return true;
2770 }
2771
2772 try {
2773 // Deliver all pending results.
2774 ArrayList a = next.results;
2775 if (a != null) {
2776 final int N = a.size();
2777 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002778 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 TAG, "Delivering results to " + next
2780 + ": " + a);
2781 next.app.thread.scheduleSendResult(next, a);
2782 }
2783 }
2784
2785 if (next.newIntents != null) {
2786 next.app.thread.scheduleNewIntent(next.newIntents, next);
2787 }
2788
Doug Zongker2bec3d42009-12-04 12:52:44 -08002789 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 System.identityHashCode(next),
2791 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792
2793 next.app.thread.scheduleResumeActivity(next,
2794 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002796 pauseIfSleepingLocked();
2797
2798 } catch (Exception e) {
2799 // Whoops, need to restart this activity!
2800 next.state = lastState;
2801 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002802 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 if (!next.hasBeenLaunched) {
2804 next.hasBeenLaunched = true;
2805 } else {
2806 if (SHOW_APP_STARTING_ICON) {
2807 mWindowManager.setAppStartingWindow(
2808 next, next.packageName, next.theme,
2809 next.nonLocalizedLabel,
2810 next.labelRes, next.icon, null, true);
2811 }
2812 }
2813 startSpecificActivityLocked(next, true, false);
2814 return true;
2815 }
2816
2817 // From this point on, if something goes wrong there is no way
2818 // to recover the activity.
2819 try {
2820 next.visible = true;
2821 completeResumeLocked(next);
2822 } catch (Exception e) {
2823 // If any exception gets thrown, toss away this
2824 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002825 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2827 "resume-exception");
2828 return true;
2829 }
2830
2831 // Didn't need to use the icicle, and it is now out of date.
2832 next.icicle = null;
2833 next.haveState = false;
2834 next.stopped = false;
2835
2836 } else {
2837 // Whoops, need to restart this activity!
2838 if (!next.hasBeenLaunched) {
2839 next.hasBeenLaunched = true;
2840 } else {
2841 if (SHOW_APP_STARTING_ICON) {
2842 mWindowManager.setAppStartingWindow(
2843 next, next.packageName, next.theme,
2844 next.nonLocalizedLabel,
2845 next.labelRes, next.icon, null, true);
2846 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002847 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 }
2849 startSpecificActivityLocked(next, true, true);
2850 }
2851
2852 return true;
2853 }
2854
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002855 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2856 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002857 final int NH = mHistory.size();
2858
2859 int addPos = -1;
2860
2861 if (!newTask) {
2862 // If starting in an existing task, find where that is...
2863 HistoryRecord next = null;
2864 boolean startIt = true;
2865 for (int i = NH-1; i >= 0; i--) {
2866 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2867 if (p.finishing) {
2868 continue;
2869 }
2870 if (p.task == r.task) {
2871 // Here it is! Now, if this is not yet visible to the
2872 // user, then just add it without starting; it will
2873 // get started when the user navigates back to it.
2874 addPos = i+1;
2875 if (!startIt) {
2876 mHistory.add(addPos, r);
2877 r.inHistory = true;
2878 r.task.numActivities++;
2879 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2880 r.info.screenOrientation, r.fullscreen);
2881 if (VALIDATE_TOKENS) {
2882 mWindowManager.validateAppTokens(mHistory);
2883 }
2884 return;
2885 }
2886 break;
2887 }
2888 if (p.fullscreen) {
2889 startIt = false;
2890 }
2891 next = p;
2892 }
2893 }
2894
2895 // Place a new activity at top of stack, so it is next to interact
2896 // with the user.
2897 if (addPos < 0) {
2898 addPos = mHistory.size();
2899 }
2900
2901 // If we are not placing the new activity frontmost, we do not want
2902 // to deliver the onUserLeaving callback to the actual frontmost
2903 // activity
2904 if (addPos < NH) {
2905 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002906 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002907 }
2908
2909 // Slot the activity into the history stack and proceed
2910 mHistory.add(addPos, r);
2911 r.inHistory = true;
2912 r.frontOfTask = newTask;
2913 r.task.numActivities++;
2914 if (NH > 0) {
2915 // We want to show the starting preview window if we are
2916 // switching to a new task, or the next activity's process is
2917 // not currently running.
2918 boolean showStartingIcon = newTask;
2919 ProcessRecord proc = r.app;
2920 if (proc == null) {
2921 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2922 }
2923 if (proc == null || proc.thread == null) {
2924 showStartingIcon = true;
2925 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002926 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002927 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002928 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2929 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2930 mNoAnimActivities.add(r);
2931 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2932 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
2933 mNoAnimActivities.remove(r);
2934 } else {
2935 mWindowManager.prepareAppTransition(newTask
2936 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
2937 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2938 mNoAnimActivities.remove(r);
2939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 mWindowManager.addAppToken(
2941 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
2942 boolean doShow = true;
2943 if (newTask) {
2944 // Even though this activity is starting fresh, we still need
2945 // to reset it to make sure we apply affinities to move any
2946 // existing activities from other tasks in to it.
2947 // If the caller has requested that the target task be
2948 // reset, then do so.
2949 if ((r.intent.getFlags()
2950 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2951 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002952 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 }
2954 }
2955 if (SHOW_APP_STARTING_ICON && doShow) {
2956 // Figure out if we are transitioning from another activity that is
2957 // "has the same starting icon" as the next one. This allows the
2958 // window manager to keep the previous window it had previously
2959 // created, if it still had one.
2960 HistoryRecord prev = mResumedActivity;
2961 if (prev != null) {
2962 // We don't want to reuse the previous starting preview if:
2963 // (1) The current activity is in a different task.
2964 if (prev.task != r.task) prev = null;
2965 // (2) The current activity is already displayed.
2966 else if (prev.nowVisible) prev = null;
2967 }
2968 mWindowManager.setAppStartingWindow(
2969 r, r.packageName, r.theme, r.nonLocalizedLabel,
2970 r.labelRes, r.icon, prev, showStartingIcon);
2971 }
2972 } else {
2973 // If this is the first activity, don't do any fancy animations,
2974 // because there is nothing for it to animate on top of.
2975 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2976 r.info.screenOrientation, r.fullscreen);
2977 }
2978 if (VALIDATE_TOKENS) {
2979 mWindowManager.validateAppTokens(mHistory);
2980 }
2981
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002982 if (doResume) {
2983 resumeTopActivityLocked(null);
2984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 }
2986
2987 /**
2988 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002989 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2990 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 * an instance of that activity in the stack and, if found, finish all
2992 * activities on top of it and return the instance.
2993 *
2994 * @param newR Description of the new activity being started.
2995 * @return Returns the old activity that should be continue to be used,
2996 * or null if none was found.
2997 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002998 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07002999 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003000 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003001
3002 // First find the requested task.
3003 while (i > 0) {
3004 i--;
3005 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3006 if (r.task.taskId == taskId) {
3007 i++;
3008 break;
3009 }
3010 }
3011
3012 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003013 while (i > 0) {
3014 i--;
3015 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3016 if (r.finishing) {
3017 continue;
3018 }
3019 if (r.task.taskId != taskId) {
3020 return null;
3021 }
3022 if (r.realActivity.equals(newR.realActivity)) {
3023 // Here it is! Now finish everything in front...
3024 HistoryRecord ret = r;
3025 if (doClear) {
3026 while (i < (mHistory.size()-1)) {
3027 i++;
3028 r = (HistoryRecord)mHistory.get(i);
3029 if (r.finishing) {
3030 continue;
3031 }
3032 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3033 null, "clear")) {
3034 i--;
3035 }
3036 }
3037 }
3038
3039 // Finally, if this is a normal launch mode (that is, not
3040 // expecting onNewIntent()), then we will finish the current
3041 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003042 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3043 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003044 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003045 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003047 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 null, "clear");
3049 }
3050 return null;
3051 }
3052 }
3053
3054 return ret;
3055 }
3056 }
3057
3058 return null;
3059 }
3060
3061 /**
3062 * Find the activity in the history stack within the given task. Returns
3063 * the index within the history at which it's found, or < 0 if not found.
3064 */
3065 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3066 int i = mHistory.size();
3067 while (i > 0) {
3068 i--;
3069 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3070 if (candidate.task.taskId != task) {
3071 break;
3072 }
3073 if (candidate.realActivity.equals(r.realActivity)) {
3074 return i;
3075 }
3076 }
3077
3078 return -1;
3079 }
3080
3081 /**
3082 * Reorder the history stack so that the activity at the given index is
3083 * brought to the front.
3084 */
3085 private final HistoryRecord moveActivityToFrontLocked(int where) {
3086 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3087 int top = mHistory.size();
3088 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3089 mHistory.add(top, newTop);
3090 oldTop.frontOfTask = false;
3091 newTop.frontOfTask = true;
3092 return newTop;
3093 }
3094
3095 /**
3096 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3097 * method will be called at the proper time.
3098 */
3099 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3100 boolean sent = false;
3101 if (r.state == ActivityState.RESUMED
3102 && r.app != null && r.app.thread != null) {
3103 try {
3104 ArrayList<Intent> ar = new ArrayList<Intent>();
3105 ar.add(new Intent(intent));
3106 r.app.thread.scheduleNewIntent(ar, r);
3107 sent = true;
3108 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003109 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 }
3111 }
3112 if (!sent) {
3113 r.addNewIntentLocked(new Intent(intent));
3114 }
3115 }
3116
3117 private final void logStartActivity(int tag, HistoryRecord r,
3118 TaskRecord task) {
3119 EventLog.writeEvent(tag,
3120 System.identityHashCode(r), task.taskId,
3121 r.shortComponentName, r.intent.getAction(),
3122 r.intent.getType(), r.intent.getDataString(),
3123 r.intent.getFlags());
3124 }
3125
3126 private final int startActivityLocked(IApplicationThread caller,
3127 Intent intent, String resolvedType,
3128 Uri[] grantedUriPermissions,
3129 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3130 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003131 int callingPid, int callingUid, boolean onlyIfNeeded,
3132 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003133 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134
3135 HistoryRecord sourceRecord = null;
3136 HistoryRecord resultRecord = null;
3137 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003138 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003139 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3141 if (index >= 0) {
3142 sourceRecord = (HistoryRecord)mHistory.get(index);
3143 if (requestCode >= 0 && !sourceRecord.finishing) {
3144 resultRecord = sourceRecord;
3145 }
3146 }
3147 }
3148
3149 int launchFlags = intent.getFlags();
3150
3151 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3152 && sourceRecord != null) {
3153 // Transfer the result target from the source activity to the new
3154 // one being started, including any failures.
3155 if (requestCode >= 0) {
3156 return START_FORWARD_AND_REQUEST_CONFLICT;
3157 }
3158 resultRecord = sourceRecord.resultTo;
3159 resultWho = sourceRecord.resultWho;
3160 requestCode = sourceRecord.requestCode;
3161 sourceRecord.resultTo = null;
3162 if (resultRecord != null) {
3163 resultRecord.removeResultsLocked(
3164 sourceRecord, resultWho, requestCode);
3165 }
3166 }
3167
3168 int err = START_SUCCESS;
3169
3170 if (intent.getComponent() == null) {
3171 // We couldn't find a class that can handle the given Intent.
3172 // That's the end of that!
3173 err = START_INTENT_NOT_RESOLVED;
3174 }
3175
3176 if (err == START_SUCCESS && aInfo == null) {
3177 // We couldn't find the specific class specified in the Intent.
3178 // Also the end of the line.
3179 err = START_CLASS_NOT_FOUND;
3180 }
3181
3182 ProcessRecord callerApp = null;
3183 if (err == START_SUCCESS && caller != null) {
3184 callerApp = getRecordForAppLocked(caller);
3185 if (callerApp != null) {
3186 callingPid = callerApp.pid;
3187 callingUid = callerApp.info.uid;
3188 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003189 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003190 + " (pid=" + callingPid + ") when starting: "
3191 + intent.toString());
3192 err = START_PERMISSION_DENIED;
3193 }
3194 }
3195
3196 if (err != START_SUCCESS) {
3197 if (resultRecord != null) {
3198 sendActivityResultLocked(-1,
3199 resultRecord, resultWho, requestCode,
3200 Activity.RESULT_CANCELED, null);
3201 }
3202 return err;
3203 }
3204
3205 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3206 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3207 if (perm != PackageManager.PERMISSION_GRANTED) {
3208 if (resultRecord != null) {
3209 sendActivityResultLocked(-1,
3210 resultRecord, resultWho, requestCode,
3211 Activity.RESULT_CANCELED, null);
3212 }
3213 String msg = "Permission Denial: starting " + intent.toString()
3214 + " from " + callerApp + " (pid=" + callingPid
3215 + ", uid=" + callingUid + ")"
3216 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003217 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 throw new SecurityException(msg);
3219 }
3220
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003221 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 boolean abort = false;
3223 try {
3224 // The Intent we give to the watcher has the extra data
3225 // stripped off, since it can contain private information.
3226 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003227 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003228 aInfo.applicationInfo.packageName);
3229 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003230 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231 }
3232
3233 if (abort) {
3234 if (resultRecord != null) {
3235 sendActivityResultLocked(-1,
3236 resultRecord, resultWho, requestCode,
3237 Activity.RESULT_CANCELED, null);
3238 }
3239 // We pretend to the caller that it was really started, but
3240 // they will just get a cancel result.
3241 return START_SUCCESS;
3242 }
3243 }
3244
3245 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3246 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003247 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003249 if (mResumedActivity == null
3250 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3251 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3252 PendingActivityLaunch pal = new PendingActivityLaunch();
3253 pal.r = r;
3254 pal.sourceRecord = sourceRecord;
3255 pal.grantedUriPermissions = grantedUriPermissions;
3256 pal.grantedMode = grantedMode;
3257 pal.onlyIfNeeded = onlyIfNeeded;
3258 mPendingActivityLaunches.add(pal);
3259 return START_SWITCHES_CANCELED;
3260 }
3261 }
3262
3263 if (mDidAppSwitch) {
3264 // This is the second allowed switch since we stopped switches,
3265 // so now just generally allow switches. Use case: user presses
3266 // home (switches disabled, switch to home, mDidAppSwitch now true);
3267 // user taps a home icon (coming from home so allowed, we hit here
3268 // and now allow anyone to switch again).
3269 mAppSwitchesAllowedTime = 0;
3270 } else {
3271 mDidAppSwitch = true;
3272 }
3273
3274 doPendingActivityLaunchesLocked(false);
3275
3276 return startActivityUncheckedLocked(r, sourceRecord,
3277 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3278 }
3279
3280 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3281 final int N = mPendingActivityLaunches.size();
3282 if (N <= 0) {
3283 return;
3284 }
3285 for (int i=0; i<N; i++) {
3286 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3287 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3288 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3289 doResume && i == (N-1));
3290 }
3291 mPendingActivityLaunches.clear();
3292 }
3293
3294 private final int startActivityUncheckedLocked(HistoryRecord r,
3295 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3296 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3297 final Intent intent = r.intent;
3298 final int callingUid = r.launchedFromUid;
3299
3300 int launchFlags = intent.getFlags();
3301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003302 // We'll invoke onUserLeaving before onPause only if the launching
3303 // activity did not explicitly state that this is an automated launch.
3304 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003305 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 "startActivity() => mUserLeaving=" + mUserLeaving);
3307
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003308 // If the caller has asked not to resume at this point, we make note
3309 // of this in the record so that we can skip it when trying to find
3310 // the top running activity.
3311 if (!doResume) {
3312 r.delayedResume = true;
3313 }
3314
3315 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3316 != 0 ? r : null;
3317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003318 // If the onlyIfNeeded flag is set, then we can do this if the activity
3319 // being launched is the same as the one making the call... or, as
3320 // a special case, if we do not know the caller then we count the
3321 // current top activity as the caller.
3322 if (onlyIfNeeded) {
3323 HistoryRecord checkedCaller = sourceRecord;
3324 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003325 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003326 }
3327 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3328 // Caller is not the same as launcher, so always needed.
3329 onlyIfNeeded = false;
3330 }
3331 }
3332
3333 if (grantedUriPermissions != null && callingUid > 0) {
3334 for (int i=0; i<grantedUriPermissions.length; i++) {
3335 grantUriPermissionLocked(callingUid, r.packageName,
3336 grantedUriPermissions[i], grantedMode, r);
3337 }
3338 }
3339
3340 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3341 intent, r);
3342
3343 if (sourceRecord == null) {
3344 // This activity is not being started from another... in this
3345 // case we -always- start a new task.
3346 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003347 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 -08003348 + intent);
3349 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3350 }
3351 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3352 // The original activity who is starting us is running as a single
3353 // instance... this new activity it is starting must go on its
3354 // own task.
3355 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3356 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3357 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3358 // The activity being started is a single instance... it always
3359 // gets launched into its own task.
3360 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3361 }
3362
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003363 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364 // For whatever reason this activity is being launched into a new
3365 // task... yet the caller has requested a result back. Well, that
3366 // is pretty messed up, so instead immediately send back a cancel
3367 // and let the new task continue launched as normal without a
3368 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003369 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003371 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003372 Activity.RESULT_CANCELED, null);
3373 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 }
3375
3376 boolean addingToTask = false;
3377 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3378 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3379 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3380 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3381 // If bring to front is requested, and no result is requested, and
3382 // we can find a task that was started with this same
3383 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003384 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 // See if there is a task to bring to the front. If this is
3386 // a SINGLE_INSTANCE activity, there can be one and only one
3387 // instance of it in the history, and it is always in its own
3388 // unique task, so we do a special search.
3389 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3390 ? findTaskLocked(intent, r.info)
3391 : findActivityLocked(intent, r.info);
3392 if (taskTop != null) {
3393 if (taskTop.task.intent == null) {
3394 // This task was started because of movement of
3395 // the activity based on affinity... now that we
3396 // are actually launching it, we can assign the
3397 // base intent.
3398 taskTop.task.setIntent(intent, r.info);
3399 }
3400 // If the target task is not in the front, then we need
3401 // to bring it to the front... except... well, with
3402 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3403 // to have the same behavior as if a new instance was
3404 // being started, which means not bringing it to the front
3405 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003406 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003407 if (curTop.task != taskTop.task) {
3408 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3409 boolean callerAtFront = sourceRecord == null
3410 || curTop.task == sourceRecord.task;
3411 if (callerAtFront) {
3412 // We really do want to push this one into the
3413 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003414 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003415 }
3416 }
3417 // If the caller has requested that the target task be
3418 // reset, then do so.
3419 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3420 taskTop = resetTaskIfNeededLocked(taskTop, r);
3421 }
3422 if (onlyIfNeeded) {
3423 // We don't need to start a new activity, and
3424 // the client said not to do anything if that
3425 // is the case, so this is it! And for paranoia, make
3426 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003427 if (doResume) {
3428 resumeTopActivityLocked(null);
3429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 return START_RETURN_INTENT_TO_CALLER;
3431 }
3432 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3433 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3434 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3435 // In this situation we want to remove all activities
3436 // from the task up to the one being started. In most
3437 // cases this means we are resetting the task to its
3438 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003439 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003440 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 if (top != null) {
3442 if (top.frontOfTask) {
3443 // Activity aliases may mean we use different
3444 // intents for the top activity, so make sure
3445 // the task now has the identity of the new
3446 // intent.
3447 top.task.setIntent(r.intent, r.info);
3448 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003449 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 deliverNewIntentLocked(top, r.intent);
3451 } else {
3452 // A special case: we need to
3453 // start the activity because it is not currently
3454 // running, and the caller has asked to clear the
3455 // current task to have this activity at the top.
3456 addingToTask = true;
3457 // Now pretend like this activity is being started
3458 // by the top of its task, so it is put in the
3459 // right place.
3460 sourceRecord = taskTop;
3461 }
3462 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3463 // In this case the top activity on the task is the
3464 // same as the one being launched, so we take that
3465 // as a request to bring the task to the foreground.
3466 // If the top activity in the task is the root
3467 // activity, deliver this new intent to it if it
3468 // desires.
3469 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3470 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003471 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 if (taskTop.frontOfTask) {
3473 taskTop.task.setIntent(r.intent, r.info);
3474 }
3475 deliverNewIntentLocked(taskTop, r.intent);
3476 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3477 // In this case we are launching the root activity
3478 // of the task, but with a different intent. We
3479 // should start a new instance on top.
3480 addingToTask = true;
3481 sourceRecord = taskTop;
3482 }
3483 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3484 // In this case an activity is being launched in to an
3485 // existing task, without resetting that task. This
3486 // is typically the situation of launching an activity
3487 // from a notification or shortcut. We want to place
3488 // the new activity on top of the current task.
3489 addingToTask = true;
3490 sourceRecord = taskTop;
3491 } else if (!taskTop.task.rootWasReset) {
3492 // In this case we are launching in to an existing task
3493 // that has not yet been started from its front door.
3494 // The current task has been brought to the front.
3495 // Ideally, we'd probably like to place this new task
3496 // at the bottom of its stack, but that's a little hard
3497 // to do with the current organization of the code so
3498 // for now we'll just drop it.
3499 taskTop.task.setIntent(r.intent, r.info);
3500 }
3501 if (!addingToTask) {
3502 // We didn't do anything... but it was needed (a.k.a., client
3503 // don't use that intent!) And for paranoia, make
3504 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003505 if (doResume) {
3506 resumeTopActivityLocked(null);
3507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003508 return START_TASK_TO_FRONT;
3509 }
3510 }
3511 }
3512 }
3513
3514 //String uri = r.intent.toURI();
3515 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003516 //Slog.i(TAG, "Given intent: " + r.intent);
3517 //Slog.i(TAG, "URI is: " + uri);
3518 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519
3520 if (r.packageName != null) {
3521 // If the activity being launched is the same as the one currently
3522 // at the top, then we need to check if it should only be launched
3523 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003524 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3525 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 if (top.realActivity.equals(r.realActivity)) {
3527 if (top.app != null && top.app.thread != null) {
3528 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3529 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3530 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003531 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003532 // For paranoia, make sure we have correctly
3533 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003534 if (doResume) {
3535 resumeTopActivityLocked(null);
3536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 if (onlyIfNeeded) {
3538 // We don't need to start a new activity, and
3539 // the client said not to do anything if that
3540 // is the case, so this is it!
3541 return START_RETURN_INTENT_TO_CALLER;
3542 }
3543 deliverNewIntentLocked(top, r.intent);
3544 return START_DELIVERED_TO_TOP;
3545 }
3546 }
3547 }
3548 }
3549
3550 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003551 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003553 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003554 Activity.RESULT_CANCELED, null);
3555 }
3556 return START_CLASS_NOT_FOUND;
3557 }
3558
3559 boolean newTask = false;
3560
3561 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003562 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3564 // todo: should do better management of integers.
3565 mCurTask++;
3566 if (mCurTask <= 0) {
3567 mCurTask = 1;
3568 }
3569 r.task = new TaskRecord(mCurTask, r.info, intent,
3570 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003571 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 + " in new task " + r.task);
3573 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003574 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003575
3576 } else if (sourceRecord != null) {
3577 if (!addingToTask &&
3578 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3579 // In this case, we are adding the activity to an existing
3580 // task, but the caller has asked to clear that task if the
3581 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003582 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003583 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003584 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003585 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 deliverNewIntentLocked(top, r.intent);
3587 // For paranoia, make sure we have correctly
3588 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003589 if (doResume) {
3590 resumeTopActivityLocked(null);
3591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003592 return START_DELIVERED_TO_TOP;
3593 }
3594 } else if (!addingToTask &&
3595 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3596 // In this case, we are launching an activity in our own task
3597 // that may already be running somewhere in the history, and
3598 // we want to shuffle it to the front of the stack if so.
3599 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3600 if (where >= 0) {
3601 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003602 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003604 if (doResume) {
3605 resumeTopActivityLocked(null);
3606 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 return START_DELIVERED_TO_TOP;
3608 }
3609 }
3610 // An existing activity is starting this new activity, so we want
3611 // to keep the new one in the same task as the one that is starting
3612 // it.
3613 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003614 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 + " in existing task " + r.task);
3616
3617 } else {
3618 // This not being started from an existing activity, and not part
3619 // of a new task... just put it in the top task, though these days
3620 // this case should never happen.
3621 final int N = mHistory.size();
3622 HistoryRecord prev =
3623 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3624 r.task = prev != null
3625 ? prev.task
3626 : new TaskRecord(mCurTask, r.info, intent,
3627 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003628 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 + " in new guessed " + r.task);
3630 }
3631 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003632 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003634 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003635 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 return START_SUCCESS;
3637 }
3638
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003639 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3640 long thisTime, long totalTime) {
3641 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3642 WaitResult w = mWaitingActivityLaunched.get(i);
3643 w.timeout = timeout;
3644 if (r != null) {
3645 w.who = new ComponentName(r.info.packageName, r.info.name);
3646 }
3647 w.thisTime = thisTime;
3648 w.totalTime = totalTime;
3649 }
3650 notify();
3651 }
3652
3653 void reportActivityVisibleLocked(HistoryRecord r) {
3654 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3655 WaitResult w = mWaitingActivityVisible.get(i);
3656 w.timeout = false;
3657 if (r != null) {
3658 w.who = new ComponentName(r.info.packageName, r.info.name);
3659 }
3660 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3661 w.thisTime = w.totalTime;
3662 }
3663 notify();
3664 }
3665
3666 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3668 int grantedMode, IBinder resultTo,
3669 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003670 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 // Refuse possible leaked file descriptors
3672 if (intent != null && intent.hasFileDescriptors()) {
3673 throw new IllegalArgumentException("File descriptors passed in Intent");
3674 }
3675
The Android Open Source Project4df24232009-03-05 14:34:35 -08003676 final boolean componentSpecified = intent.getComponent() != null;
3677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003678 // Don't modify the client's object!
3679 intent = new Intent(intent);
3680
3681 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 ActivityInfo aInfo;
3683 try {
3684 ResolveInfo rInfo =
3685 ActivityThread.getPackageManager().resolveIntent(
3686 intent, resolvedType,
3687 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003688 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 aInfo = rInfo != null ? rInfo.activityInfo : null;
3690 } catch (RemoteException e) {
3691 aInfo = null;
3692 }
3693
3694 if (aInfo != null) {
3695 // Store the found target back into the intent, because now that
3696 // we have it we never want to do this again. For example, if the
3697 // user navigates back to this point in the history, we should
3698 // always restart the exact same activity.
3699 intent.setComponent(new ComponentName(
3700 aInfo.applicationInfo.packageName, aInfo.name));
3701
3702 // Don't debug things in the system process
3703 if (debug) {
3704 if (!aInfo.processName.equals("system")) {
3705 setDebugApp(aInfo.processName, true, false);
3706 }
3707 }
3708 }
3709
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003710 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003711 int callingPid;
3712 int callingUid;
3713 if (caller == null) {
3714 callingPid = Binder.getCallingPid();
3715 callingUid = Binder.getCallingUid();
3716 } else {
3717 callingPid = callingUid = -1;
3718 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003719
3720 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003721 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3722 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003726 int res = startActivityLocked(caller, intent, resolvedType,
3727 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003728 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003729 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003730
Dianne Hackborne2522462010-03-29 18:41:30 -07003731 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003732 // If the caller also wants to switch to a new configuration,
3733 // do so now. This allows a clean switch, as we are waiting
3734 // for the current activity to pause (so we will not destroy
3735 // it), and have not yet started the next activity.
3736 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3737 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003738 mConfigWillChange = false;
3739 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3740 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003741 updateConfigurationLocked(config, null);
3742 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003744 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003745
3746 if (outResult != null) {
3747 outResult.result = res;
3748 if (res == IActivityManager.START_SUCCESS) {
3749 mWaitingActivityLaunched.add(outResult);
3750 do {
3751 try {
3752 wait();
3753 } catch (InterruptedException e) {
3754 }
3755 } while (!outResult.timeout && outResult.who == null);
3756 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3757 HistoryRecord r = this.topRunningActivityLocked(null);
3758 if (r.nowVisible) {
3759 outResult.timeout = false;
3760 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3761 outResult.totalTime = 0;
3762 outResult.thisTime = 0;
3763 } else {
3764 outResult.thisTime = SystemClock.uptimeMillis();
3765 mWaitingActivityVisible.add(outResult);
3766 do {
3767 try {
3768 wait();
3769 } catch (InterruptedException e) {
3770 }
3771 } while (!outResult.timeout && outResult.who == null);
3772 }
3773 }
3774 }
3775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 return res;
3777 }
3778 }
3779
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003780 public final int startActivity(IApplicationThread caller,
3781 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3782 int grantedMode, IBinder resultTo,
3783 String resultWho, int requestCode, boolean onlyIfNeeded,
3784 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003785 return startActivityMayWait(caller, intent, resolvedType,
3786 grantedUriPermissions, grantedMode, resultTo, resultWho,
3787 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003788 }
3789
3790 public final WaitResult startActivityAndWait(IApplicationThread caller,
3791 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3792 int grantedMode, IBinder resultTo,
3793 String resultWho, int requestCode, boolean onlyIfNeeded,
3794 boolean debug) {
3795 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003796 startActivityMayWait(caller, intent, resolvedType,
3797 grantedUriPermissions, grantedMode, resultTo, resultWho,
3798 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003799 return res;
3800 }
3801
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003802 public final int startActivityWithConfig(IApplicationThread caller,
3803 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3804 int grantedMode, IBinder resultTo,
3805 String resultWho, int requestCode, boolean onlyIfNeeded,
3806 boolean debug, Configuration config) {
3807 return startActivityMayWait(caller, intent, resolvedType,
3808 grantedUriPermissions, grantedMode, resultTo, resultWho,
3809 requestCode, onlyIfNeeded, debug, null, config);
3810 }
3811
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003812 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003813 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003814 IBinder resultTo, String resultWho, int requestCode,
3815 int flagsMask, int flagsValues) {
3816 // Refuse possible leaked file descriptors
3817 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3818 throw new IllegalArgumentException("File descriptors passed in Intent");
3819 }
3820
3821 IIntentSender sender = intent.getTarget();
3822 if (!(sender instanceof PendingIntentRecord)) {
3823 throw new IllegalArgumentException("Bad PendingIntent object");
3824 }
3825
3826 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003827
3828 synchronized (this) {
3829 // If this is coming from the currently resumed activity, it is
3830 // effectively saying that app switches are allowed at this point.
3831 if (mResumedActivity != null
3832 && mResumedActivity.info.applicationInfo.uid ==
3833 Binder.getCallingUid()) {
3834 mAppSwitchesAllowedTime = 0;
3835 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003836 }
3837
3838 return pir.sendInner(0, fillInIntent, resolvedType,
3839 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
3840 }
3841
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003842 public boolean startNextMatchingActivity(IBinder callingActivity,
3843 Intent intent) {
3844 // Refuse possible leaked file descriptors
3845 if (intent != null && intent.hasFileDescriptors() == true) {
3846 throw new IllegalArgumentException("File descriptors passed in Intent");
3847 }
3848
3849 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003850 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003851 if (index < 0) {
3852 return false;
3853 }
3854 HistoryRecord r = (HistoryRecord)mHistory.get(index);
3855 if (r.app == null || r.app.thread == null) {
3856 // The caller is not running... d'oh!
3857 return false;
3858 }
3859 intent = new Intent(intent);
3860 // The caller is not allowed to change the data.
3861 intent.setDataAndType(r.intent.getData(), r.intent.getType());
3862 // And we are resetting to find the next component...
3863 intent.setComponent(null);
3864
3865 ActivityInfo aInfo = null;
3866 try {
3867 List<ResolveInfo> resolves =
3868 ActivityThread.getPackageManager().queryIntentActivities(
3869 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003870 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003871
3872 // Look for the original activity in the list...
3873 final int N = resolves != null ? resolves.size() : 0;
3874 for (int i=0; i<N; i++) {
3875 ResolveInfo rInfo = resolves.get(i);
3876 if (rInfo.activityInfo.packageName.equals(r.packageName)
3877 && rInfo.activityInfo.name.equals(r.info.name)) {
3878 // We found the current one... the next matching is
3879 // after it.
3880 i++;
3881 if (i<N) {
3882 aInfo = resolves.get(i).activityInfo;
3883 }
3884 break;
3885 }
3886 }
3887 } catch (RemoteException e) {
3888 }
3889
3890 if (aInfo == null) {
3891 // Nobody who is next!
3892 return false;
3893 }
3894
3895 intent.setComponent(new ComponentName(
3896 aInfo.applicationInfo.packageName, aInfo.name));
3897 intent.setFlags(intent.getFlags()&~(
3898 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
3899 Intent.FLAG_ACTIVITY_CLEAR_TOP|
3900 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
3901 Intent.FLAG_ACTIVITY_NEW_TASK));
3902
3903 // Okay now we need to start the new activity, replacing the
3904 // currently running activity. This is a little tricky because
3905 // we want to start the new one as if the current one is finished,
3906 // but not finish the current one first so that there is no flicker.
3907 // And thus...
3908 final boolean wasFinishing = r.finishing;
3909 r.finishing = true;
3910
3911 // Propagate reply information over to the new activity.
3912 final HistoryRecord resultTo = r.resultTo;
3913 final String resultWho = r.resultWho;
3914 final int requestCode = r.requestCode;
3915 r.resultTo = null;
3916 if (resultTo != null) {
3917 resultTo.removeResultsLocked(r, resultWho, requestCode);
3918 }
3919
3920 final long origId = Binder.clearCallingIdentity();
3921 // XXX we are not dealing with propagating grantedUriPermissions...
3922 // those are not yet exposed to user code, so there is no need.
3923 int res = startActivityLocked(r.app.thread, intent,
3924 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003925 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 Binder.restoreCallingIdentity(origId);
3927
3928 r.finishing = wasFinishing;
3929 if (res != START_SUCCESS) {
3930 return false;
3931 }
3932 return true;
3933 }
3934 }
3935
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003936 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 Intent intent, String resolvedType, IBinder resultTo,
3938 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07003939
3940 // This is so super not safe, that only the system (or okay root)
3941 // can do it.
3942 final int callingUid = Binder.getCallingUid();
3943 if (callingUid != 0 && callingUid != Process.myUid()) {
3944 throw new SecurityException(
3945 "startActivityInPackage only available to the system");
3946 }
3947
The Android Open Source Project4df24232009-03-05 14:34:35 -08003948 final boolean componentSpecified = intent.getComponent() != null;
3949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 // Don't modify the client's object!
3951 intent = new Intent(intent);
3952
3953 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003954 ActivityInfo aInfo;
3955 try {
3956 ResolveInfo rInfo =
3957 ActivityThread.getPackageManager().resolveIntent(
3958 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07003959 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 aInfo = rInfo != null ? rInfo.activityInfo : null;
3961 } catch (RemoteException e) {
3962 aInfo = null;
3963 }
3964
3965 if (aInfo != null) {
3966 // Store the found target back into the intent, because now that
3967 // we have it we never want to do this again. For example, if the
3968 // user navigates back to this point in the history, we should
3969 // always restart the exact same activity.
3970 intent.setComponent(new ComponentName(
3971 aInfo.applicationInfo.packageName, aInfo.name));
3972 }
3973
3974 synchronized(this) {
3975 return startActivityLocked(null, intent, resolvedType,
3976 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003977 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003978 }
3979 }
3980
Josh Bartel7f208742010-02-25 11:01:44 -06003981 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003982 // Remove any existing entries that are the same kind of task.
3983 int N = mRecentTasks.size();
3984 for (int i=0; i<N; i++) {
3985 TaskRecord tr = mRecentTasks.get(i);
3986 if ((task.affinity != null && task.affinity.equals(tr.affinity))
3987 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
3988 mRecentTasks.remove(i);
3989 i--;
3990 N--;
3991 if (task.intent == null) {
3992 // If the new recent task we are adding is not fully
3993 // specified, then replace it with the existing recent task.
3994 task = tr;
3995 }
3996 }
3997 }
3998 if (N >= MAX_RECENT_TASKS) {
3999 mRecentTasks.remove(N-1);
4000 }
4001 mRecentTasks.add(0, task);
4002 }
4003
4004 public void setRequestedOrientation(IBinder token,
4005 int requestedOrientation) {
4006 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004007 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004008 if (index < 0) {
4009 return;
4010 }
4011 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4012 final long origId = Binder.clearCallingIdentity();
4013 mWindowManager.setAppOrientation(r, requestedOrientation);
4014 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07004015 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004016 r.mayFreezeScreenLocked(r.app) ? r : null);
4017 if (config != null) {
4018 r.frozenBeforeDestroy = true;
4019 if (!updateConfigurationLocked(config, r)) {
4020 resumeTopActivityLocked(null);
4021 }
4022 }
4023 Binder.restoreCallingIdentity(origId);
4024 }
4025 }
4026
4027 public int getRequestedOrientation(IBinder token) {
4028 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004029 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 if (index < 0) {
4031 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4032 }
4033 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4034 return mWindowManager.getAppOrientation(r);
4035 }
4036 }
4037
4038 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004039 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004040 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4041 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4042 if (!r.finishing) {
4043 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4044 "no-history");
4045 }
4046 } else if (r.app != null && r.app.thread != null) {
4047 if (mFocusedActivity == r) {
4048 setFocusedActivityLocked(topRunningActivityLocked(null));
4049 }
4050 r.resumeKeyDispatchingLocked();
4051 try {
4052 r.stopped = false;
4053 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004054 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055 TAG, "Stopping visible=" + r.visible + " for " + r);
4056 if (!r.visible) {
4057 mWindowManager.setAppVisibility(r, false);
4058 }
4059 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4060 } catch (Exception e) {
4061 // Maybe just ignore exceptions here... if the process
4062 // has crashed, our death notification will clean things
4063 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004064 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004065 // Just in case, assume it to be stopped.
4066 r.stopped = true;
4067 r.state = ActivityState.STOPPED;
4068 if (r.configDestroy) {
4069 destroyActivityLocked(r, true);
4070 }
4071 }
4072 }
4073 }
4074
4075 /**
4076 * @return Returns true if the activity is being finished, false if for
4077 * some reason it is being left as-is.
4078 */
4079 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4080 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004081 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004082 TAG, "Finishing activity: token=" + token
4083 + ", result=" + resultCode + ", data=" + resultData);
4084
Dianne Hackborn75b03852009-06-12 15:43:26 -07004085 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086 if (index < 0) {
4087 return false;
4088 }
4089 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4090
4091 // Is this the last activity left?
4092 boolean lastActivity = true;
4093 for (int i=mHistory.size()-1; i>=0; i--) {
4094 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4095 if (!p.finishing && p != r) {
4096 lastActivity = false;
4097 break;
4098 }
4099 }
4100
4101 // If this is the last activity, but it is the home activity, then
4102 // just don't finish it.
4103 if (lastActivity) {
4104 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4105 return false;
4106 }
4107 }
4108
4109 finishActivityLocked(r, index, resultCode, resultData, reason);
4110 return true;
4111 }
4112
4113 /**
4114 * @return Returns true if this activity has been removed from the history
4115 * list, or false if it is still in the list and will be removed later.
4116 */
4117 private final boolean finishActivityLocked(HistoryRecord r, int index,
4118 int resultCode, Intent resultData, String reason) {
4119 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004120 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 return false;
4122 }
4123
4124 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004125 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004126 System.identityHashCode(r),
4127 r.task.taskId, r.shortComponentName, reason);
4128 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004129 if (index < (mHistory.size()-1)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4131 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004132 if (r.frontOfTask) {
4133 // The next activity is now the front of the task.
4134 next.frontOfTask = true;
4135 }
4136 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4137 // If the caller asked that this activity (and all above it)
4138 // be cleared when the task is reset, don't lose that information,
4139 // but propagate it up to the next activity.
4140 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004142 }
4143 }
4144
4145 r.pauseKeyDispatchingLocked();
4146 if (mFocusedActivity == r) {
4147 setFocusedActivityLocked(topRunningActivityLocked(null));
4148 }
4149
4150 // send the result
4151 HistoryRecord resultTo = r.resultTo;
4152 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004153 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004154 + " who=" + r.resultWho + " req=" + r.requestCode
4155 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004156 if (r.info.applicationInfo.uid > 0) {
4157 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4158 r.packageName, resultData, r);
4159 }
4160 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4161 resultData);
4162 r.resultTo = null;
4163 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004164 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004165
4166 // Make sure this HistoryRecord is not holding on to other resources,
4167 // because clients have remote IPC references to this object so we
4168 // can't assume that will go away and want to avoid circular IPC refs.
4169 r.results = null;
4170 r.pendingResults = null;
4171 r.newIntents = null;
4172 r.icicle = null;
4173
4174 if (mPendingThumbnails.size() > 0) {
4175 // There are clients waiting to receive thumbnails so, in case
4176 // this is an activity that someone is waiting for, add it
4177 // to the pending list so we can correctly update the clients.
4178 mCancelledThumbnails.add(r);
4179 }
4180
4181 if (mResumedActivity == r) {
4182 boolean endTask = index <= 0
4183 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004184 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 "Prepare close transition: finishing " + r);
4186 mWindowManager.prepareAppTransition(endTask
4187 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4188 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4189
4190 // Tell window manager to prepare for this one to be removed.
4191 mWindowManager.setAppVisibility(r, false);
4192
4193 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004194 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4195 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196 startPausingLocked(false, false);
4197 }
4198
4199 } else if (r.state != ActivityState.PAUSING) {
4200 // If the activity is PAUSING, we will complete the finish once
4201 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004202 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004203 return finishCurrentActivityLocked(r, index,
4204 FINISH_AFTER_PAUSE) == null;
4205 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004206 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004207 }
4208
4209 return false;
4210 }
4211
4212 private static final int FINISH_IMMEDIATELY = 0;
4213 private static final int FINISH_AFTER_PAUSE = 1;
4214 private static final int FINISH_AFTER_VISIBLE = 2;
4215
4216 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4217 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004218 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004219 if (index < 0) {
4220 return null;
4221 }
4222
4223 return finishCurrentActivityLocked(r, index, mode);
4224 }
4225
4226 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4227 int index, int mode) {
4228 // First things first: if this activity is currently visible,
4229 // and the resumed activity is not yet visible, then hold off on
4230 // finishing until the resumed one becomes visible.
4231 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4232 if (!mStoppingActivities.contains(r)) {
4233 mStoppingActivities.add(r);
4234 if (mStoppingActivities.size() > 3) {
4235 // If we already have a few activities waiting to stop,
4236 // then give up on things going idle and start clearing
4237 // them out.
4238 Message msg = Message.obtain();
4239 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4240 mHandler.sendMessage(msg);
4241 }
4242 }
4243 r.state = ActivityState.STOPPING;
4244 updateOomAdjLocked();
4245 return r;
4246 }
4247
4248 // make sure the record is cleaned out of other places.
4249 mStoppingActivities.remove(r);
4250 mWaitingVisibleActivities.remove(r);
4251 if (mResumedActivity == r) {
4252 mResumedActivity = null;
4253 }
4254 final ActivityState prevState = r.state;
4255 r.state = ActivityState.FINISHING;
4256
4257 if (mode == FINISH_IMMEDIATELY
4258 || prevState == ActivityState.STOPPED
4259 || prevState == ActivityState.INITIALIZING) {
4260 // If this activity is already stopped, we can just finish
4261 // it right now.
4262 return destroyActivityLocked(r, true) ? null : r;
4263 } else {
4264 // Need to go through the full pause cycle to get this
4265 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004266 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 mFinishingActivities.add(r);
4268 resumeTopActivityLocked(null);
4269 }
4270 return r;
4271 }
4272
4273 /**
4274 * This is the internal entry point for handling Activity.finish().
4275 *
4276 * @param token The Binder token referencing the Activity we want to finish.
4277 * @param resultCode Result code, if any, from this Activity.
4278 * @param resultData Result data (Intent), if any, from this Activity.
4279 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004280 * @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 -08004281 */
4282 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4283 // Refuse possible leaked file descriptors
4284 if (resultData != null && resultData.hasFileDescriptors() == true) {
4285 throw new IllegalArgumentException("File descriptors passed in Intent");
4286 }
4287
4288 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004289 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 // Find the first activity that is not finishing.
4291 HistoryRecord next = topRunningActivityLocked(token, 0);
4292 if (next != null) {
4293 // ask watcher if this is allowed
4294 boolean resumeOK = true;
4295 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004296 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004297 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004298 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004299 }
4300
4301 if (!resumeOK) {
4302 return false;
4303 }
4304 }
4305 }
4306 final long origId = Binder.clearCallingIdentity();
4307 boolean res = requestFinishActivityLocked(token, resultCode,
4308 resultData, "app-request");
4309 Binder.restoreCallingIdentity(origId);
4310 return res;
4311 }
4312 }
4313
4314 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4315 String resultWho, int requestCode, int resultCode, Intent data) {
4316
4317 if (callingUid > 0) {
4318 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4319 data, r);
4320 }
4321
Joe Onorato8a9b2202010-02-26 18:56:32 -08004322 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004323 + " : who=" + resultWho + " req=" + requestCode
4324 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004325 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4326 try {
4327 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4328 list.add(new ResultInfo(resultWho, requestCode,
4329 resultCode, data));
4330 r.app.thread.scheduleSendResult(r, list);
4331 return;
4332 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004333 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004334 }
4335 }
4336
4337 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4338 }
4339
4340 public final void finishSubActivity(IBinder token, String resultWho,
4341 int requestCode) {
4342 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004343 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 if (index < 0) {
4345 return;
4346 }
4347 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4348
4349 final long origId = Binder.clearCallingIdentity();
4350
4351 int i;
4352 for (i=mHistory.size()-1; i>=0; i--) {
4353 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4354 if (r.resultTo == self && r.requestCode == requestCode) {
4355 if ((r.resultWho == null && resultWho == null) ||
4356 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4357 finishActivityLocked(r, i,
4358 Activity.RESULT_CANCELED, null, "request-sub");
4359 }
4360 }
4361 }
4362
4363 Binder.restoreCallingIdentity(origId);
4364 }
4365 }
4366
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004367 public boolean willActivityBeVisible(IBinder token) {
4368 synchronized(this) {
4369 int i;
4370 for (i=mHistory.size()-1; i>=0; i--) {
4371 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4372 if (r == token) {
4373 return true;
4374 }
4375 if (r.fullscreen && !r.finishing) {
4376 return false;
4377 }
4378 }
4379 return true;
4380 }
4381 }
4382
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004383 public void overridePendingTransition(IBinder token, String packageName,
4384 int enterAnim, int exitAnim) {
4385 synchronized(this) {
4386 int index = indexOfTokenLocked(token);
4387 if (index < 0) {
4388 return;
4389 }
4390 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4391
4392 final long origId = Binder.clearCallingIdentity();
4393
4394 if (self.state == ActivityState.RESUMED
4395 || self.state == ActivityState.PAUSING) {
4396 mWindowManager.overridePendingAppTransition(packageName,
4397 enterAnim, exitAnim);
4398 }
4399
4400 Binder.restoreCallingIdentity(origId);
4401 }
4402 }
4403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004404 /**
4405 * Perform clean-up of service connections in an activity record.
4406 */
4407 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4408 // Throw away any services that have been bound by this activity.
4409 if (r.connections != null) {
4410 Iterator<ConnectionRecord> it = r.connections.iterator();
4411 while (it.hasNext()) {
4412 ConnectionRecord c = it.next();
4413 removeConnectionLocked(c, null, r);
4414 }
4415 r.connections = null;
4416 }
4417 }
4418
4419 /**
4420 * Perform the common clean-up of an activity record. This is called both
4421 * as part of destroyActivityLocked() (when destroying the client-side
4422 * representation) and cleaning things up as a result of its hosting
4423 * processing going away, in which case there is no remaining client-side
4424 * state to destroy so only the cleanup here is needed.
4425 */
4426 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4427 if (mResumedActivity == r) {
4428 mResumedActivity = null;
4429 }
4430 if (mFocusedActivity == r) {
4431 mFocusedActivity = null;
4432 }
4433
4434 r.configDestroy = false;
4435 r.frozenBeforeDestroy = false;
4436
4437 // Make sure this record is no longer in the pending finishes list.
4438 // This could happen, for example, if we are trimming activities
4439 // down to the max limit while they are still waiting to finish.
4440 mFinishingActivities.remove(r);
4441 mWaitingVisibleActivities.remove(r);
4442
4443 // Remove any pending results.
4444 if (r.finishing && r.pendingResults != null) {
4445 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4446 PendingIntentRecord rec = apr.get();
4447 if (rec != null) {
4448 cancelIntentSenderLocked(rec, false);
4449 }
4450 }
4451 r.pendingResults = null;
4452 }
4453
4454 if (cleanServices) {
4455 cleanUpActivityServicesLocked(r);
4456 }
4457
4458 if (mPendingThumbnails.size() > 0) {
4459 // There are clients waiting to receive thumbnails so, in case
4460 // this is an activity that someone is waiting for, add it
4461 // to the pending list so we can correctly update the clients.
4462 mCancelledThumbnails.add(r);
4463 }
4464
4465 // Get rid of any pending idle timeouts.
4466 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4467 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4468 }
4469
4470 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4471 if (r.state != ActivityState.DESTROYED) {
4472 mHistory.remove(r);
4473 r.inHistory = false;
4474 r.state = ActivityState.DESTROYED;
4475 mWindowManager.removeAppToken(r);
4476 if (VALIDATE_TOKENS) {
4477 mWindowManager.validateAppTokens(mHistory);
4478 }
4479 cleanUpActivityServicesLocked(r);
4480 removeActivityUriPermissionsLocked(r);
4481 }
4482 }
4483
4484 /**
4485 * Destroy the current CLIENT SIDE instance of an activity. This may be
4486 * called both when actually finishing an activity, or when performing
4487 * a configuration switch where we destroy the current client-side object
4488 * but then create a new client-side object for this same HistoryRecord.
4489 */
4490 private final boolean destroyActivityLocked(HistoryRecord r,
4491 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004492 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 TAG, "Removing activity: token=" + r
4494 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004495 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 System.identityHashCode(r),
4497 r.task.taskId, r.shortComponentName);
4498
4499 boolean removedFromHistory = false;
4500
4501 cleanUpActivityLocked(r, false);
4502
Dianne Hackborn03abb812010-01-04 18:43:19 -08004503 final boolean hadApp = r.app != null;
4504
4505 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 if (removeFromApp) {
4507 int idx = r.app.activities.indexOf(r);
4508 if (idx >= 0) {
4509 r.app.activities.remove(idx);
4510 }
4511 if (r.persistent) {
4512 decPersistentCountLocked(r.app);
4513 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004514 if (r.app.activities.size() == 0) {
4515 // No longer have activities, so update location in
4516 // LRU list.
4517 updateLruProcessLocked(r.app, true, false);
4518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004519 }
4520
4521 boolean skipDestroy = false;
4522
4523 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004524 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004525 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4526 r.configChangeFlags);
4527 } catch (Exception e) {
4528 // We can just ignore exceptions here... if the process
4529 // has crashed, our death notification will clean things
4530 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004531 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004532 if (r.finishing) {
4533 removeActivityFromHistoryLocked(r);
4534 removedFromHistory = true;
4535 skipDestroy = true;
4536 }
4537 }
4538
4539 r.app = null;
4540 r.nowVisible = false;
4541
4542 if (r.finishing && !skipDestroy) {
4543 r.state = ActivityState.DESTROYING;
4544 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4545 msg.obj = r;
4546 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4547 } else {
4548 r.state = ActivityState.DESTROYED;
4549 }
4550 } else {
4551 // remove this record from the history.
4552 if (r.finishing) {
4553 removeActivityFromHistoryLocked(r);
4554 removedFromHistory = true;
4555 } else {
4556 r.state = ActivityState.DESTROYED;
4557 }
4558 }
4559
4560 r.configChangeFlags = 0;
4561
Dianne Hackborn03abb812010-01-04 18:43:19 -08004562 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004563 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004564 }
4565
4566 return removedFromHistory;
4567 }
4568
Dianne Hackborn03abb812010-01-04 18:43:19 -08004569 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004570 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004571 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 TAG, "Removing app " + app + " from list " + list
4573 + " with " + i + " entries");
4574 while (i > 0) {
4575 i--;
4576 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004577 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004578 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4579 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004580 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 list.remove(i);
4582 }
4583 }
4584 }
4585
4586 /**
4587 * Main function for removing an existing process from the activity manager
4588 * as a result of that process going away. Clears out all connections
4589 * to the process.
4590 */
4591 private final void handleAppDiedLocked(ProcessRecord app,
4592 boolean restarting) {
4593 cleanUpApplicationRecordLocked(app, restarting, -1);
4594 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004595 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004596 }
4597
4598 // Just in case...
4599 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004600 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004601 mPausingActivity = null;
4602 }
4603 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4604 mLastPausedActivity = null;
4605 }
4606
4607 // Remove this application's activities from active lists.
4608 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4609 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4610 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4611 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4612
4613 boolean atTop = true;
4614 boolean hasVisibleActivities = false;
4615
4616 // Clean out the history list.
4617 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004618 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 TAG, "Removing app " + app + " from history with " + i + " entries");
4620 while (i > 0) {
4621 i--;
4622 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004623 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004624 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4625 if (r.app == app) {
4626 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004627 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004628 TAG, "Removing this entry! frozen=" + r.haveState
4629 + " finishing=" + r.finishing);
4630 mHistory.remove(i);
4631
4632 r.inHistory = false;
4633 mWindowManager.removeAppToken(r);
4634 if (VALIDATE_TOKENS) {
4635 mWindowManager.validateAppTokens(mHistory);
4636 }
4637 removeActivityUriPermissionsLocked(r);
4638
4639 } else {
4640 // We have the current state for this activity, so
4641 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004642 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 TAG, "Keeping entry, setting app to null");
4644 if (r.visible) {
4645 hasVisibleActivities = true;
4646 }
4647 r.app = null;
4648 r.nowVisible = false;
4649 if (!r.haveState) {
4650 r.icicle = null;
4651 }
4652 }
4653
4654 cleanUpActivityLocked(r, true);
4655 r.state = ActivityState.STOPPED;
4656 }
4657 atTop = false;
4658 }
4659
4660 app.activities.clear();
4661
4662 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004663 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004664 + " running instrumentation " + app.instrumentationClass);
4665 Bundle info = new Bundle();
4666 info.putString("shortMsg", "Process crashed.");
4667 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4668 }
4669
4670 if (!restarting) {
4671 if (!resumeTopActivityLocked(null)) {
4672 // If there was nothing to resume, and we are not already
4673 // restarting this process, but there is a visible activity that
4674 // is hosted by the process... then make sure all visible
4675 // activities are running, taking care of restarting this
4676 // process.
4677 if (hasVisibleActivities) {
4678 ensureActivitiesVisibleLocked(null, 0);
4679 }
4680 }
4681 }
4682 }
4683
4684 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4685 IBinder threadBinder = thread.asBinder();
4686
4687 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004688 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4689 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004690 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4691 return i;
4692 }
4693 }
4694 return -1;
4695 }
4696
4697 private final ProcessRecord getRecordForAppLocked(
4698 IApplicationThread thread) {
4699 if (thread == null) {
4700 return null;
4701 }
4702
4703 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004704 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004705 }
4706
4707 private final void appDiedLocked(ProcessRecord app, int pid,
4708 IApplicationThread thread) {
4709
4710 mProcDeaths[0]++;
4711
Magnus Edlund7bb25812010-02-24 15:45:06 +01004712 // Clean up already done if the process has been re-started.
4713 if (app.pid == pid && app.thread != null &&
4714 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07004715 if (!app.killedBackground) {
4716 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
4717 + ") has died.");
4718 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08004719 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004720 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 TAG, "Dying app: " + app + ", pid: " + pid
4722 + ", thread: " + thread.asBinder());
4723 boolean doLowMem = app.instrumentationClass == null;
4724 handleAppDiedLocked(app, false);
4725
4726 if (doLowMem) {
4727 // If there are no longer any background processes running,
4728 // and the app that died was not running instrumentation,
4729 // then tell everyone we are now low on memory.
4730 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004731 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4732 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4734 haveBg = true;
4735 break;
4736 }
4737 }
4738
4739 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004740 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004741 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004742 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004743 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4744 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004745 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004746 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4747 // The low memory report is overriding any current
4748 // state for a GC request. Make sure to do
4749 // visible/foreground processes first.
4750 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4751 rec.lastRequestedGc = 0;
4752 } else {
4753 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004755 rec.reportLowMemory = true;
4756 rec.lastLowMemory = now;
4757 mProcessesToGc.remove(rec);
4758 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759 }
4760 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004761 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004762 }
4763 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004764 } else if (app.pid != pid) {
4765 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004766 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004767 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004768 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004769 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004770 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771 + thread.asBinder());
4772 }
4773 }
4774
Dan Egnor42471dd2010-01-07 17:25:22 -08004775 /**
4776 * If a stack trace dump file is configured, dump process stack traces.
4777 * @param pids of dalvik VM processes to dump stack traces for
4778 * @return file containing stack traces, or null if no dump file is configured
4779 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08004780 public static File dumpStackTraces(ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004781 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4782 if (tracesPath == null || tracesPath.length() == 0) {
4783 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004784 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004785
4786 File tracesFile = new File(tracesPath);
4787 try {
4788 File tracesDir = tracesFile.getParentFile();
4789 if (!tracesDir.exists()) tracesFile.mkdirs();
4790 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4791
4792 if (tracesFile.exists()) tracesFile.delete();
4793 tracesFile.createNewFile();
4794 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
4795 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004796 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004797 return null;
4798 }
4799
4800 // Use a FileObserver to detect when traces finish writing.
4801 // The order of traces is considered important to maintain for legibility.
4802 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
4803 public synchronized void onEvent(int event, String path) { notify(); }
4804 };
4805
4806 try {
4807 observer.startWatching();
4808 int num = pids.size();
4809 for (int i = 0; i < num; i++) {
4810 synchronized (observer) {
4811 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
4812 observer.wait(200); // Wait for write-close, give up after 200msec
4813 }
4814 }
4815 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08004816 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08004817 } finally {
4818 observer.stopWatching();
4819 }
4820
4821 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004822 }
4823
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004824 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08004825 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004826 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004827
4828 synchronized (this) {
4829 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
4830 if (mShuttingDown) {
4831 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
4832 return;
4833 } else if (app.notResponding) {
4834 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
4835 return;
4836 } else if (app.crashing) {
4837 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
4838 return;
4839 }
4840
4841 // In case we come through here for the same app before completing
4842 // this one, mark as anring now so we will bail out.
4843 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08004844
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004845 // Log the ANR to the event log.
4846 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
4847 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08004848
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004849 // Dump thread traces as quickly as we can, starting with "interesting" processes.
4850 pids.add(app.pid);
4851
4852 int parentPid = app.pid;
4853 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
4854 if (parentPid != app.pid) pids.add(parentPid);
4855
4856 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08004857
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004858 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
4859 ProcessRecord r = mLruProcesses.get(i);
4860 if (r != null && r.thread != null) {
4861 int pid = r.pid;
4862 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
4863 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004864 }
4865 }
4866
Dan Egnor42471dd2010-01-07 17:25:22 -08004867 File tracesFile = dumpStackTraces(pids);
4868
4869 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07004870 StringBuilder info = mStringBuilder;
4871 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08004872 info.append("ANR in ").append(app.processName);
4873 if (activity != null && activity.shortComponentName != null) {
4874 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07004875 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08004876 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004877 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004878 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004880 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08004881 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004883
Dan Egnor42471dd2010-01-07 17:25:22 -08004884 String cpuInfo = null;
4885 if (MONITOR_CPU_USAGE) {
4886 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004887 synchronized (mProcessStatsThread) {
4888 cpuInfo = mProcessStats.printCurrentState();
4889 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004890 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 }
4892
Joe Onorato8a9b2202010-02-26 18:56:32 -08004893 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08004894 if (tracesFile == null) {
4895 // There is no trace file, so dump (only) the alleged culprit's threads to the log
4896 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
4897 }
4898
4899 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
4900
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004901 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004902 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08004903 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
4904 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004905 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004906 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
4907 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 }
4909 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004910 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004911 }
4912 }
4913
Dan Egnor42471dd2010-01-07 17:25:22 -08004914 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
4915 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
4916 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07004917
4918 synchronized (this) {
4919 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
4920 Process.killProcess(app.pid);
4921 return;
4922 }
4923
4924 // Set the app's notResponding state, and look up the errorReportReceiver
4925 makeAppNotRespondingLocked(app,
4926 activity != null ? activity.shortComponentName : null,
4927 annotation != null ? "ANR " + annotation : "ANR",
4928 info.toString());
4929
4930 // Bring up the infamous App Not Responding dialog
4931 Message msg = Message.obtain();
4932 HashMap map = new HashMap();
4933 msg.what = SHOW_NOT_RESPONDING_MSG;
4934 msg.obj = map;
4935 map.put("app", app);
4936 if (activity != null) {
4937 map.put("activity", activity);
4938 }
4939
4940 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08004941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 }
4943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 private final void decPersistentCountLocked(ProcessRecord app)
4945 {
4946 app.persistentActivities--;
4947 if (app.persistentActivities > 0) {
4948 // Still more of 'em...
4949 return;
4950 }
4951 if (app.persistent) {
4952 // Ah, but the application itself is persistent. Whatever!
4953 return;
4954 }
4955
4956 // App is no longer persistent... make sure it and the ones
4957 // following it in the LRU list have the correc oom_adj.
4958 updateOomAdjLocked();
4959 }
4960
4961 public void setPersistent(IBinder token, boolean isPersistent) {
4962 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
4963 != PackageManager.PERMISSION_GRANTED) {
4964 String msg = "Permission Denial: setPersistent() from pid="
4965 + Binder.getCallingPid()
4966 + ", uid=" + Binder.getCallingUid()
4967 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004968 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004969 throw new SecurityException(msg);
4970 }
4971
4972 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004973 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004974 if (index < 0) {
4975 return;
4976 }
4977 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4978 ProcessRecord app = r.app;
4979
Joe Onorato8a9b2202010-02-26 18:56:32 -08004980 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004981 TAG, "Setting persistence " + isPersistent + ": " + r);
4982
4983 if (isPersistent) {
4984 if (r.persistent) {
4985 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004986 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004987 return;
4988 }
4989 r.persistent = true;
4990 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004991 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992 if (app.persistentActivities > 1) {
4993 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08004994 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004995 return;
4996 }
4997 if (app.persistent) {
4998 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004999 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 return;
5001 }
5002
5003 // App is now persistent... make sure it and the ones
5004 // following it now have the correct oom_adj.
5005 final long origId = Binder.clearCallingIdentity();
5006 updateOomAdjLocked();
5007 Binder.restoreCallingIdentity(origId);
5008
5009 } else {
5010 if (!r.persistent) {
5011 // Okay okay, I heard you already!
5012 return;
5013 }
5014 r.persistent = false;
5015 final long origId = Binder.clearCallingIdentity();
5016 decPersistentCountLocked(app);
5017 Binder.restoreCallingIdentity(origId);
5018
5019 }
5020 }
5021 }
5022
5023 public boolean clearApplicationUserData(final String packageName,
5024 final IPackageDataObserver observer) {
5025 int uid = Binder.getCallingUid();
5026 int pid = Binder.getCallingPid();
5027 long callingId = Binder.clearCallingIdentity();
5028 try {
5029 IPackageManager pm = ActivityThread.getPackageManager();
5030 int pkgUid = -1;
5031 synchronized(this) {
5032 try {
5033 pkgUid = pm.getPackageUid(packageName);
5034 } catch (RemoteException e) {
5035 }
5036 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005037 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 return false;
5039 }
5040 if (uid == pkgUid || checkComponentPermission(
5041 android.Manifest.permission.CLEAR_APP_USER_DATA,
5042 pid, uid, -1)
5043 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005044 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005045 } else {
5046 throw new SecurityException(pid+" does not have permission:"+
5047 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5048 "for process:"+packageName);
5049 }
5050 }
5051
5052 try {
5053 //clear application user data
5054 pm.clearApplicationUserData(packageName, observer);
5055 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5056 Uri.fromParts("package", packageName, null));
5057 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005058 synchronized (this) {
5059 broadcastIntentLocked(null, null, intent,
5060 null, null, 0, null, null, null,
5061 false, false, MY_PID, Process.SYSTEM_UID);
5062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 } catch (RemoteException e) {
5064 }
5065 } finally {
5066 Binder.restoreCallingIdentity(callingId);
5067 }
5068 return true;
5069 }
5070
Dianne Hackborn03abb812010-01-04 18:43:19 -08005071 public void killBackgroundProcesses(final String packageName) {
5072 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5073 != PackageManager.PERMISSION_GRANTED &&
5074 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5075 != PackageManager.PERMISSION_GRANTED) {
5076 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 + Binder.getCallingPid()
5078 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005079 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005080 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005081 throw new SecurityException(msg);
5082 }
5083
5084 long callingId = Binder.clearCallingIdentity();
5085 try {
5086 IPackageManager pm = ActivityThread.getPackageManager();
5087 int pkgUid = -1;
5088 synchronized(this) {
5089 try {
5090 pkgUid = pm.getPackageUid(packageName);
5091 } catch (RemoteException e) {
5092 }
5093 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005094 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005095 return;
5096 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005097 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005098 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005099 }
5100 } finally {
5101 Binder.restoreCallingIdentity(callingId);
5102 }
5103 }
5104
5105 public void forceStopPackage(final String packageName) {
5106 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5107 != PackageManager.PERMISSION_GRANTED) {
5108 String msg = "Permission Denial: forceStopPackage() from pid="
5109 + Binder.getCallingPid()
5110 + ", uid=" + Binder.getCallingUid()
5111 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005112 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005113 throw new SecurityException(msg);
5114 }
5115
5116 long callingId = Binder.clearCallingIdentity();
5117 try {
5118 IPackageManager pm = ActivityThread.getPackageManager();
5119 int pkgUid = -1;
5120 synchronized(this) {
5121 try {
5122 pkgUid = pm.getPackageUid(packageName);
5123 } catch (RemoteException e) {
5124 }
5125 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005126 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005127 return;
5128 }
5129 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 }
5131 } finally {
5132 Binder.restoreCallingIdentity(callingId);
5133 }
5134 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005135
5136 /*
5137 * The pkg name and uid have to be specified.
5138 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5139 */
5140 public void killApplicationWithUid(String pkg, int uid) {
5141 if (pkg == null) {
5142 return;
5143 }
5144 // Make sure the uid is valid.
5145 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005146 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005147 return;
5148 }
5149 int callerUid = Binder.getCallingUid();
5150 // Only the system server can kill an application
5151 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005152 // Post an aysnc message to kill the application
5153 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5154 msg.arg1 = uid;
5155 msg.arg2 = 0;
5156 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005157 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005158 } else {
5159 throw new SecurityException(callerUid + " cannot kill pkg: " +
5160 pkg);
5161 }
5162 }
5163
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005164 public void closeSystemDialogs(String reason) {
5165 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5166 if (reason != null) {
5167 intent.putExtra("reason", reason);
5168 }
5169
5170 final int uid = Binder.getCallingUid();
5171 final long origId = Binder.clearCallingIdentity();
5172 synchronized (this) {
5173 int i = mWatchers.beginBroadcast();
5174 while (i > 0) {
5175 i--;
5176 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5177 if (w != null) {
5178 try {
5179 w.closingSystemDialogs(reason);
5180 } catch (RemoteException e) {
5181 }
5182 }
5183 }
5184 mWatchers.finishBroadcast();
5185
Dianne Hackbornffa42482009-09-23 22:20:11 -07005186 mWindowManager.closeSystemDialogs(reason);
5187
5188 for (i=mHistory.size()-1; i>=0; i--) {
5189 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5190 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5191 finishActivityLocked(r, i,
5192 Activity.RESULT_CANCELED, null, "close-sys");
5193 }
5194 }
5195
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005196 broadcastIntentLocked(null, null, intent, null,
5197 null, 0, null, null, null, false, false, -1, uid);
5198 }
5199 Binder.restoreCallingIdentity(origId);
5200 }
5201
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005202 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005203 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005204 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5205 for (int i=pids.length-1; i>=0; i--) {
5206 infos[i] = new Debug.MemoryInfo();
5207 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005208 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005209 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005210 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005211
5212 public void killApplicationProcess(String processName, int uid) {
5213 if (processName == null) {
5214 return;
5215 }
5216
5217 int callerUid = Binder.getCallingUid();
5218 // Only the system server can kill an application
5219 if (callerUid == Process.SYSTEM_UID) {
5220 synchronized (this) {
5221 ProcessRecord app = getProcessRecordLocked(processName, uid);
5222 if (app != null) {
5223 try {
5224 app.thread.scheduleSuicide();
5225 } catch (RemoteException e) {
5226 // If the other end already died, then our work here is done.
5227 }
5228 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005229 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005230 + processName + " / " + uid);
5231 }
5232 }
5233 } else {
5234 throw new SecurityException(callerUid + " cannot kill app process: " +
5235 processName);
5236 }
5237 }
5238
Dianne Hackborn03abb812010-01-04 18:43:19 -08005239 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005240 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005241 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5242 Uri.fromParts("package", packageName, null));
5243 intent.putExtra(Intent.EXTRA_UID, uid);
5244 broadcastIntentLocked(null, null, intent,
5245 null, null, 0, null, null, null,
5246 false, false, MY_PID, Process.SYSTEM_UID);
5247 }
5248
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005249 private final boolean killPackageProcessesLocked(String packageName, int uid,
5250 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005251 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005252
Dianne Hackborn03abb812010-01-04 18:43:19 -08005253 // Remove all processes this package may have touched: all with the
5254 // same UID (except for the system or root user), and all whose name
5255 // matches the package name.
5256 final String procNamePrefix = packageName + ":";
5257 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5258 final int NA = apps.size();
5259 for (int ia=0; ia<NA; ia++) {
5260 ProcessRecord app = apps.valueAt(ia);
5261 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005262 if (doit) {
5263 procs.add(app);
5264 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005265 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5266 || app.processName.equals(packageName)
5267 || app.processName.startsWith(procNamePrefix)) {
5268 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005269 if (!doit) {
5270 return true;
5271 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005272 app.removed = true;
5273 procs.add(app);
5274 }
5275 }
5276 }
5277 }
5278
5279 int N = procs.size();
5280 for (int i=0; i<N; i++) {
5281 removeProcessLocked(procs.get(i), callerWillRestart);
5282 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005283 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005284 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005285
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005286 private final boolean forceStopPackageLocked(String name, int uid,
5287 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005288 int i, N;
5289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005290 if (uid < 0) {
5291 try {
5292 uid = ActivityThread.getPackageManager().getPackageUid(name);
5293 } catch (RemoteException e) {
5294 }
5295 }
5296
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005297 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005298 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005299
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005300 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5301 while (badApps.hasNext()) {
5302 SparseArray<Long> ba = badApps.next();
5303 if (ba.get(uid) != null) {
5304 badApps.remove();
5305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005306 }
5307 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005308
5309 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5310 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311
5312 for (i=mHistory.size()-1; i>=0; i--) {
5313 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5314 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005315 if (!doit) {
5316 return true;
5317 }
5318 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005319 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 if (r.app != null) {
5321 r.app.removed = true;
5322 }
5323 r.app = null;
5324 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5325 }
5326 }
5327
5328 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5329 for (ServiceRecord service : mServices.values()) {
5330 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005331 if (!doit) {
5332 return true;
5333 }
5334 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005335 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005336 if (service.app != null) {
5337 service.app.removed = true;
5338 }
5339 service.app = null;
5340 services.add(service);
5341 }
5342 }
5343
5344 N = services.size();
5345 for (i=0; i<N; i++) {
5346 bringDownServiceLocked(services.get(i), true);
5347 }
5348
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005349 if (doit) {
5350 if (purgeCache) {
5351 AttributeCache ac = AttributeCache.instance();
5352 if (ac != null) {
5353 ac.removePackage(name);
5354 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005355 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005356 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005357 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005358
5359 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005360 }
5361
5362 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5363 final String name = app.processName;
5364 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005365 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005366 TAG, "Force removing process " + app + " (" + name
5367 + "/" + uid + ")");
5368
5369 mProcessNames.remove(name, uid);
5370 boolean needRestart = false;
5371 if (app.pid > 0 && app.pid != MY_PID) {
5372 int pid = app.pid;
5373 synchronized (mPidsSelfLocked) {
5374 mPidsSelfLocked.remove(pid);
5375 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5376 }
5377 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005378 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 Process.killProcess(pid);
5380
5381 if (app.persistent) {
5382 if (!callerWillRestart) {
5383 addAppLocked(app.info);
5384 } else {
5385 needRestart = true;
5386 }
5387 }
5388 } else {
5389 mRemovedProcesses.add(app);
5390 }
5391
5392 return needRestart;
5393 }
5394
5395 private final void processStartTimedOutLocked(ProcessRecord app) {
5396 final int pid = app.pid;
5397 boolean gone = false;
5398 synchronized (mPidsSelfLocked) {
5399 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5400 if (knownApp != null && knownApp.thread == null) {
5401 mPidsSelfLocked.remove(pid);
5402 gone = true;
5403 }
5404 }
5405
5406 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005407 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005408 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005409 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005411 // Take care of any launching providers waiting for this process.
5412 checkAppInLaunchingProvidersLocked(app, true);
5413 // Take care of any services that are waiting for the process.
5414 for (int i=0; i<mPendingServices.size(); i++) {
5415 ServiceRecord sr = mPendingServices.get(i);
5416 if (app.info.uid == sr.appInfo.uid
5417 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005418 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005419 mPendingServices.remove(i);
5420 i--;
5421 bringDownServiceLocked(sr, true);
5422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005423 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005424 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005425 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005426 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005427 try {
5428 IBackupManager bm = IBackupManager.Stub.asInterface(
5429 ServiceManager.getService(Context.BACKUP_SERVICE));
5430 bm.agentDisconnected(app.info.packageName);
5431 } catch (RemoteException e) {
5432 // Can't happen; the backup manager is local
5433 }
5434 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005435 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005436 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005437 mPendingBroadcast = null;
5438 scheduleBroadcastsLocked();
5439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005440 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005441 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442 }
5443 }
5444
5445 private final boolean attachApplicationLocked(IApplicationThread thread,
5446 int pid) {
5447
5448 // Find the application record that is being attached... either via
5449 // the pid if we are running in multiple processes, or just pull the
5450 // next app record if we are emulating process with anonymous threads.
5451 ProcessRecord app;
5452 if (pid != MY_PID && pid >= 0) {
5453 synchronized (mPidsSelfLocked) {
5454 app = mPidsSelfLocked.get(pid);
5455 }
5456 } else if (mStartingProcesses.size() > 0) {
5457 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005458 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 } else {
5460 app = null;
5461 }
5462
5463 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005464 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005465 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005466 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005467 if (pid > 0 && pid != MY_PID) {
5468 Process.killProcess(pid);
5469 } else {
5470 try {
5471 thread.scheduleExit();
5472 } catch (Exception e) {
5473 // Ignore exceptions.
5474 }
5475 }
5476 return false;
5477 }
5478
5479 // If this application record is still attached to a previous
5480 // process, clean it up now.
5481 if (app.thread != null) {
5482 handleAppDiedLocked(app, true);
5483 }
5484
5485 // Tell the process all about itself.
5486
Joe Onorato8a9b2202010-02-26 18:56:32 -08005487 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 TAG, "Binding process pid " + pid + " to record " + app);
5489
5490 String processName = app.processName;
5491 try {
5492 thread.asBinder().linkToDeath(new AppDeathRecipient(
5493 app, pid, thread), 0);
5494 } catch (RemoteException e) {
5495 app.resetPackageList();
5496 startProcessLocked(app, "link fail", processName);
5497 return false;
5498 }
5499
Doug Zongker2bec3d42009-12-04 12:52:44 -08005500 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501
5502 app.thread = thread;
5503 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005504 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5505 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005506 app.forcingToForeground = null;
5507 app.foregroundServices = false;
5508 app.debugging = false;
5509
5510 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5511
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005512 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5513 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005515 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005516 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005517 }
5518
Joe Onorato8a9b2202010-02-26 18:56:32 -08005519 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005520 TAG, "New app record " + app
5521 + " thread=" + thread.asBinder() + " pid=" + pid);
5522 try {
5523 int testMode = IApplicationThread.DEBUG_OFF;
5524 if (mDebugApp != null && mDebugApp.equals(processName)) {
5525 testMode = mWaitForDebugger
5526 ? IApplicationThread.DEBUG_WAIT
5527 : IApplicationThread.DEBUG_ON;
5528 app.debugging = true;
5529 if (mDebugTransient) {
5530 mDebugApp = mOrigDebugApp;
5531 mWaitForDebugger = mOrigWaitForDebugger;
5532 }
5533 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005534
Christopher Tate181fafa2009-05-14 11:12:14 -07005535 // If the app is being launched for restore or full backup, set it up specially
5536 boolean isRestrictedBackupMode = false;
5537 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5538 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5539 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5540 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005541
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005542 ensurePackageDexOpt(app.instrumentationInfo != null
5543 ? app.instrumentationInfo.packageName
5544 : app.info.packageName);
5545 if (app.instrumentationClass != null) {
5546 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005547 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005548 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005549 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005550 thread.bindApplication(processName, app.instrumentationInfo != null
5551 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005552 app.instrumentationClass, app.instrumentationProfileFile,
5553 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005554 isRestrictedBackupMode || !normalMode,
5555 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005556 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005557 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 } catch (Exception e) {
5559 // todo: Yikes! What should we do? For now we will try to
5560 // start another process, but that could easily get us in
5561 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005562 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563
5564 app.resetPackageList();
5565 startProcessLocked(app, "bind fail", processName);
5566 return false;
5567 }
5568
5569 // Remove this record from the list of starting applications.
5570 mPersistentStartingProcesses.remove(app);
5571 mProcessesOnHold.remove(app);
5572
5573 boolean badApp = false;
5574 boolean didSomething = false;
5575
5576 // See if the top visible activity is waiting to run in this process...
5577 HistoryRecord hr = topRunningActivityLocked(null);
5578 if (hr != null) {
5579 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5580 && processName.equals(hr.processName)) {
5581 try {
5582 if (realStartActivityLocked(hr, app, true, true)) {
5583 didSomething = true;
5584 }
5585 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005586 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005587 + hr.intent.getComponent().flattenToShortString(), e);
5588 badApp = true;
5589 }
5590 } else {
5591 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5592 }
5593 }
5594
5595 // Find any services that should be running in this process...
5596 if (!badApp && mPendingServices.size() > 0) {
5597 ServiceRecord sr = null;
5598 try {
5599 for (int i=0; i<mPendingServices.size(); i++) {
5600 sr = mPendingServices.get(i);
5601 if (app.info.uid != sr.appInfo.uid
5602 || !processName.equals(sr.processName)) {
5603 continue;
5604 }
5605
5606 mPendingServices.remove(i);
5607 i--;
5608 realStartServiceLocked(sr, app);
5609 didSomething = true;
5610 }
5611 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005612 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 + sr.shortName, e);
5614 badApp = true;
5615 }
5616 }
5617
5618 // Check if the next broadcast receiver is in this process...
5619 BroadcastRecord br = mPendingBroadcast;
5620 if (!badApp && br != null && br.curApp == app) {
5621 try {
5622 mPendingBroadcast = null;
5623 processCurBroadcastLocked(br, app);
5624 didSomething = true;
5625 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005626 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005627 + br.curComponent.flattenToShortString(), e);
5628 badApp = true;
5629 logBroadcastReceiverDiscard(br);
5630 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5631 br.resultExtras, br.resultAbort, true);
5632 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005633 // We need to reset the state if we fails to start the receiver.
5634 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 }
5636 }
5637
Christopher Tate181fafa2009-05-14 11:12:14 -07005638 // Check whether the next backup agent is in this process...
5639 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005640 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005641 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005642 try {
5643 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5644 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005645 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005646 e.printStackTrace();
5647 }
5648 }
5649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005650 if (badApp) {
5651 // todo: Also need to kill application to deal with all
5652 // kinds of exceptions.
5653 handleAppDiedLocked(app, false);
5654 return false;
5655 }
5656
5657 if (!didSomething) {
5658 updateOomAdjLocked();
5659 }
5660
5661 return true;
5662 }
5663
5664 public final void attachApplication(IApplicationThread thread) {
5665 synchronized (this) {
5666 int callingPid = Binder.getCallingPid();
5667 final long origId = Binder.clearCallingIdentity();
5668 attachApplicationLocked(thread, callingPid);
5669 Binder.restoreCallingIdentity(origId);
5670 }
5671 }
5672
Dianne Hackborne88846e2009-09-30 21:34:25 -07005673 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005675 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676 Binder.restoreCallingIdentity(origId);
5677 }
5678
5679 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5680 boolean remove) {
5681 int N = mStoppingActivities.size();
5682 if (N <= 0) return null;
5683
5684 ArrayList<HistoryRecord> stops = null;
5685
5686 final boolean nowVisible = mResumedActivity != null
5687 && mResumedActivity.nowVisible
5688 && !mResumedActivity.waitingVisible;
5689 for (int i=0; i<N; i++) {
5690 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005691 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005692 + nowVisible + " waitingVisible=" + s.waitingVisible
5693 + " finishing=" + s.finishing);
5694 if (s.waitingVisible && nowVisible) {
5695 mWaitingVisibleActivities.remove(s);
5696 s.waitingVisible = false;
5697 if (s.finishing) {
5698 // If this activity is finishing, it is sitting on top of
5699 // everyone else but we now know it is no longer needed...
5700 // so get rid of it. Otherwise, we need to go through the
5701 // normal flow and hide it once we determine that it is
5702 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005703 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005704 mWindowManager.setAppVisibility(s, false);
5705 }
5706 }
5707 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005708 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 if (stops == null) {
5710 stops = new ArrayList<HistoryRecord>();
5711 }
5712 stops.add(s);
5713 mStoppingActivities.remove(i);
5714 N--;
5715 i--;
5716 }
5717 }
5718
5719 return stops;
5720 }
5721
5722 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005723 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005724 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005725 mWindowManager.enableScreenAfterBoot();
5726 }
5727
Dianne Hackborne88846e2009-09-30 21:34:25 -07005728 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5729 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005730 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005731
5732 ArrayList<HistoryRecord> stops = null;
5733 ArrayList<HistoryRecord> finishes = null;
5734 ArrayList<HistoryRecord> thumbnails = null;
5735 int NS = 0;
5736 int NF = 0;
5737 int NT = 0;
5738 IApplicationThread sendThumbnail = null;
5739 boolean booting = false;
5740 boolean enableScreen = false;
5741
5742 synchronized (this) {
5743 if (token != null) {
5744 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5745 }
5746
5747 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005748 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005749 if (index >= 0) {
5750 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5751
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005752 if (fromTimeout) {
5753 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5754 }
5755
Dianne Hackborne88846e2009-09-30 21:34:25 -07005756 // This is a hack to semi-deal with a race condition
5757 // in the client where it can be constructed with a
5758 // newer configuration from when we asked it to launch.
5759 // We'll update with whatever configuration it now says
5760 // it used to launch.
5761 if (config != null) {
5762 r.configuration = config;
5763 }
5764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 // No longer need to keep the device awake.
5766 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5767 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5768 mLaunchingActivity.release();
5769 }
5770
5771 // We are now idle. If someone is waiting for a thumbnail from
5772 // us, we can now deliver.
5773 r.idle = true;
5774 scheduleAppGcsLocked();
5775 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5776 sendThumbnail = r.app.thread;
5777 r.thumbnailNeeded = false;
5778 }
5779
5780 // If this activity is fullscreen, set up to hide those under it.
5781
Joe Onorato8a9b2202010-02-26 18:56:32 -08005782 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005783 ensureActivitiesVisibleLocked(null, 0);
5784
Joe Onorato8a9b2202010-02-26 18:56:32 -08005785 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 if (!mBooted && !fromTimeout) {
5787 mBooted = true;
5788 enableScreen = true;
5789 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005790
5791 } else if (fromTimeout) {
5792 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005793 }
5794
5795 // Atomically retrieve all of the other things to do.
5796 stops = processStoppingActivitiesLocked(true);
5797 NS = stops != null ? stops.size() : 0;
5798 if ((NF=mFinishingActivities.size()) > 0) {
5799 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
5800 mFinishingActivities.clear();
5801 }
5802 if ((NT=mCancelledThumbnails.size()) > 0) {
5803 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
5804 mCancelledThumbnails.clear();
5805 }
5806
5807 booting = mBooting;
5808 mBooting = false;
5809 }
5810
5811 int i;
5812
5813 // Send thumbnail if requested.
5814 if (sendThumbnail != null) {
5815 try {
5816 sendThumbnail.requestThumbnail(token);
5817 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005818 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819 sendPendingThumbnail(null, token, null, null, true);
5820 }
5821 }
5822
5823 // Stop any activities that are scheduled to do so but have been
5824 // waiting for the next one to start.
5825 for (i=0; i<NS; i++) {
5826 HistoryRecord r = (HistoryRecord)stops.get(i);
5827 synchronized (this) {
5828 if (r.finishing) {
5829 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
5830 } else {
5831 stopActivityLocked(r);
5832 }
5833 }
5834 }
5835
5836 // Finish any activities that are scheduled to do so but have been
5837 // waiting for the next one to start.
5838 for (i=0; i<NF; i++) {
5839 HistoryRecord r = (HistoryRecord)finishes.get(i);
5840 synchronized (this) {
5841 destroyActivityLocked(r, true);
5842 }
5843 }
5844
5845 // Report back to any thumbnail receivers.
5846 for (i=0; i<NT; i++) {
5847 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
5848 sendPendingThumbnail(r, null, null, null, true);
5849 }
5850
5851 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005852 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 }
5854
5855 trimApplications();
5856 //dump();
5857 //mWindowManager.dump();
5858
5859 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 enableScreenAfterBoot();
5861 }
5862 }
5863
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005864 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005865 IntentFilter pkgFilter = new IntentFilter();
5866 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5867 pkgFilter.addDataScheme("package");
5868 mContext.registerReceiver(new BroadcastReceiver() {
5869 @Override
5870 public void onReceive(Context context, Intent intent) {
5871 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
5872 if (pkgs != null) {
5873 for (String pkg : pkgs) {
5874 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
5875 setResultCode(Activity.RESULT_OK);
5876 return;
5877 }
5878 }
5879 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005880 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005881 }, pkgFilter);
5882
5883 synchronized (this) {
5884 // Ensure that any processes we had put on hold are now started
5885 // up.
5886 final int NP = mProcessesOnHold.size();
5887 if (NP > 0) {
5888 ArrayList<ProcessRecord> procs =
5889 new ArrayList<ProcessRecord>(mProcessesOnHold);
5890 for (int ip=0; ip<NP; ip++) {
5891 this.startProcessLocked(procs.get(ip), "on-hold", null);
5892 }
5893 }
5894
5895 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5896 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005897 broadcastIntentLocked(null, null,
5898 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
5899 null, null, 0, null, null,
5900 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
5901 false, false, MY_PID, Process.SYSTEM_UID);
5902 }
5903 }
5904 }
5905
5906 final void ensureBootCompleted() {
5907 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005908 boolean enableScreen;
5909 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005910 booting = mBooting;
5911 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005912 enableScreen = !mBooted;
5913 mBooted = true;
5914 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005915
5916 if (booting) {
5917 finishBooting();
5918 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005919
5920 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005921 enableScreenAfterBoot();
5922 }
5923 }
5924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005925 public final void activityPaused(IBinder token, Bundle icicle) {
5926 // Refuse possible leaked file descriptors
5927 if (icicle != null && icicle.hasFileDescriptors()) {
5928 throw new IllegalArgumentException("File descriptors passed in Bundle");
5929 }
5930
5931 final long origId = Binder.clearCallingIdentity();
5932 activityPaused(token, icicle, false);
5933 Binder.restoreCallingIdentity(origId);
5934 }
5935
5936 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005937 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
5939 + ", timeout=" + timeout);
5940
5941 HistoryRecord r = null;
5942
5943 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005944 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005945 if (index >= 0) {
5946 r = (HistoryRecord)mHistory.get(index);
5947 if (!timeout) {
5948 r.icicle = icicle;
5949 r.haveState = true;
5950 }
5951 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
5952 if (mPausingActivity == r) {
5953 r.state = ActivityState.PAUSED;
5954 completePauseLocked();
5955 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005956 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 System.identityHashCode(r), r.shortComponentName,
5958 mPausingActivity != null
5959 ? mPausingActivity.shortComponentName : "(none)");
5960 }
5961 }
5962 }
5963 }
5964
5965 public final void activityStopped(IBinder token, Bitmap thumbnail,
5966 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005967 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 TAG, "Activity stopped: token=" + token);
5969
5970 HistoryRecord r = null;
5971
5972 final long origId = Binder.clearCallingIdentity();
5973
5974 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005975 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005976 if (index >= 0) {
5977 r = (HistoryRecord)mHistory.get(index);
5978 r.thumbnail = thumbnail;
5979 r.description = description;
5980 r.stopped = true;
5981 r.state = ActivityState.STOPPED;
5982 if (!r.finishing) {
5983 if (r.configDestroy) {
5984 destroyActivityLocked(r, true);
5985 resumeTopActivityLocked(null);
5986 }
5987 }
5988 }
5989 }
5990
5991 if (r != null) {
5992 sendPendingThumbnail(r, null, null, null, false);
5993 }
5994
5995 trimApplications();
5996
5997 Binder.restoreCallingIdentity(origId);
5998 }
5999
6000 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006001 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006002 synchronized (this) {
6003 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
6004
Dianne Hackborn75b03852009-06-12 15:43:26 -07006005 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006006 if (index >= 0) {
6007 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6008 if (r.state == ActivityState.DESTROYING) {
6009 final long origId = Binder.clearCallingIdentity();
6010 removeActivityFromHistoryLocked(r);
6011 Binder.restoreCallingIdentity(origId);
6012 }
6013 }
6014 }
6015 }
6016
6017 public String getCallingPackage(IBinder token) {
6018 synchronized (this) {
6019 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07006020 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006021 }
6022 }
6023
6024 public ComponentName getCallingActivity(IBinder token) {
6025 synchronized (this) {
6026 HistoryRecord r = getCallingRecordLocked(token);
6027 return r != null ? r.intent.getComponent() : null;
6028 }
6029 }
6030
6031 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006032 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006033 if (index >= 0) {
6034 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6035 if (r != null) {
6036 return r.resultTo;
6037 }
6038 }
6039 return null;
6040 }
6041
6042 public ComponentName getActivityClassForToken(IBinder token) {
6043 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006044 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006045 if (index >= 0) {
6046 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6047 return r.intent.getComponent();
6048 }
6049 return null;
6050 }
6051 }
6052
6053 public String getPackageForToken(IBinder token) {
6054 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006055 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 if (index >= 0) {
6057 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6058 return r.packageName;
6059 }
6060 return null;
6061 }
6062 }
6063
6064 public IIntentSender getIntentSender(int type,
6065 String packageName, IBinder token, String resultWho,
6066 int requestCode, Intent intent, String resolvedType, int flags) {
6067 // Refuse possible leaked file descriptors
6068 if (intent != null && intent.hasFileDescriptors() == true) {
6069 throw new IllegalArgumentException("File descriptors passed in Intent");
6070 }
6071
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006072 if (type == INTENT_SENDER_BROADCAST) {
6073 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6074 throw new IllegalArgumentException(
6075 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6076 }
6077 }
6078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 synchronized(this) {
6080 int callingUid = Binder.getCallingUid();
6081 try {
6082 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6083 Process.supportsProcesses()) {
6084 int uid = ActivityThread.getPackageManager()
6085 .getPackageUid(packageName);
6086 if (uid != Binder.getCallingUid()) {
6087 String msg = "Permission Denial: getIntentSender() from pid="
6088 + Binder.getCallingPid()
6089 + ", uid=" + Binder.getCallingUid()
6090 + ", (need uid=" + uid + ")"
6091 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006092 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006093 throw new SecurityException(msg);
6094 }
6095 }
6096 } catch (RemoteException e) {
6097 throw new SecurityException(e);
6098 }
6099 HistoryRecord activity = null;
6100 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006101 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 if (index < 0) {
6103 return null;
6104 }
6105 activity = (HistoryRecord)mHistory.get(index);
6106 if (activity.finishing) {
6107 return null;
6108 }
6109 }
6110
6111 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6112 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6113 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6114 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6115 |PendingIntent.FLAG_UPDATE_CURRENT);
6116
6117 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6118 type, packageName, activity, resultWho,
6119 requestCode, intent, resolvedType, flags);
6120 WeakReference<PendingIntentRecord> ref;
6121 ref = mIntentSenderRecords.get(key);
6122 PendingIntentRecord rec = ref != null ? ref.get() : null;
6123 if (rec != null) {
6124 if (!cancelCurrent) {
6125 if (updateCurrent) {
6126 rec.key.requestIntent.replaceExtras(intent);
6127 }
6128 return rec;
6129 }
6130 rec.canceled = true;
6131 mIntentSenderRecords.remove(key);
6132 }
6133 if (noCreate) {
6134 return rec;
6135 }
6136 rec = new PendingIntentRecord(this, key, callingUid);
6137 mIntentSenderRecords.put(key, rec.ref);
6138 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6139 if (activity.pendingResults == null) {
6140 activity.pendingResults
6141 = new HashSet<WeakReference<PendingIntentRecord>>();
6142 }
6143 activity.pendingResults.add(rec.ref);
6144 }
6145 return rec;
6146 }
6147 }
6148
6149 public void cancelIntentSender(IIntentSender sender) {
6150 if (!(sender instanceof PendingIntentRecord)) {
6151 return;
6152 }
6153 synchronized(this) {
6154 PendingIntentRecord rec = (PendingIntentRecord)sender;
6155 try {
6156 int uid = ActivityThread.getPackageManager()
6157 .getPackageUid(rec.key.packageName);
6158 if (uid != Binder.getCallingUid()) {
6159 String msg = "Permission Denial: cancelIntentSender() from pid="
6160 + Binder.getCallingPid()
6161 + ", uid=" + Binder.getCallingUid()
6162 + " is not allowed to cancel packges "
6163 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006164 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006165 throw new SecurityException(msg);
6166 }
6167 } catch (RemoteException e) {
6168 throw new SecurityException(e);
6169 }
6170 cancelIntentSenderLocked(rec, true);
6171 }
6172 }
6173
6174 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6175 rec.canceled = true;
6176 mIntentSenderRecords.remove(rec.key);
6177 if (cleanActivity && rec.key.activity != null) {
6178 rec.key.activity.pendingResults.remove(rec.ref);
6179 }
6180 }
6181
6182 public String getPackageForIntentSender(IIntentSender pendingResult) {
6183 if (!(pendingResult instanceof PendingIntentRecord)) {
6184 return null;
6185 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006186 try {
6187 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6188 return res.key.packageName;
6189 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006190 }
6191 return null;
6192 }
6193
6194 public void setProcessLimit(int max) {
6195 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6196 "setProcessLimit()");
6197 mProcessLimit = max;
6198 }
6199
6200 public int getProcessLimit() {
6201 return mProcessLimit;
6202 }
6203
6204 void foregroundTokenDied(ForegroundToken token) {
6205 synchronized (ActivityManagerService.this) {
6206 synchronized (mPidsSelfLocked) {
6207 ForegroundToken cur
6208 = mForegroundProcesses.get(token.pid);
6209 if (cur != token) {
6210 return;
6211 }
6212 mForegroundProcesses.remove(token.pid);
6213 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6214 if (pr == null) {
6215 return;
6216 }
6217 pr.forcingToForeground = null;
6218 pr.foregroundServices = false;
6219 }
6220 updateOomAdjLocked();
6221 }
6222 }
6223
6224 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6225 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6226 "setProcessForeground()");
6227 synchronized(this) {
6228 boolean changed = false;
6229
6230 synchronized (mPidsSelfLocked) {
6231 ProcessRecord pr = mPidsSelfLocked.get(pid);
6232 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006233 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006234 return;
6235 }
6236 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6237 if (oldToken != null) {
6238 oldToken.token.unlinkToDeath(oldToken, 0);
6239 mForegroundProcesses.remove(pid);
6240 pr.forcingToForeground = null;
6241 changed = true;
6242 }
6243 if (isForeground && token != null) {
6244 ForegroundToken newToken = new ForegroundToken() {
6245 public void binderDied() {
6246 foregroundTokenDied(this);
6247 }
6248 };
6249 newToken.pid = pid;
6250 newToken.token = token;
6251 try {
6252 token.linkToDeath(newToken, 0);
6253 mForegroundProcesses.put(pid, newToken);
6254 pr.forcingToForeground = token;
6255 changed = true;
6256 } catch (RemoteException e) {
6257 // If the process died while doing this, we will later
6258 // do the cleanup with the process death link.
6259 }
6260 }
6261 }
6262
6263 if (changed) {
6264 updateOomAdjLocked();
6265 }
6266 }
6267 }
6268
6269 // =========================================================
6270 // PERMISSIONS
6271 // =========================================================
6272
6273 static class PermissionController extends IPermissionController.Stub {
6274 ActivityManagerService mActivityManagerService;
6275 PermissionController(ActivityManagerService activityManagerService) {
6276 mActivityManagerService = activityManagerService;
6277 }
6278
6279 public boolean checkPermission(String permission, int pid, int uid) {
6280 return mActivityManagerService.checkPermission(permission, pid,
6281 uid) == PackageManager.PERMISSION_GRANTED;
6282 }
6283 }
6284
6285 /**
6286 * This can be called with or without the global lock held.
6287 */
6288 int checkComponentPermission(String permission, int pid, int uid,
6289 int reqUid) {
6290 // We might be performing an operation on behalf of an indirect binder
6291 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6292 // client identity accordingly before proceeding.
6293 Identity tlsIdentity = sCallerIdentity.get();
6294 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006295 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006296 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6297 uid = tlsIdentity.uid;
6298 pid = tlsIdentity.pid;
6299 }
6300
6301 // Root, system server and our own process get to do everything.
6302 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6303 !Process.supportsProcesses()) {
6304 return PackageManager.PERMISSION_GRANTED;
6305 }
6306 // If the target requires a specific UID, always fail for others.
6307 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006308 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006309 return PackageManager.PERMISSION_DENIED;
6310 }
6311 if (permission == null) {
6312 return PackageManager.PERMISSION_GRANTED;
6313 }
6314 try {
6315 return ActivityThread.getPackageManager()
6316 .checkUidPermission(permission, uid);
6317 } catch (RemoteException e) {
6318 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006319 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006320 }
6321 return PackageManager.PERMISSION_DENIED;
6322 }
6323
6324 /**
6325 * As the only public entry point for permissions checking, this method
6326 * can enforce the semantic that requesting a check on a null global
6327 * permission is automatically denied. (Internally a null permission
6328 * string is used when calling {@link #checkComponentPermission} in cases
6329 * when only uid-based security is needed.)
6330 *
6331 * This can be called with or without the global lock held.
6332 */
6333 public int checkPermission(String permission, int pid, int uid) {
6334 if (permission == null) {
6335 return PackageManager.PERMISSION_DENIED;
6336 }
6337 return checkComponentPermission(permission, pid, uid, -1);
6338 }
6339
6340 /**
6341 * Binder IPC calls go through the public entry point.
6342 * This can be called with or without the global lock held.
6343 */
6344 int checkCallingPermission(String permission) {
6345 return checkPermission(permission,
6346 Binder.getCallingPid(),
6347 Binder.getCallingUid());
6348 }
6349
6350 /**
6351 * This can be called with or without the global lock held.
6352 */
6353 void enforceCallingPermission(String permission, String func) {
6354 if (checkCallingPermission(permission)
6355 == PackageManager.PERMISSION_GRANTED) {
6356 return;
6357 }
6358
6359 String msg = "Permission Denial: " + func + " from pid="
6360 + Binder.getCallingPid()
6361 + ", uid=" + Binder.getCallingUid()
6362 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006363 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006364 throw new SecurityException(msg);
6365 }
6366
6367 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6368 ProviderInfo pi, int uid, int modeFlags) {
6369 try {
6370 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6371 if ((pi.readPermission != null) &&
6372 (pm.checkUidPermission(pi.readPermission, uid)
6373 != PackageManager.PERMISSION_GRANTED)) {
6374 return false;
6375 }
6376 }
6377 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6378 if ((pi.writePermission != null) &&
6379 (pm.checkUidPermission(pi.writePermission, uid)
6380 != PackageManager.PERMISSION_GRANTED)) {
6381 return false;
6382 }
6383 }
6384 return true;
6385 } catch (RemoteException e) {
6386 return false;
6387 }
6388 }
6389
6390 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6391 int modeFlags) {
6392 // Root gets to do everything.
6393 if (uid == 0 || !Process.supportsProcesses()) {
6394 return true;
6395 }
6396 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6397 if (perms == null) return false;
6398 UriPermission perm = perms.get(uri);
6399 if (perm == null) return false;
6400 return (modeFlags&perm.modeFlags) == modeFlags;
6401 }
6402
6403 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6404 // Another redirected-binder-call permissions check as in
6405 // {@link checkComponentPermission}.
6406 Identity tlsIdentity = sCallerIdentity.get();
6407 if (tlsIdentity != null) {
6408 uid = tlsIdentity.uid;
6409 pid = tlsIdentity.pid;
6410 }
6411
6412 // Our own process gets to do everything.
6413 if (pid == MY_PID) {
6414 return PackageManager.PERMISSION_GRANTED;
6415 }
6416 synchronized(this) {
6417 return checkUriPermissionLocked(uri, uid, modeFlags)
6418 ? PackageManager.PERMISSION_GRANTED
6419 : PackageManager.PERMISSION_DENIED;
6420 }
6421 }
6422
6423 private void grantUriPermissionLocked(int callingUid,
6424 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6425 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6426 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6427 if (modeFlags == 0) {
6428 return;
6429 }
6430
Joe Onorato8a9b2202010-02-26 18:56:32 -08006431 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006432 "Requested grant " + targetPkg + " permission to " + uri);
6433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006434 final IPackageManager pm = ActivityThread.getPackageManager();
6435
6436 // If this is not a content: uri, we can't do anything with it.
6437 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006438 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006439 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 return;
6441 }
6442
6443 String name = uri.getAuthority();
6444 ProviderInfo pi = null;
6445 ContentProviderRecord cpr
6446 = (ContentProviderRecord)mProvidersByName.get(name);
6447 if (cpr != null) {
6448 pi = cpr.info;
6449 } else {
6450 try {
6451 pi = pm.resolveContentProvider(name,
6452 PackageManager.GET_URI_PERMISSION_PATTERNS);
6453 } catch (RemoteException ex) {
6454 }
6455 }
6456 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006457 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006458 return;
6459 }
6460
6461 int targetUid;
6462 try {
6463 targetUid = pm.getPackageUid(targetPkg);
6464 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006465 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006466 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 return;
6468 }
6469 } catch (RemoteException ex) {
6470 return;
6471 }
6472
6473 // First... does the target actually need this permission?
6474 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6475 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006476 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006477 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006478 return;
6479 }
6480
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006481 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006482 if (!pi.grantUriPermissions) {
6483 throw new SecurityException("Provider " + pi.packageName
6484 + "/" + pi.name
6485 + " does not allow granting of Uri permissions (uri "
6486 + uri + ")");
6487 }
6488 if (pi.uriPermissionPatterns != null) {
6489 final int N = pi.uriPermissionPatterns.length;
6490 boolean allowed = false;
6491 for (int i=0; i<N; i++) {
6492 if (pi.uriPermissionPatterns[i] != null
6493 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6494 allowed = true;
6495 break;
6496 }
6497 }
6498 if (!allowed) {
6499 throw new SecurityException("Provider " + pi.packageName
6500 + "/" + pi.name
6501 + " does not allow granting of permission to path of Uri "
6502 + uri);
6503 }
6504 }
6505
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006506 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006507 // this uri?
6508 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6509 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6510 throw new SecurityException("Uid " + callingUid
6511 + " does not have permission to uri " + uri);
6512 }
6513 }
6514
6515 // Okay! So here we are: the caller has the assumed permission
6516 // to the uri, and the target doesn't. Let's now give this to
6517 // the target.
6518
Joe Onorato8a9b2202010-02-26 18:56:32 -08006519 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006520 "Granting " + targetPkg + " permission to " + uri);
6521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006522 HashMap<Uri, UriPermission> targetUris
6523 = mGrantedUriPermissions.get(targetUid);
6524 if (targetUris == null) {
6525 targetUris = new HashMap<Uri, UriPermission>();
6526 mGrantedUriPermissions.put(targetUid, targetUris);
6527 }
6528
6529 UriPermission perm = targetUris.get(uri);
6530 if (perm == null) {
6531 perm = new UriPermission(targetUid, uri);
6532 targetUris.put(uri, perm);
6533
6534 }
6535 perm.modeFlags |= modeFlags;
6536 if (activity == null) {
6537 perm.globalModeFlags |= modeFlags;
6538 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6539 perm.readActivities.add(activity);
6540 if (activity.readUriPermissions == null) {
6541 activity.readUriPermissions = new HashSet<UriPermission>();
6542 }
6543 activity.readUriPermissions.add(perm);
6544 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6545 perm.writeActivities.add(activity);
6546 if (activity.writeUriPermissions == null) {
6547 activity.writeUriPermissions = new HashSet<UriPermission>();
6548 }
6549 activity.writeUriPermissions.add(perm);
6550 }
6551 }
6552
6553 private void grantUriPermissionFromIntentLocked(int callingUid,
6554 String targetPkg, Intent intent, HistoryRecord activity) {
6555 if (intent == null) {
6556 return;
6557 }
6558 Uri data = intent.getData();
6559 if (data == null) {
6560 return;
6561 }
6562 grantUriPermissionLocked(callingUid, targetPkg, data,
6563 intent.getFlags(), activity);
6564 }
6565
6566 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6567 Uri uri, int modeFlags) {
6568 synchronized(this) {
6569 final ProcessRecord r = getRecordForAppLocked(caller);
6570 if (r == null) {
6571 throw new SecurityException("Unable to find app for caller "
6572 + caller
6573 + " when granting permission to uri " + uri);
6574 }
6575 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006576 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006577 return;
6578 }
6579 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006580 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006581 return;
6582 }
6583
6584 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6585 null);
6586 }
6587 }
6588
6589 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6590 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6591 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6592 HashMap<Uri, UriPermission> perms
6593 = mGrantedUriPermissions.get(perm.uid);
6594 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006595 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006596 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006597 perms.remove(perm.uri);
6598 if (perms.size() == 0) {
6599 mGrantedUriPermissions.remove(perm.uid);
6600 }
6601 }
6602 }
6603 }
6604
6605 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6606 if (activity.readUriPermissions != null) {
6607 for (UriPermission perm : activity.readUriPermissions) {
6608 perm.readActivities.remove(activity);
6609 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6610 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6611 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6612 removeUriPermissionIfNeededLocked(perm);
6613 }
6614 }
6615 }
6616 if (activity.writeUriPermissions != null) {
6617 for (UriPermission perm : activity.writeUriPermissions) {
6618 perm.writeActivities.remove(activity);
6619 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6620 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6621 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6622 removeUriPermissionIfNeededLocked(perm);
6623 }
6624 }
6625 }
6626 }
6627
6628 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6629 int modeFlags) {
6630 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6631 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6632 if (modeFlags == 0) {
6633 return;
6634 }
6635
Joe Onorato8a9b2202010-02-26 18:56:32 -08006636 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006637 "Revoking all granted permissions to " + uri);
6638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006639 final IPackageManager pm = ActivityThread.getPackageManager();
6640
6641 final String authority = uri.getAuthority();
6642 ProviderInfo pi = null;
6643 ContentProviderRecord cpr
6644 = (ContentProviderRecord)mProvidersByName.get(authority);
6645 if (cpr != null) {
6646 pi = cpr.info;
6647 } else {
6648 try {
6649 pi = pm.resolveContentProvider(authority,
6650 PackageManager.GET_URI_PERMISSION_PATTERNS);
6651 } catch (RemoteException ex) {
6652 }
6653 }
6654 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006655 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006656 return;
6657 }
6658
6659 // Does the caller have this permission on the URI?
6660 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6661 // Right now, if you are not the original owner of the permission,
6662 // you are not allowed to revoke it.
6663 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6664 throw new SecurityException("Uid " + callingUid
6665 + " does not have permission to uri " + uri);
6666 //}
6667 }
6668
6669 // Go through all of the permissions and remove any that match.
6670 final List<String> SEGMENTS = uri.getPathSegments();
6671 if (SEGMENTS != null) {
6672 final int NS = SEGMENTS.size();
6673 int N = mGrantedUriPermissions.size();
6674 for (int i=0; i<N; i++) {
6675 HashMap<Uri, UriPermission> perms
6676 = mGrantedUriPermissions.valueAt(i);
6677 Iterator<UriPermission> it = perms.values().iterator();
6678 toploop:
6679 while (it.hasNext()) {
6680 UriPermission perm = it.next();
6681 Uri targetUri = perm.uri;
6682 if (!authority.equals(targetUri.getAuthority())) {
6683 continue;
6684 }
6685 List<String> targetSegments = targetUri.getPathSegments();
6686 if (targetSegments == null) {
6687 continue;
6688 }
6689 if (targetSegments.size() < NS) {
6690 continue;
6691 }
6692 for (int j=0; j<NS; j++) {
6693 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6694 continue toploop;
6695 }
6696 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006697 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006698 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 perm.clearModes(modeFlags);
6700 if (perm.modeFlags == 0) {
6701 it.remove();
6702 }
6703 }
6704 if (perms.size() == 0) {
6705 mGrantedUriPermissions.remove(
6706 mGrantedUriPermissions.keyAt(i));
6707 N--;
6708 i--;
6709 }
6710 }
6711 }
6712 }
6713
6714 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6715 int modeFlags) {
6716 synchronized(this) {
6717 final ProcessRecord r = getRecordForAppLocked(caller);
6718 if (r == null) {
6719 throw new SecurityException("Unable to find app for caller "
6720 + caller
6721 + " when revoking permission to uri " + uri);
6722 }
6723 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006724 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006725 return;
6726 }
6727
6728 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6729 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6730 if (modeFlags == 0) {
6731 return;
6732 }
6733
6734 final IPackageManager pm = ActivityThread.getPackageManager();
6735
6736 final String authority = uri.getAuthority();
6737 ProviderInfo pi = null;
6738 ContentProviderRecord cpr
6739 = (ContentProviderRecord)mProvidersByName.get(authority);
6740 if (cpr != null) {
6741 pi = cpr.info;
6742 } else {
6743 try {
6744 pi = pm.resolveContentProvider(authority,
6745 PackageManager.GET_URI_PERMISSION_PATTERNS);
6746 } catch (RemoteException ex) {
6747 }
6748 }
6749 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006750 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006751 return;
6752 }
6753
6754 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6755 }
6756 }
6757
6758 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6759 synchronized (this) {
6760 ProcessRecord app =
6761 who != null ? getRecordForAppLocked(who) : null;
6762 if (app == null) return;
6763
6764 Message msg = Message.obtain();
6765 msg.what = WAIT_FOR_DEBUGGER_MSG;
6766 msg.obj = app;
6767 msg.arg1 = waiting ? 1 : 0;
6768 mHandler.sendMessage(msg);
6769 }
6770 }
6771
6772 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6773 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006774 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006775 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006776 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006777 }
6778
6779 // =========================================================
6780 // TASK MANAGEMENT
6781 // =========================================================
6782
6783 public List getTasks(int maxNum, int flags,
6784 IThumbnailReceiver receiver) {
6785 ArrayList list = new ArrayList();
6786
6787 PendingThumbnailsRecord pending = null;
6788 IApplicationThread topThumbnail = null;
6789 HistoryRecord topRecord = null;
6790
6791 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006792 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006793 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
6794 + ", receiver=" + receiver);
6795
6796 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
6797 != PackageManager.PERMISSION_GRANTED) {
6798 if (receiver != null) {
6799 // If the caller wants to wait for pending thumbnails,
6800 // it ain't gonna get them.
6801 try {
6802 receiver.finished();
6803 } catch (RemoteException ex) {
6804 }
6805 }
6806 String msg = "Permission Denial: getTasks() from pid="
6807 + Binder.getCallingPid()
6808 + ", uid=" + Binder.getCallingUid()
6809 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006810 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006811 throw new SecurityException(msg);
6812 }
6813
6814 int pos = mHistory.size()-1;
6815 HistoryRecord next =
6816 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6817 HistoryRecord top = null;
6818 CharSequence topDescription = null;
6819 TaskRecord curTask = null;
6820 int numActivities = 0;
6821 int numRunning = 0;
6822 while (pos >= 0 && maxNum > 0) {
6823 final HistoryRecord r = next;
6824 pos--;
6825 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
6826
6827 // Initialize state for next task if needed.
6828 if (top == null ||
6829 (top.state == ActivityState.INITIALIZING
6830 && top.task == r.task)) {
6831 top = r;
6832 topDescription = r.description;
6833 curTask = r.task;
6834 numActivities = numRunning = 0;
6835 }
6836
6837 // Add 'r' into the current task.
6838 numActivities++;
6839 if (r.app != null && r.app.thread != null) {
6840 numRunning++;
6841 }
6842 if (topDescription == null) {
6843 topDescription = r.description;
6844 }
6845
Joe Onorato8a9b2202010-02-26 18:56:32 -08006846 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006847 TAG, r.intent.getComponent().flattenToShortString()
6848 + ": task=" + r.task);
6849
6850 // If the next one is a different task, generate a new
6851 // TaskInfo entry for what we have.
6852 if (next == null || next.task != curTask) {
6853 ActivityManager.RunningTaskInfo ci
6854 = new ActivityManager.RunningTaskInfo();
6855 ci.id = curTask.taskId;
6856 ci.baseActivity = r.intent.getComponent();
6857 ci.topActivity = top.intent.getComponent();
6858 ci.thumbnail = top.thumbnail;
6859 ci.description = topDescription;
6860 ci.numActivities = numActivities;
6861 ci.numRunning = numRunning;
6862 //System.out.println(
6863 // "#" + maxNum + ": " + " descr=" + ci.description);
6864 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006865 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006866 TAG, "State=" + top.state + "Idle=" + top.idle
6867 + " app=" + top.app
6868 + " thr=" + (top.app != null ? top.app.thread : null));
6869 if (top.state == ActivityState.RESUMED
6870 || top.state == ActivityState.PAUSING) {
6871 if (top.idle && top.app != null
6872 && top.app.thread != null) {
6873 topRecord = top;
6874 topThumbnail = top.app.thread;
6875 } else {
6876 top.thumbnailNeeded = true;
6877 }
6878 }
6879 if (pending == null) {
6880 pending = new PendingThumbnailsRecord(receiver);
6881 }
6882 pending.pendingRecords.add(top);
6883 }
6884 list.add(ci);
6885 maxNum--;
6886 top = null;
6887 }
6888 }
6889
6890 if (pending != null) {
6891 mPendingThumbnails.add(pending);
6892 }
6893 }
6894
Joe Onorato8a9b2202010-02-26 18:56:32 -08006895 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006896
6897 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006898 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006899 try {
6900 topThumbnail.requestThumbnail(topRecord);
6901 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006902 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006903 sendPendingThumbnail(null, topRecord, null, null, true);
6904 }
6905 }
6906
6907 if (pending == null && receiver != null) {
6908 // In this case all thumbnails were available and the client
6909 // is being asked to be told when the remaining ones come in...
6910 // which is unusually, since the top-most currently running
6911 // activity should never have a canned thumbnail! Oh well.
6912 try {
6913 receiver.finished();
6914 } catch (RemoteException ex) {
6915 }
6916 }
6917
6918 return list;
6919 }
6920
6921 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
6922 int flags) {
6923 synchronized (this) {
6924 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
6925 "getRecentTasks()");
6926
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006927 IPackageManager pm = ActivityThread.getPackageManager();
6928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006929 final int N = mRecentTasks.size();
6930 ArrayList<ActivityManager.RecentTaskInfo> res
6931 = new ArrayList<ActivityManager.RecentTaskInfo>(
6932 maxNum < N ? maxNum : N);
6933 for (int i=0; i<N && maxNum > 0; i++) {
6934 TaskRecord tr = mRecentTasks.get(i);
6935 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
6936 || (tr.intent == null)
6937 || ((tr.intent.getFlags()
6938 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
6939 ActivityManager.RecentTaskInfo rti
6940 = new ActivityManager.RecentTaskInfo();
6941 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
6942 rti.baseIntent = new Intent(
6943 tr.intent != null ? tr.intent : tr.affinityIntent);
6944 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07006945
6946 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
6947 // Check whether this activity is currently available.
6948 try {
6949 if (rti.origActivity != null) {
6950 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
6951 continue;
6952 }
6953 } else if (rti.baseIntent != null) {
6954 if (pm.queryIntentActivities(rti.baseIntent,
6955 null, 0) == null) {
6956 continue;
6957 }
6958 }
6959 } catch (RemoteException e) {
6960 // Will never happen.
6961 }
6962 }
6963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006964 res.add(rti);
6965 maxNum--;
6966 }
6967 }
6968 return res;
6969 }
6970 }
6971
6972 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
6973 int j;
6974 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
6975 TaskRecord jt = startTask;
6976
6977 // First look backwards
6978 for (j=startIndex-1; j>=0; j--) {
6979 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6980 if (r.task != jt) {
6981 jt = r.task;
6982 if (affinity.equals(jt.affinity)) {
6983 return j;
6984 }
6985 }
6986 }
6987
6988 // Now look forwards
6989 final int N = mHistory.size();
6990 jt = startTask;
6991 for (j=startIndex+1; j<N; j++) {
6992 HistoryRecord r = (HistoryRecord)mHistory.get(j);
6993 if (r.task != jt) {
6994 if (affinity.equals(jt.affinity)) {
6995 return j;
6996 }
6997 jt = r.task;
6998 }
6999 }
7000
7001 // Might it be at the top?
7002 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
7003 return N-1;
7004 }
7005
7006 return -1;
7007 }
7008
7009 /**
7010 * Perform a reset of the given task, if needed as part of launching it.
7011 * Returns the new HistoryRecord at the top of the task.
7012 */
7013 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
7014 HistoryRecord newActivity) {
7015 boolean forceReset = (newActivity.info.flags
7016 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
7017 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
7018 if ((newActivity.info.flags
7019 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
7020 forceReset = true;
7021 }
7022 }
7023
7024 final TaskRecord task = taskTop.task;
7025
7026 // We are going to move through the history list so that we can look
7027 // at each activity 'target' with 'below' either the interesting
7028 // activity immediately below it in the stack or null.
7029 HistoryRecord target = null;
7030 int targetI = 0;
7031 int taskTopI = -1;
7032 int replyChainEnd = -1;
7033 int lastReparentPos = -1;
7034 for (int i=mHistory.size()-1; i>=-1; i--) {
7035 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
7036
7037 if (below != null && below.finishing) {
7038 continue;
7039 }
7040 if (target == null) {
7041 target = below;
7042 targetI = i;
7043 // If we were in the middle of a reply chain before this
7044 // task, it doesn't appear like the root of the chain wants
7045 // anything interesting, so drop it.
7046 replyChainEnd = -1;
7047 continue;
7048 }
7049
7050 final int flags = target.info.flags;
7051
7052 final boolean finishOnTaskLaunch =
7053 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7054 final boolean allowTaskReparenting =
7055 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7056
7057 if (target.task == task) {
7058 // We are inside of the task being reset... we'll either
7059 // finish this activity, push it out for another task,
7060 // or leave it as-is. We only do this
7061 // for activities that are not the root of the task (since
7062 // if we finish the root, we may no longer have the task!).
7063 if (taskTopI < 0) {
7064 taskTopI = targetI;
7065 }
7066 if (below != null && below.task == task) {
7067 final boolean clearWhenTaskReset =
7068 (target.intent.getFlags()
7069 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007070 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007071 // If this activity is sending a reply to a previous
7072 // activity, we can't do anything with it now until
7073 // we reach the start of the reply chain.
7074 // XXX note that we are assuming the result is always
7075 // to the previous activity, which is almost always
7076 // the case but we really shouldn't count on.
7077 if (replyChainEnd < 0) {
7078 replyChainEnd = targetI;
7079 }
Ed Heyl73798232009-03-24 21:32:21 -07007080 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007081 && target.taskAffinity != null
7082 && !target.taskAffinity.equals(task.affinity)) {
7083 // If this activity has an affinity for another
7084 // task, then we need to move it out of here. We will
7085 // move it as far out of the way as possible, to the
7086 // bottom of the activity stack. This also keeps it
7087 // correctly ordered with any activities we previously
7088 // moved.
7089 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7090 if (target.taskAffinity != null
7091 && target.taskAffinity.equals(p.task.affinity)) {
7092 // If the activity currently at the bottom has the
7093 // same task affinity as the one we are moving,
7094 // then merge it into the same task.
7095 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007096 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007097 + " out to bottom task " + p.task);
7098 } else {
7099 mCurTask++;
7100 if (mCurTask <= 0) {
7101 mCurTask = 1;
7102 }
7103 target.task = new TaskRecord(mCurTask, target.info, null,
7104 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7105 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007106 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007107 + " out to new task " + target.task);
7108 }
7109 mWindowManager.setAppGroupId(target, task.taskId);
7110 if (replyChainEnd < 0) {
7111 replyChainEnd = targetI;
7112 }
7113 int dstPos = 0;
7114 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7115 p = (HistoryRecord)mHistory.get(srcPos);
7116 if (p.finishing) {
7117 continue;
7118 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007119 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007120 + " out to target's task " + target.task);
7121 task.numActivities--;
7122 p.task = target.task;
7123 target.task.numActivities++;
7124 mHistory.remove(srcPos);
7125 mHistory.add(dstPos, p);
7126 mWindowManager.moveAppToken(dstPos, p);
7127 mWindowManager.setAppGroupId(p, p.task.taskId);
7128 dstPos++;
7129 if (VALIDATE_TOKENS) {
7130 mWindowManager.validateAppTokens(mHistory);
7131 }
7132 i++;
7133 }
7134 if (taskTop == p) {
7135 taskTop = below;
7136 }
7137 if (taskTopI == replyChainEnd) {
7138 taskTopI = -1;
7139 }
7140 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007141 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 } else if (forceReset || finishOnTaskLaunch
7143 || clearWhenTaskReset) {
7144 // If the activity should just be removed -- either
7145 // because it asks for it, or the task should be
7146 // cleared -- then finish it and anything that is
7147 // part of its reply chain.
7148 if (clearWhenTaskReset) {
7149 // In this case, we want to finish this activity
7150 // and everything above it, so be sneaky and pretend
7151 // like these are all in the reply chain.
7152 replyChainEnd = targetI+1;
7153 while (replyChainEnd < mHistory.size() &&
7154 ((HistoryRecord)mHistory.get(
7155 replyChainEnd)).task == task) {
7156 replyChainEnd++;
7157 }
7158 replyChainEnd--;
7159 } else if (replyChainEnd < 0) {
7160 replyChainEnd = targetI;
7161 }
7162 HistoryRecord p = null;
7163 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7164 p = (HistoryRecord)mHistory.get(srcPos);
7165 if (p.finishing) {
7166 continue;
7167 }
7168 if (finishActivityLocked(p, srcPos,
7169 Activity.RESULT_CANCELED, null, "reset")) {
7170 replyChainEnd--;
7171 srcPos--;
7172 }
7173 }
7174 if (taskTop == p) {
7175 taskTop = below;
7176 }
7177 if (taskTopI == replyChainEnd) {
7178 taskTopI = -1;
7179 }
7180 replyChainEnd = -1;
7181 } else {
7182 // If we were in the middle of a chain, well the
7183 // activity that started it all doesn't want anything
7184 // special, so leave it all as-is.
7185 replyChainEnd = -1;
7186 }
7187 } else {
7188 // Reached the bottom of the task -- any reply chain
7189 // should be left as-is.
7190 replyChainEnd = -1;
7191 }
7192
7193 } else if (target.resultTo != null) {
7194 // If this activity is sending a reply to a previous
7195 // activity, we can't do anything with it now until
7196 // we reach the start of the reply chain.
7197 // XXX note that we are assuming the result is always
7198 // to the previous activity, which is almost always
7199 // the case but we really shouldn't count on.
7200 if (replyChainEnd < 0) {
7201 replyChainEnd = targetI;
7202 }
7203
7204 } else if (taskTopI >= 0 && allowTaskReparenting
7205 && task.affinity != null
7206 && task.affinity.equals(target.taskAffinity)) {
7207 // We are inside of another task... if this activity has
7208 // an affinity for our task, then either remove it if we are
7209 // clearing or move it over to our task. Note that
7210 // we currently punt on the case where we are resetting a
7211 // task that is not at the top but who has activities above
7212 // with an affinity to it... this is really not a normal
7213 // case, and we will need to later pull that task to the front
7214 // and usually at that point we will do the reset and pick
7215 // up those remaining activities. (This only happens if
7216 // someone starts an activity in a new task from an activity
7217 // in a task that is not currently on top.)
7218 if (forceReset || finishOnTaskLaunch) {
7219 if (replyChainEnd < 0) {
7220 replyChainEnd = targetI;
7221 }
7222 HistoryRecord p = null;
7223 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7224 p = (HistoryRecord)mHistory.get(srcPos);
7225 if (p.finishing) {
7226 continue;
7227 }
7228 if (finishActivityLocked(p, srcPos,
7229 Activity.RESULT_CANCELED, null, "reset")) {
7230 taskTopI--;
7231 lastReparentPos--;
7232 replyChainEnd--;
7233 srcPos--;
7234 }
7235 }
7236 replyChainEnd = -1;
7237 } else {
7238 if (replyChainEnd < 0) {
7239 replyChainEnd = targetI;
7240 }
7241 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7242 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7243 if (p.finishing) {
7244 continue;
7245 }
7246 if (lastReparentPos < 0) {
7247 lastReparentPos = taskTopI;
7248 taskTop = p;
7249 } else {
7250 lastReparentPos--;
7251 }
7252 mHistory.remove(srcPos);
7253 p.task.numActivities--;
7254 p.task = task;
7255 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007256 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007257 + " in to resetting task " + task);
7258 task.numActivities++;
7259 mWindowManager.moveAppToken(lastReparentPos, p);
7260 mWindowManager.setAppGroupId(p, p.task.taskId);
7261 if (VALIDATE_TOKENS) {
7262 mWindowManager.validateAppTokens(mHistory);
7263 }
7264 }
7265 replyChainEnd = -1;
7266
7267 // Now we've moved it in to place... but what if this is
7268 // a singleTop activity and we have put it on top of another
7269 // instance of the same activity? Then we drop the instance
7270 // below so it remains singleTop.
7271 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7272 for (int j=lastReparentPos-1; j>=0; j--) {
7273 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7274 if (p.finishing) {
7275 continue;
7276 }
7277 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7278 if (finishActivityLocked(p, j,
7279 Activity.RESULT_CANCELED, null, "replace")) {
7280 taskTopI--;
7281 lastReparentPos--;
7282 }
7283 }
7284 }
7285 }
7286 }
7287 }
7288
7289 target = below;
7290 targetI = i;
7291 }
7292
7293 return taskTop;
7294 }
7295
7296 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007297 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007298 */
7299 public void moveTaskToFront(int task) {
7300 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7301 "moveTaskToFront()");
7302
7303 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007304 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7305 Binder.getCallingUid(), "Task to front")) {
7306 return;
7307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 final long origId = Binder.clearCallingIdentity();
7309 try {
7310 int N = mRecentTasks.size();
7311 for (int i=0; i<N; i++) {
7312 TaskRecord tr = mRecentTasks.get(i);
7313 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007314 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007315 return;
7316 }
7317 }
7318 for (int i=mHistory.size()-1; i>=0; i--) {
7319 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7320 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007321 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007322 return;
7323 }
7324 }
7325 } finally {
7326 Binder.restoreCallingIdentity(origId);
7327 }
7328 }
7329 }
7330
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007331 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007332 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007333
7334 final int task = tr.taskId;
7335 int top = mHistory.size()-1;
7336
7337 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7338 // nothing to do!
7339 return;
7340 }
7341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342 ArrayList moved = new ArrayList();
7343
7344 // Applying the affinities may have removed entries from the history,
7345 // so get the size again.
7346 top = mHistory.size()-1;
7347 int pos = top;
7348
7349 // Shift all activities with this task up to the top
7350 // of the stack, keeping them in the same internal order.
7351 while (pos >= 0) {
7352 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007353 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007354 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7355 boolean first = true;
7356 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007357 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007358 mHistory.remove(pos);
7359 mHistory.add(top, r);
7360 moved.add(0, r);
7361 top--;
7362 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007363 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007364 first = false;
7365 }
7366 }
7367 pos--;
7368 }
7369
Joe Onorato8a9b2202010-02-26 18:56:32 -08007370 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007371 "Prepare to front transition: task=" + tr);
7372 if (reason != null &&
7373 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7374 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7375 HistoryRecord r = topRunningActivityLocked(null);
7376 if (r != null) {
7377 mNoAnimActivities.add(r);
7378 }
7379 } else {
7380 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7381 }
7382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007383 mWindowManager.moveAppTokensToTop(moved);
7384 if (VALIDATE_TOKENS) {
7385 mWindowManager.validateAppTokens(mHistory);
7386 }
7387
Josh Bartel7f208742010-02-25 11:01:44 -06007388 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007389 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 }
7391
Josh Bartel7f208742010-02-25 11:01:44 -06007392 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007393 resumeTopActivityLocked(null);
7394 }
7395
7396 public void moveTaskToBack(int task) {
7397 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7398 "moveTaskToBack()");
7399
7400 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007401 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7402 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7403 Binder.getCallingUid(), "Task to back")) {
7404 return;
7405 }
7406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007407 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007408 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409 Binder.restoreCallingIdentity(origId);
7410 }
7411 }
7412
7413 /**
7414 * Moves an activity, and all of the other activities within the same task, to the bottom
7415 * of the history stack. The activity's order within the task is unchanged.
7416 *
7417 * @param token A reference to the activity we wish to move
7418 * @param nonRoot If false then this only works if the activity is the root
7419 * of a task; if true it will work for any activity in a task.
7420 * @return Returns true if the move completed, false if not.
7421 */
7422 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7423 synchronized(this) {
7424 final long origId = Binder.clearCallingIdentity();
7425 int taskId = getTaskForActivityLocked(token, !nonRoot);
7426 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007427 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007428 }
7429 Binder.restoreCallingIdentity(origId);
7430 }
7431 return false;
7432 }
7433
7434 /**
7435 * Worker method for rearranging history stack. Implements the function of moving all
7436 * activities for a specific task (gathering them if disjoint) into a single group at the
7437 * bottom of the stack.
7438 *
7439 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7440 * to premeptively cancel the move.
7441 *
7442 * @param task The taskId to collect and move to the bottom.
7443 * @return Returns true if the move completed, false if not.
7444 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007445 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007446 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007447
7448 // If we have a watcher, preflight the move before committing to it. First check
7449 // for *other* available tasks, but if none are available, then try again allowing the
7450 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007451 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007452 HistoryRecord next = topRunningActivityLocked(null, task);
7453 if (next == null) {
7454 next = topRunningActivityLocked(null, 0);
7455 }
7456 if (next != null) {
7457 // ask watcher if this is allowed
7458 boolean moveOK = true;
7459 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007460 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007462 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007463 }
7464 if (!moveOK) {
7465 return false;
7466 }
7467 }
7468 }
7469
7470 ArrayList moved = new ArrayList();
7471
Joe Onorato8a9b2202010-02-26 18:56:32 -08007472 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007473 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007474
7475 final int N = mHistory.size();
7476 int bottom = 0;
7477 int pos = 0;
7478
7479 // Shift all activities with this task down to the bottom
7480 // of the stack, keeping them in the same internal order.
7481 while (pos < N) {
7482 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007483 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007484 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7485 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007486 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487 mHistory.remove(pos);
7488 mHistory.add(bottom, r);
7489 moved.add(r);
7490 bottom++;
7491 }
7492 pos++;
7493 }
7494
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007495 if (reason != null &&
7496 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7497 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7498 HistoryRecord r = topRunningActivityLocked(null);
7499 if (r != null) {
7500 mNoAnimActivities.add(r);
7501 }
7502 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007503 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007505 mWindowManager.moveAppTokensToBottom(moved);
7506 if (VALIDATE_TOKENS) {
7507 mWindowManager.validateAppTokens(mHistory);
7508 }
7509
Josh Bartel7f208742010-02-25 11:01:44 -06007510 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007511 return true;
7512 }
7513
7514 public void moveTaskBackwards(int task) {
7515 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7516 "moveTaskBackwards()");
7517
7518 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007519 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7520 Binder.getCallingUid(), "Task backwards")) {
7521 return;
7522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 final long origId = Binder.clearCallingIdentity();
7524 moveTaskBackwardsLocked(task);
7525 Binder.restoreCallingIdentity(origId);
7526 }
7527 }
7528
7529 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007530 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007531 }
7532
7533 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7534 synchronized(this) {
7535 return getTaskForActivityLocked(token, onlyRoot);
7536 }
7537 }
7538
7539 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7540 final int N = mHistory.size();
7541 TaskRecord lastTask = null;
7542 for (int i=0; i<N; i++) {
7543 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7544 if (r == token) {
7545 if (!onlyRoot || lastTask != r.task) {
7546 return r.task.taskId;
7547 }
7548 return -1;
7549 }
7550 lastTask = r.task;
7551 }
7552
7553 return -1;
7554 }
7555
7556 /**
7557 * Returns the top activity in any existing task matching the given
7558 * Intent. Returns null if no such task is found.
7559 */
7560 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7561 ComponentName cls = intent.getComponent();
7562 if (info.targetActivity != null) {
7563 cls = new ComponentName(info.packageName, info.targetActivity);
7564 }
7565
7566 TaskRecord cp = null;
7567
7568 final int N = mHistory.size();
7569 for (int i=(N-1); i>=0; i--) {
7570 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7571 if (!r.finishing && r.task != cp
7572 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7573 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007574 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007575 // + "/aff=" + r.task.affinity + " to new cls="
7576 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7577 if (r.task.affinity != null) {
7578 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007579 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 return r;
7581 }
7582 } else if (r.task.intent != null
7583 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007584 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007585 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007586 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007587 return r;
7588 } else if (r.task.affinityIntent != null
7589 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007590 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007592 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007593 return r;
7594 }
7595 }
7596 }
7597
7598 return null;
7599 }
7600
7601 /**
7602 * Returns the first activity (starting from the top of the stack) that
7603 * is the same as the given activity. Returns null if no such activity
7604 * is found.
7605 */
7606 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7607 ComponentName cls = intent.getComponent();
7608 if (info.targetActivity != null) {
7609 cls = new ComponentName(info.packageName, info.targetActivity);
7610 }
7611
7612 final int N = mHistory.size();
7613 for (int i=(N-1); i>=0; i--) {
7614 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7615 if (!r.finishing) {
7616 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007617 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007618 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007619 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007620 return r;
7621 }
7622 }
7623 }
7624
7625 return null;
7626 }
7627
7628 public void finishOtherInstances(IBinder token, ComponentName className) {
7629 synchronized(this) {
7630 final long origId = Binder.clearCallingIdentity();
7631
7632 int N = mHistory.size();
7633 TaskRecord lastTask = null;
7634 for (int i=0; i<N; i++) {
7635 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7636 if (r.realActivity.equals(className)
7637 && r != token && lastTask != r.task) {
7638 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7639 null, "others")) {
7640 i--;
7641 N--;
7642 }
7643 }
7644 lastTask = r.task;
7645 }
7646
7647 Binder.restoreCallingIdentity(origId);
7648 }
7649 }
7650
7651 // =========================================================
7652 // THUMBNAILS
7653 // =========================================================
7654
7655 public void reportThumbnail(IBinder token,
7656 Bitmap thumbnail, CharSequence description) {
7657 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7658 final long origId = Binder.clearCallingIdentity();
7659 sendPendingThumbnail(null, token, thumbnail, description, true);
7660 Binder.restoreCallingIdentity(origId);
7661 }
7662
7663 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7664 Bitmap thumbnail, CharSequence description, boolean always) {
7665 TaskRecord task = null;
7666 ArrayList receivers = null;
7667
7668 //System.out.println("Send pending thumbnail: " + r);
7669
7670 synchronized(this) {
7671 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007672 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 if (index < 0) {
7674 return;
7675 }
7676 r = (HistoryRecord)mHistory.get(index);
7677 }
7678 if (thumbnail == null) {
7679 thumbnail = r.thumbnail;
7680 description = r.description;
7681 }
7682 if (thumbnail == null && !always) {
7683 // If there is no thumbnail, and this entry is not actually
7684 // going away, then abort for now and pick up the next
7685 // thumbnail we get.
7686 return;
7687 }
7688 task = r.task;
7689
7690 int N = mPendingThumbnails.size();
7691 int i=0;
7692 while (i<N) {
7693 PendingThumbnailsRecord pr =
7694 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7695 //System.out.println("Looking in " + pr.pendingRecords);
7696 if (pr.pendingRecords.remove(r)) {
7697 if (receivers == null) {
7698 receivers = new ArrayList();
7699 }
7700 receivers.add(pr);
7701 if (pr.pendingRecords.size() == 0) {
7702 pr.finished = true;
7703 mPendingThumbnails.remove(i);
7704 N--;
7705 continue;
7706 }
7707 }
7708 i++;
7709 }
7710 }
7711
7712 if (receivers != null) {
7713 final int N = receivers.size();
7714 for (int i=0; i<N; i++) {
7715 try {
7716 PendingThumbnailsRecord pr =
7717 (PendingThumbnailsRecord)receivers.get(i);
7718 pr.receiver.newThumbnail(
7719 task != null ? task.taskId : -1, thumbnail, description);
7720 if (pr.finished) {
7721 pr.receiver.finished();
7722 }
7723 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007724 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007725 }
7726 }
7727 }
7728 }
7729
7730 // =========================================================
7731 // CONTENT PROVIDERS
7732 // =========================================================
7733
7734 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7735 List providers = null;
7736 try {
7737 providers = ActivityThread.getPackageManager().
7738 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007739 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007740 } catch (RemoteException ex) {
7741 }
7742 if (providers != null) {
7743 final int N = providers.size();
7744 for (int i=0; i<N; i++) {
7745 ProviderInfo cpi =
7746 (ProviderInfo)providers.get(i);
7747 ContentProviderRecord cpr =
7748 (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7749 if (cpr == null) {
7750 cpr = new ContentProviderRecord(cpi, app.info);
7751 mProvidersByClass.put(cpi.name, cpr);
7752 }
7753 app.pubProviders.put(cpi.name, cpr);
7754 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007755 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007756 }
7757 }
7758 return providers;
7759 }
7760
7761 private final String checkContentProviderPermissionLocked(
7762 ProviderInfo cpi, ProcessRecord r, int mode) {
7763 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7764 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7765 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7766 cpi.exported ? -1 : cpi.applicationInfo.uid)
7767 == PackageManager.PERMISSION_GRANTED
7768 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7769 return null;
7770 }
7771 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7772 cpi.exported ? -1 : cpi.applicationInfo.uid)
7773 == PackageManager.PERMISSION_GRANTED) {
7774 return null;
7775 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007776
7777 PathPermission[] pps = cpi.pathPermissions;
7778 if (pps != null) {
7779 int i = pps.length;
7780 while (i > 0) {
7781 i--;
7782 PathPermission pp = pps[i];
7783 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
7784 cpi.exported ? -1 : cpi.applicationInfo.uid)
7785 == PackageManager.PERMISSION_GRANTED
7786 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7787 return null;
7788 }
7789 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
7790 cpi.exported ? -1 : cpi.applicationInfo.uid)
7791 == PackageManager.PERMISSION_GRANTED) {
7792 return null;
7793 }
7794 }
7795 }
7796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 String msg = "Permission Denial: opening provider " + cpi.name
7798 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
7799 + ", uid=" + callingUid + ") requires "
7800 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007801 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007802 return msg;
7803 }
7804
7805 private final ContentProviderHolder getContentProviderImpl(
7806 IApplicationThread caller, String name) {
7807 ContentProviderRecord cpr;
7808 ProviderInfo cpi = null;
7809
7810 synchronized(this) {
7811 ProcessRecord r = null;
7812 if (caller != null) {
7813 r = getRecordForAppLocked(caller);
7814 if (r == null) {
7815 throw new SecurityException(
7816 "Unable to find app for caller " + caller
7817 + " (pid=" + Binder.getCallingPid()
7818 + ") when getting content provider " + name);
7819 }
7820 }
7821
7822 // First check if this content provider has been published...
7823 cpr = (ContentProviderRecord)mProvidersByName.get(name);
7824 if (cpr != null) {
7825 cpi = cpr.info;
7826 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7827 return new ContentProviderHolder(cpi,
7828 cpi.readPermission != null
7829 ? cpi.readPermission : cpi.writePermission);
7830 }
7831
7832 if (r != null && cpr.canRunHere(r)) {
7833 // This provider has been published or is in the process
7834 // of being published... but it is also allowed to run
7835 // in the caller's process, so don't make a connection
7836 // and just let the caller instantiate its own instance.
7837 if (cpr.provider != null) {
7838 // don't give caller the provider object, it needs
7839 // to make its own.
7840 cpr = new ContentProviderRecord(cpr);
7841 }
7842 return cpr;
7843 }
7844
7845 final long origId = Binder.clearCallingIdentity();
7846
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007847 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007848 // return it right away.
7849 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007850 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007851 "Adding provider requested by "
7852 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007853 + cpr.info.processName);
7854 Integer cnt = r.conProviders.get(cpr);
7855 if (cnt == null) {
7856 r.conProviders.put(cpr, new Integer(1));
7857 } else {
7858 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007860 cpr.clients.add(r);
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07007861 if (cpr.app != null && r.setAdj >= VISIBLE_APP_ADJ) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07007862 // If this is a visible app accessing the provider,
7863 // make sure to count it as being accessed and thus
7864 // back up on the LRU list. This is good because
7865 // content providers are often expensive to start.
7866 updateLruProcessLocked(cpr.app, false, true);
7867 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07007868 } else {
7869 cpr.externals++;
7870 }
7871
7872 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007873 updateOomAdjLocked(cpr.app);
7874 }
7875
7876 Binder.restoreCallingIdentity(origId);
7877
7878 } else {
7879 try {
7880 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007881 resolveContentProvider(name,
7882 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007883 } catch (RemoteException ex) {
7884 }
7885 if (cpi == null) {
7886 return null;
7887 }
7888
7889 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
7890 return new ContentProviderHolder(cpi,
7891 cpi.readPermission != null
7892 ? cpi.readPermission : cpi.writePermission);
7893 }
7894
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08007895 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
7896 && !cpi.processName.equals("system")) {
7897 // If this content provider does not run in the system
7898 // process, and the system is not yet ready to run other
7899 // processes, then fail fast instead of hanging.
7900 throw new IllegalArgumentException(
7901 "Attempt to launch content provider before system ready");
7902 }
7903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007904 cpr = (ContentProviderRecord)mProvidersByClass.get(cpi.name);
7905 final boolean firstClass = cpr == null;
7906 if (firstClass) {
7907 try {
7908 ApplicationInfo ai =
7909 ActivityThread.getPackageManager().
7910 getApplicationInfo(
7911 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007912 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007913 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007914 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 + cpi.name);
7916 return null;
7917 }
7918 cpr = new ContentProviderRecord(cpi, ai);
7919 } catch (RemoteException ex) {
7920 // pm is in same process, this will never happen.
7921 }
7922 }
7923
7924 if (r != null && cpr.canRunHere(r)) {
7925 // If this is a multiprocess provider, then just return its
7926 // info and allow the caller to instantiate it. Only do
7927 // this if the provider is the same user as the caller's
7928 // process, or can run as root (so can be in any process).
7929 return cpr;
7930 }
7931
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007932 if (DEBUG_PROVIDER) {
7933 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007934 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007935 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936 }
7937
7938 // This is single process, and our app is now connecting to it.
7939 // See if we are already in the process of launching this
7940 // provider.
7941 final int N = mLaunchingProviders.size();
7942 int i;
7943 for (i=0; i<N; i++) {
7944 if (mLaunchingProviders.get(i) == cpr) {
7945 break;
7946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007947 }
7948
7949 // If the provider is not already being launched, then get it
7950 // started.
7951 if (i >= N) {
7952 final long origId = Binder.clearCallingIdentity();
7953 ProcessRecord proc = startProcessLocked(cpi.processName,
7954 cpr.appInfo, false, 0, "content provider",
7955 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007956 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007958 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007959 + cpi.applicationInfo.packageName + "/"
7960 + cpi.applicationInfo.uid + " for provider "
7961 + name + ": process is bad");
7962 return null;
7963 }
7964 cpr.launchingApp = proc;
7965 mLaunchingProviders.add(cpr);
7966 Binder.restoreCallingIdentity(origId);
7967 }
7968
7969 // Make sure the provider is published (the same provider class
7970 // may be published under multiple names).
7971 if (firstClass) {
7972 mProvidersByClass.put(cpi.name, cpr);
7973 }
7974 mProvidersByName.put(name, cpr);
7975
7976 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007977 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07007978 "Adding provider requested by "
7979 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007980 + cpr.info.processName);
7981 Integer cnt = r.conProviders.get(cpr);
7982 if (cnt == null) {
7983 r.conProviders.put(cpr, new Integer(1));
7984 } else {
7985 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
7986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007987 cpr.clients.add(r);
7988 } else {
7989 cpr.externals++;
7990 }
7991 }
7992 }
7993
7994 // Wait for the provider to be published...
7995 synchronized (cpr) {
7996 while (cpr.provider == null) {
7997 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007998 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007999 + cpi.applicationInfo.packageName + "/"
8000 + cpi.applicationInfo.uid + " for provider "
8001 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008002 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008003 cpi.applicationInfo.packageName,
8004 cpi.applicationInfo.uid, name);
8005 return null;
8006 }
8007 try {
8008 cpr.wait();
8009 } catch (InterruptedException ex) {
8010 }
8011 }
8012 }
8013 return cpr;
8014 }
8015
8016 public final ContentProviderHolder getContentProvider(
8017 IApplicationThread caller, String name) {
8018 if (caller == null) {
8019 String msg = "null IApplicationThread when getting content provider "
8020 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008021 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008022 throw new SecurityException(msg);
8023 }
8024
8025 return getContentProviderImpl(caller, name);
8026 }
8027
8028 private ContentProviderHolder getContentProviderExternal(String name) {
8029 return getContentProviderImpl(null, name);
8030 }
8031
8032 /**
8033 * Drop a content provider from a ProcessRecord's bookkeeping
8034 * @param cpr
8035 */
8036 public void removeContentProvider(IApplicationThread caller, String name) {
8037 synchronized (this) {
8038 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
8039 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008040 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008041 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008042 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008043 return;
8044 }
8045 final ProcessRecord r = getRecordForAppLocked(caller);
8046 if (r == null) {
8047 throw new SecurityException(
8048 "Unable to find app for caller " + caller +
8049 " when removing content provider " + name);
8050 }
8051 //update content provider record entry info
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008052 ContentProviderRecord localCpr = (ContentProviderRecord)
8053 mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008054 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008055 + r.info.processName + " from process "
8056 + localCpr.appInfo.processName);
8057 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008058 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008059 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008060 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008061 return;
8062 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008063 Integer cnt = r.conProviders.get(localCpr);
8064 if (cnt == null || cnt.intValue() <= 1) {
8065 localCpr.clients.remove(r);
8066 r.conProviders.remove(localCpr);
8067 } else {
8068 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008070 }
8071 updateOomAdjLocked();
8072 }
8073 }
8074
8075 private void removeContentProviderExternal(String name) {
8076 synchronized (this) {
8077 ContentProviderRecord cpr = (ContentProviderRecord)mProvidersByName.get(name);
8078 if(cpr == null) {
8079 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008080 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 return;
8082 }
8083
8084 //update content provider record entry info
8085 ContentProviderRecord localCpr = (ContentProviderRecord) mProvidersByClass.get(cpr.info.name);
8086 localCpr.externals--;
8087 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008088 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008089 }
8090 updateOomAdjLocked();
8091 }
8092 }
8093
8094 public final void publishContentProviders(IApplicationThread caller,
8095 List<ContentProviderHolder> providers) {
8096 if (providers == null) {
8097 return;
8098 }
8099
8100 synchronized(this) {
8101 final ProcessRecord r = getRecordForAppLocked(caller);
8102 if (r == null) {
8103 throw new SecurityException(
8104 "Unable to find app for caller " + caller
8105 + " (pid=" + Binder.getCallingPid()
8106 + ") when publishing content providers");
8107 }
8108
8109 final long origId = Binder.clearCallingIdentity();
8110
8111 final int N = providers.size();
8112 for (int i=0; i<N; i++) {
8113 ContentProviderHolder src = providers.get(i);
8114 if (src == null || src.info == null || src.provider == null) {
8115 continue;
8116 }
8117 ContentProviderRecord dst =
8118 (ContentProviderRecord)r.pubProviders.get(src.info.name);
8119 if (dst != null) {
8120 mProvidersByClass.put(dst.info.name, dst);
8121 String names[] = dst.info.authority.split(";");
8122 for (int j = 0; j < names.length; j++) {
8123 mProvidersByName.put(names[j], dst);
8124 }
8125
8126 int NL = mLaunchingProviders.size();
8127 int j;
8128 for (j=0; j<NL; j++) {
8129 if (mLaunchingProviders.get(j) == dst) {
8130 mLaunchingProviders.remove(j);
8131 j--;
8132 NL--;
8133 }
8134 }
8135 synchronized (dst) {
8136 dst.provider = src.provider;
8137 dst.app = r;
8138 dst.notifyAll();
8139 }
8140 updateOomAdjLocked(r);
8141 }
8142 }
8143
8144 Binder.restoreCallingIdentity(origId);
8145 }
8146 }
8147
8148 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008149 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008150 synchronized (mSelf) {
8151 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8152 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008153 if (providers != null) {
8154 for (int i=providers.size()-1; i>=0; i--) {
8155 ProviderInfo pi = (ProviderInfo)providers.get(i);
8156 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8157 Slog.w(TAG, "Not installing system proc provider " + pi.name
8158 + ": not system .apk");
8159 providers.remove(i);
8160 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008161 }
8162 }
8163 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008164 if (providers != null) {
8165 mSystemThread.installSystemProviders(providers);
8166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008167 }
8168
8169 // =========================================================
8170 // GLOBAL MANAGEMENT
8171 // =========================================================
8172
8173 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8174 ApplicationInfo info, String customProcess) {
8175 String proc = customProcess != null ? customProcess : info.processName;
8176 BatteryStatsImpl.Uid.Proc ps = null;
8177 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8178 synchronized (stats) {
8179 ps = stats.getProcessStatsLocked(info.uid, proc);
8180 }
8181 return new ProcessRecord(ps, thread, info, proc);
8182 }
8183
8184 final ProcessRecord addAppLocked(ApplicationInfo info) {
8185 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8186
8187 if (app == null) {
8188 app = newProcessRecordLocked(null, info, null);
8189 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008190 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008191 }
8192
8193 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8194 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8195 app.persistent = true;
8196 app.maxAdj = CORE_SERVER_ADJ;
8197 }
8198 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8199 mPersistentStartingProcesses.add(app);
8200 startProcessLocked(app, "added application", app.processName);
8201 }
8202
8203 return app;
8204 }
8205
8206 public void unhandledBack() {
8207 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8208 "unhandledBack()");
8209
8210 synchronized(this) {
8211 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008212 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008213 TAG, "Performing unhandledBack(): stack size = " + count);
8214 if (count > 1) {
8215 final long origId = Binder.clearCallingIdentity();
8216 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8217 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8218 Binder.restoreCallingIdentity(origId);
8219 }
8220 }
8221 }
8222
8223 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8224 String name = uri.getAuthority();
8225 ContentProviderHolder cph = getContentProviderExternal(name);
8226 ParcelFileDescriptor pfd = null;
8227 if (cph != null) {
8228 // We record the binder invoker's uid in thread-local storage before
8229 // going to the content provider to open the file. Later, in the code
8230 // that handles all permissions checks, we look for this uid and use
8231 // that rather than the Activity Manager's own uid. The effect is that
8232 // we do the check against the caller's permissions even though it looks
8233 // to the content provider like the Activity Manager itself is making
8234 // the request.
8235 sCallerIdentity.set(new Identity(
8236 Binder.getCallingPid(), Binder.getCallingUid()));
8237 try {
8238 pfd = cph.provider.openFile(uri, "r");
8239 } catch (FileNotFoundException e) {
8240 // do nothing; pfd will be returned null
8241 } finally {
8242 // Ensure that whatever happens, we clean up the identity state
8243 sCallerIdentity.remove();
8244 }
8245
8246 // We've got the fd now, so we're done with the provider.
8247 removeContentProviderExternal(name);
8248 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008249 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008250 }
8251 return pfd;
8252 }
8253
8254 public void goingToSleep() {
8255 synchronized(this) {
8256 mSleeping = true;
8257 mWindowManager.setEventDispatching(false);
8258
8259 if (mResumedActivity != null) {
8260 pauseIfSleepingLocked();
8261 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008262 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008263 }
8264 }
8265 }
8266
Dianne Hackborn55280a92009-05-07 15:53:46 -07008267 public boolean shutdown(int timeout) {
8268 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8269 != PackageManager.PERMISSION_GRANTED) {
8270 throw new SecurityException("Requires permission "
8271 + android.Manifest.permission.SHUTDOWN);
8272 }
8273
8274 boolean timedout = false;
8275
8276 synchronized(this) {
8277 mShuttingDown = true;
8278 mWindowManager.setEventDispatching(false);
8279
8280 if (mResumedActivity != null) {
8281 pauseIfSleepingLocked();
8282 final long endTime = System.currentTimeMillis() + timeout;
8283 while (mResumedActivity != null || mPausingActivity != null) {
8284 long delay = endTime - System.currentTimeMillis();
8285 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008286 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008287 timedout = true;
8288 break;
8289 }
8290 try {
8291 this.wait();
8292 } catch (InterruptedException e) {
8293 }
8294 }
8295 }
8296 }
8297
8298 mUsageStatsService.shutdown();
8299 mBatteryStatsService.shutdown();
8300
8301 return timedout;
8302 }
8303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008304 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008305 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008306 if (!mGoingToSleep.isHeld()) {
8307 mGoingToSleep.acquire();
8308 if (mLaunchingActivity.isHeld()) {
8309 mLaunchingActivity.release();
8310 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8311 }
8312 }
8313
8314 // If we are not currently pausing an activity, get the current
8315 // one to pause. If we are pausing one, we will just let that stuff
8316 // run and release the wake lock when all done.
8317 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008318 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8319 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008320 startPausingLocked(false, true);
8321 }
8322 }
8323 }
8324
8325 public void wakingUp() {
8326 synchronized(this) {
8327 if (mGoingToSleep.isHeld()) {
8328 mGoingToSleep.release();
8329 }
8330 mWindowManager.setEventDispatching(true);
8331 mSleeping = false;
8332 resumeTopActivityLocked(null);
8333 }
8334 }
8335
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008336 public void stopAppSwitches() {
8337 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8338 != PackageManager.PERMISSION_GRANTED) {
8339 throw new SecurityException("Requires permission "
8340 + android.Manifest.permission.STOP_APP_SWITCHES);
8341 }
8342
8343 synchronized(this) {
8344 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8345 + APP_SWITCH_DELAY_TIME;
8346 mDidAppSwitch = false;
8347 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8348 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8349 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8350 }
8351 }
8352
8353 public void resumeAppSwitches() {
8354 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8355 != PackageManager.PERMISSION_GRANTED) {
8356 throw new SecurityException("Requires permission "
8357 + android.Manifest.permission.STOP_APP_SWITCHES);
8358 }
8359
8360 synchronized(this) {
8361 // Note that we don't execute any pending app switches... we will
8362 // let those wait until either the timeout, or the next start
8363 // activity request.
8364 mAppSwitchesAllowedTime = 0;
8365 }
8366 }
8367
8368 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8369 String name) {
8370 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8371 return true;
8372 }
8373
8374 final int perm = checkComponentPermission(
8375 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8376 callingUid, -1);
8377 if (perm == PackageManager.PERMISSION_GRANTED) {
8378 return true;
8379 }
8380
Joe Onorato8a9b2202010-02-26 18:56:32 -08008381 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008382 return false;
8383 }
8384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 public void setDebugApp(String packageName, boolean waitForDebugger,
8386 boolean persistent) {
8387 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8388 "setDebugApp()");
8389
8390 // Note that this is not really thread safe if there are multiple
8391 // callers into it at the same time, but that's not a situation we
8392 // care about.
8393 if (persistent) {
8394 final ContentResolver resolver = mContext.getContentResolver();
8395 Settings.System.putString(
8396 resolver, Settings.System.DEBUG_APP,
8397 packageName);
8398 Settings.System.putInt(
8399 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8400 waitForDebugger ? 1 : 0);
8401 }
8402
8403 synchronized (this) {
8404 if (!persistent) {
8405 mOrigDebugApp = mDebugApp;
8406 mOrigWaitForDebugger = mWaitForDebugger;
8407 }
8408 mDebugApp = packageName;
8409 mWaitForDebugger = waitForDebugger;
8410 mDebugTransient = !persistent;
8411 if (packageName != null) {
8412 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008413 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008414 Binder.restoreCallingIdentity(origId);
8415 }
8416 }
8417 }
8418
8419 public void setAlwaysFinish(boolean enabled) {
8420 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8421 "setAlwaysFinish()");
8422
8423 Settings.System.putInt(
8424 mContext.getContentResolver(),
8425 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8426
8427 synchronized (this) {
8428 mAlwaysFinishActivities = enabled;
8429 }
8430 }
8431
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008432 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008433 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008434 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008435 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008436 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008437 }
8438 }
8439
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008440 public boolean isUserAMonkey() {
8441 // For now the fact that there is a controller implies
8442 // we have a monkey.
8443 synchronized (this) {
8444 return mController != null;
8445 }
8446 }
8447
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008448 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008449 synchronized (this) {
8450 mWatchers.register(watcher);
8451 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008452 }
8453
8454 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008455 synchronized (this) {
8456 mWatchers.unregister(watcher);
8457 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008458 }
8459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008460 public final void enterSafeMode() {
8461 synchronized(this) {
8462 // It only makes sense to do this before the system is ready
8463 // and started launching other packages.
8464 if (!mSystemReady) {
8465 try {
8466 ActivityThread.getPackageManager().enterSafeMode();
8467 } catch (RemoteException e) {
8468 }
8469
8470 View v = LayoutInflater.from(mContext).inflate(
8471 com.android.internal.R.layout.safe_mode, null);
8472 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8473 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8474 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8475 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8476 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8477 lp.format = v.getBackground().getOpacity();
8478 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8479 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8480 ((WindowManager)mContext.getSystemService(
8481 Context.WINDOW_SERVICE)).addView(v, lp);
8482 }
8483 }
8484 }
8485
8486 public void noteWakeupAlarm(IIntentSender sender) {
8487 if (!(sender instanceof PendingIntentRecord)) {
8488 return;
8489 }
8490 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8491 synchronized (stats) {
8492 if (mBatteryStatsService.isOnBattery()) {
8493 mBatteryStatsService.enforceCallingPermission();
8494 PendingIntentRecord rec = (PendingIntentRecord)sender;
8495 int MY_UID = Binder.getCallingUid();
8496 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8497 BatteryStatsImpl.Uid.Pkg pkg =
8498 stats.getPackageStatsLocked(uid, rec.key.packageName);
8499 pkg.incWakeupsLocked();
8500 }
8501 }
8502 }
8503
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008504 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008505 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008506 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008507 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008508 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509 // XXX Note: don't acquire main activity lock here, because the window
8510 // manager calls in with its locks held.
8511
8512 boolean killed = false;
8513 synchronized (mPidsSelfLocked) {
8514 int[] types = new int[pids.length];
8515 int worstType = 0;
8516 for (int i=0; i<pids.length; i++) {
8517 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8518 if (proc != null) {
8519 int type = proc.setAdj;
8520 types[i] = type;
8521 if (type > worstType) {
8522 worstType = type;
8523 }
8524 }
8525 }
8526
8527 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8528 // then constrain it so we will kill all hidden procs.
8529 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8530 worstType = HIDDEN_APP_MIN_ADJ;
8531 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008532 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008533 for (int i=0; i<pids.length; i++) {
8534 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8535 if (proc == null) {
8536 continue;
8537 }
8538 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008539 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008540 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008541 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8542 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008544 proc.killedBackground = true;
8545 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008546 }
8547 }
8548 }
8549 return killed;
8550 }
8551
8552 public void reportPss(IApplicationThread caller, int pss) {
8553 Watchdog.PssRequestor req;
8554 String name;
8555 ProcessRecord callerApp;
8556 synchronized (this) {
8557 if (caller == null) {
8558 return;
8559 }
8560 callerApp = getRecordForAppLocked(caller);
8561 if (callerApp == null) {
8562 return;
8563 }
8564 callerApp.lastPss = pss;
8565 req = callerApp;
8566 name = callerApp.processName;
8567 }
8568 Watchdog.getInstance().reportPss(req, name, pss);
8569 if (!callerApp.persistent) {
8570 removeRequestedPss(callerApp);
8571 }
8572 }
8573
8574 public void requestPss(Runnable completeCallback) {
8575 ArrayList<ProcessRecord> procs;
8576 synchronized (this) {
8577 mRequestPssCallback = completeCallback;
8578 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008579 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8580 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008581 if (!proc.persistent) {
8582 mRequestPssList.add(proc);
8583 }
8584 }
8585 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8586 }
8587
8588 int oldPri = Process.getThreadPriority(Process.myTid());
8589 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8590 for (int i=procs.size()-1; i>=0; i--) {
8591 ProcessRecord proc = procs.get(i);
8592 proc.lastPss = 0;
8593 proc.requestPss();
8594 }
8595 Process.setThreadPriority(oldPri);
8596 }
8597
8598 void removeRequestedPss(ProcessRecord proc) {
8599 Runnable callback = null;
8600 synchronized (this) {
8601 if (mRequestPssList.remove(proc)) {
8602 if (mRequestPssList.size() == 0) {
8603 callback = mRequestPssCallback;
8604 mRequestPssCallback = null;
8605 }
8606 }
8607 }
8608
8609 if (callback != null) {
8610 callback.run();
8611 }
8612 }
8613
8614 public void collectPss(Watchdog.PssStats stats) {
8615 stats.mEmptyPss = 0;
8616 stats.mEmptyCount = 0;
8617 stats.mBackgroundPss = 0;
8618 stats.mBackgroundCount = 0;
8619 stats.mServicePss = 0;
8620 stats.mServiceCount = 0;
8621 stats.mVisiblePss = 0;
8622 stats.mVisibleCount = 0;
8623 stats.mForegroundPss = 0;
8624 stats.mForegroundCount = 0;
8625 stats.mNoPssCount = 0;
8626 synchronized (this) {
8627 int i;
8628 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8629 ? mProcDeaths.length : stats.mProcDeaths.length;
8630 int aggr = 0;
8631 for (i=0; i<NPD; i++) {
8632 aggr += mProcDeaths[i];
8633 stats.mProcDeaths[i] = aggr;
8634 }
8635 while (i<stats.mProcDeaths.length) {
8636 stats.mProcDeaths[i] = 0;
8637 i++;
8638 }
8639
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008640 for (i=mLruProcesses.size()-1; i>=0; i--) {
8641 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642 if (proc.persistent) {
8643 continue;
8644 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008645 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008646 if (proc.lastPss == 0) {
8647 stats.mNoPssCount++;
8648 continue;
8649 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008650 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8651 if (proc.empty) {
8652 stats.mEmptyPss += proc.lastPss;
8653 stats.mEmptyCount++;
8654 } else {
8655 stats.mBackgroundPss += proc.lastPss;
8656 stats.mBackgroundCount++;
8657 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008658 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8659 stats.mVisiblePss += proc.lastPss;
8660 stats.mVisibleCount++;
8661 } else {
8662 stats.mForegroundPss += proc.lastPss;
8663 stats.mForegroundCount++;
8664 }
8665 }
8666 }
8667 }
8668
8669 public final void startRunning(String pkg, String cls, String action,
8670 String data) {
8671 synchronized(this) {
8672 if (mStartRunning) {
8673 return;
8674 }
8675 mStartRunning = true;
8676 mTopComponent = pkg != null && cls != null
8677 ? new ComponentName(pkg, cls) : null;
8678 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8679 mTopData = data;
8680 if (!mSystemReady) {
8681 return;
8682 }
8683 }
8684
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008685 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008686 }
8687
8688 private void retrieveSettings() {
8689 final ContentResolver resolver = mContext.getContentResolver();
8690 String debugApp = Settings.System.getString(
8691 resolver, Settings.System.DEBUG_APP);
8692 boolean waitForDebugger = Settings.System.getInt(
8693 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8694 boolean alwaysFinishActivities = Settings.System.getInt(
8695 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8696
8697 Configuration configuration = new Configuration();
8698 Settings.System.getConfiguration(resolver, configuration);
8699
8700 synchronized (this) {
8701 mDebugApp = mOrigDebugApp = debugApp;
8702 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8703 mAlwaysFinishActivities = alwaysFinishActivities;
8704 // This happens before any activities are started, so we can
8705 // change mConfiguration in-place.
8706 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008707 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008708 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008709 }
8710 }
8711
8712 public boolean testIsSystemReady() {
8713 // no need to synchronize(this) just to read & return the value
8714 return mSystemReady;
8715 }
8716
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008717 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 // In the simulator, startRunning will never have been called, which
8719 // normally sets a few crucial variables. Do it here instead.
8720 if (!Process.supportsProcesses()) {
8721 mStartRunning = true;
8722 mTopAction = Intent.ACTION_MAIN;
8723 }
8724
8725 synchronized(this) {
8726 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008727 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 return;
8729 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008730
8731 // Check to see if there are any update receivers to run.
8732 if (!mDidUpdate) {
8733 if (mWaitingUpdate) {
8734 return;
8735 }
8736 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8737 List<ResolveInfo> ris = null;
8738 try {
8739 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8740 intent, null, 0);
8741 } catch (RemoteException e) {
8742 }
8743 if (ris != null) {
8744 for (int i=ris.size()-1; i>=0; i--) {
8745 if ((ris.get(i).activityInfo.applicationInfo.flags
8746 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8747 ris.remove(i);
8748 }
8749 }
8750 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8751 for (int i=0; i<ris.size(); i++) {
8752 ActivityInfo ai = ris.get(i).activityInfo;
8753 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8754 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008755 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008756 finisher = new IIntentReceiver.Stub() {
8757 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008758 String data, Bundle extras, boolean ordered,
8759 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008760 throws RemoteException {
8761 synchronized (ActivityManagerService.this) {
8762 mDidUpdate = true;
8763 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008764 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008765 }
8766 };
8767 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008768 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008769 broadcastIntentLocked(null, null, intent, null, finisher,
8770 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008771 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008772 mWaitingUpdate = true;
8773 }
8774 }
8775 }
8776 if (mWaitingUpdate) {
8777 return;
8778 }
8779 mDidUpdate = true;
8780 }
8781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 mSystemReady = true;
8783 if (!mStartRunning) {
8784 return;
8785 }
8786 }
8787
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008788 ArrayList<ProcessRecord> procsToKill = null;
8789 synchronized(mPidsSelfLocked) {
8790 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
8791 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
8792 if (!isAllowedWhileBooting(proc.info)){
8793 if (procsToKill == null) {
8794 procsToKill = new ArrayList<ProcessRecord>();
8795 }
8796 procsToKill.add(proc);
8797 }
8798 }
8799 }
8800
8801 if (procsToKill != null) {
8802 synchronized(this) {
8803 for (int i=procsToKill.size()-1; i>=0; i--) {
8804 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008805 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008806 removeProcessLocked(proc, true);
8807 }
8808 }
8809 }
8810
Joe Onorato8a9b2202010-02-26 18:56:32 -08008811 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008812 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 SystemClock.uptimeMillis());
8814
8815 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008816 // Make sure we have no pre-ready processes sitting around.
8817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008818 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
8819 ResolveInfo ri = mContext.getPackageManager()
8820 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07008821 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008822 CharSequence errorMsg = null;
8823 if (ri != null) {
8824 ActivityInfo ai = ri.activityInfo;
8825 ApplicationInfo app = ai.applicationInfo;
8826 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8827 mTopAction = Intent.ACTION_FACTORY_TEST;
8828 mTopData = null;
8829 mTopComponent = new ComponentName(app.packageName,
8830 ai.name);
8831 } else {
8832 errorMsg = mContext.getResources().getText(
8833 com.android.internal.R.string.factorytest_not_system);
8834 }
8835 } else {
8836 errorMsg = mContext.getResources().getText(
8837 com.android.internal.R.string.factorytest_no_action);
8838 }
8839 if (errorMsg != null) {
8840 mTopAction = null;
8841 mTopData = null;
8842 mTopComponent = null;
8843 Message msg = Message.obtain();
8844 msg.what = SHOW_FACTORY_ERROR_MSG;
8845 msg.getData().putCharSequence("msg", errorMsg);
8846 mHandler.sendMessage(msg);
8847 }
8848 }
8849 }
8850
8851 retrieveSettings();
8852
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008853 if (goingCallback != null) goingCallback.run();
8854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008855 synchronized (this) {
8856 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
8857 try {
8858 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008859 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008860 if (apps != null) {
8861 int N = apps.size();
8862 int i;
8863 for (i=0; i<N; i++) {
8864 ApplicationInfo info
8865 = (ApplicationInfo)apps.get(i);
8866 if (info != null &&
8867 !info.packageName.equals("android")) {
8868 addAppLocked(info);
8869 }
8870 }
8871 }
8872 } catch (RemoteException ex) {
8873 // pm is in same process, this will never happen.
8874 }
8875 }
8876
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008877 // Start up initial activity.
8878 mBooting = true;
8879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008880 try {
8881 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
8882 Message msg = Message.obtain();
8883 msg.what = SHOW_UID_ERROR_MSG;
8884 mHandler.sendMessage(msg);
8885 }
8886 } catch (RemoteException e) {
8887 }
8888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008889 resumeTopActivityLocked(null);
8890 }
8891 }
8892
Dan Egnorb7f03672009-12-09 16:22:32 -08008893 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008894 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008895 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008896 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008897 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008898 startAppProblemLocked(app);
8899 app.stopFreezingAllLocked();
8900 return handleAppCrashLocked(app);
8901 }
8902
Dan Egnorb7f03672009-12-09 16:22:32 -08008903 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008904 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008905 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08008906 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08008907 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
8908 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008909 startAppProblemLocked(app);
8910 app.stopFreezingAllLocked();
8911 }
8912
8913 /**
8914 * Generate a process error record, suitable for attachment to a ProcessRecord.
8915 *
8916 * @param app The ProcessRecord in which the error occurred.
8917 * @param condition Crashing, Application Not Responding, etc. Values are defined in
8918 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08008919 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008920 * @param shortMsg Short message describing the crash.
8921 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08008922 * @param stackTrace Full crash stack trace, may be null.
8923 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008924 * @return Returns a fully-formed AppErrorStateInfo record.
8925 */
8926 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08008927 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08008929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008930 report.condition = condition;
8931 report.processName = app.processName;
8932 report.pid = app.pid;
8933 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08008934 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008935 report.shortMsg = shortMsg;
8936 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08008937 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008938
8939 return report;
8940 }
8941
Dan Egnor42471dd2010-01-07 17:25:22 -08008942 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008943 synchronized (this) {
8944 app.crashing = false;
8945 app.crashingReport = null;
8946 app.notResponding = false;
8947 app.notRespondingReport = null;
8948 if (app.anrDialog == fromDialog) {
8949 app.anrDialog = null;
8950 }
8951 if (app.waitDialog == fromDialog) {
8952 app.waitDialog = null;
8953 }
8954 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08008955 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07008956 Slog.i(ActivityManagerService.TAG, "Killing "
8957 + app.processName + " (pid=" + app.pid + "): user's request");
8958 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
8959 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008960 Process.killProcess(app.pid);
8961 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 }
8963 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008964
Dan Egnorb7f03672009-12-09 16:22:32 -08008965 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008966 long now = SystemClock.uptimeMillis();
8967
8968 Long crashTime = mProcessCrashTimes.get(app.info.processName,
8969 app.info.uid);
8970 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
8971 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08008972 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008974 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008975 app.info.processName, app.info.uid);
8976 killServicesLocked(app, false);
8977 for (int i=mHistory.size()-1; i>=0; i--) {
8978 HistoryRecord r = (HistoryRecord)mHistory.get(i);
8979 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008980 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008981 + r.intent.getComponent().flattenToShortString());
8982 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
8983 }
8984 }
8985 if (!app.persistent) {
8986 // We don't want to start this process again until the user
8987 // explicitly does so... but for persistent process, we really
8988 // need to keep it running. If a persistent process is actually
8989 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08008990 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008991 app.info.processName);
8992 mBadProcesses.put(app.info.processName, app.info.uid, now);
8993 app.bad = true;
8994 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
8995 app.removed = true;
8996 removeProcessLocked(app, false);
8997 return false;
8998 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07008999 } else {
9000 HistoryRecord r = topRunningActivityLocked(null);
9001 if (r.app == app) {
9002 // If the top running activity is from this crashing
9003 // process, then terminate it to avoid getting in a loop.
9004 Slog.w(TAG, " Force finishing activity "
9005 + r.intent.getComponent().flattenToShortString());
9006 int index = indexOfTokenLocked(r);
9007 finishActivityLocked(r, index,
9008 Activity.RESULT_CANCELED, null, "crashed");
9009 // Also terminate an activities below it that aren't yet
9010 // stopped, to avoid a situation where one will get
9011 // re-start our crashing activity once it gets resumed again.
9012 index--;
9013 if (index >= 0) {
9014 r = (HistoryRecord)mHistory.get(index);
9015 if (r.state == ActivityState.RESUMED
9016 || r.state == ActivityState.PAUSING
9017 || r.state == ActivityState.PAUSED) {
9018 if (!r.isHomeActivity) {
9019 Slog.w(TAG, " Force finishing activity "
9020 + r.intent.getComponent().flattenToShortString());
9021 finishActivityLocked(r, index,
9022 Activity.RESULT_CANCELED, null, "crashed");
9023 }
9024 }
9025 }
9026 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009027 }
9028
9029 // Bump up the crash count of any services currently running in the proc.
9030 if (app.services.size() != 0) {
9031 // Any services running in the application need to be placed
9032 // back in the pending list.
9033 Iterator it = app.services.iterator();
9034 while (it.hasNext()) {
9035 ServiceRecord sr = (ServiceRecord)it.next();
9036 sr.crashCount++;
9037 }
9038 }
9039
9040 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9041 return true;
9042 }
9043
9044 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009045 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9046 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009047 skipCurrentReceiverLocked(app);
9048 }
9049
9050 void skipCurrentReceiverLocked(ProcessRecord app) {
9051 boolean reschedule = false;
9052 BroadcastRecord r = app.curReceiver;
9053 if (r != null) {
9054 // The current broadcast is waiting for this app's receiver
9055 // to be finished. Looks like that's not going to happen, so
9056 // let the broadcast continue.
9057 logBroadcastReceiverDiscard(r);
9058 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9059 r.resultExtras, r.resultAbort, true);
9060 reschedule = true;
9061 }
9062 r = mPendingBroadcast;
9063 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009064 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009065 "skip & discard pending app " + r);
9066 logBroadcastReceiverDiscard(r);
9067 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9068 r.resultExtras, r.resultAbort, true);
9069 reschedule = true;
9070 }
9071 if (reschedule) {
9072 scheduleBroadcastsLocked();
9073 }
9074 }
9075
Dan Egnor60d87622009-12-16 16:32:58 -08009076 /**
9077 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9078 * The application process will exit immediately after this call returns.
9079 * @param app object of the crashing app, null for the system server
9080 * @param crashInfo describing the exception
9081 */
9082 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9083 ProcessRecord r = findAppProcess(app);
9084
9085 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9086 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009087 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009088 crashInfo.exceptionClassName,
9089 crashInfo.exceptionMessage,
9090 crashInfo.throwFileName,
9091 crashInfo.throwLineNumber);
9092
Dan Egnor42471dd2010-01-07 17:25:22 -08009093 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009094
9095 crashApplication(r, crashInfo);
9096 }
9097
9098 /**
9099 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9100 * @param app object of the crashing app, null for the system server
9101 * @param tag reported by the caller
9102 * @param crashInfo describing the context of the error
9103 * @return true if the process should exit immediately (WTF is fatal)
9104 */
9105 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009106 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009107 ProcessRecord r = findAppProcess(app);
9108
9109 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9110 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009111 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009112 tag, crashInfo.exceptionMessage);
9113
Dan Egnor42471dd2010-01-07 17:25:22 -08009114 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009115
Doug Zongker43866e02010-01-07 12:09:54 -08009116 if (Settings.Secure.getInt(mContext.getContentResolver(),
9117 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009118 crashApplication(r, crashInfo);
9119 return true;
9120 } else {
9121 return false;
9122 }
9123 }
9124
9125 /**
9126 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9127 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9128 */
9129 private ProcessRecord findAppProcess(IBinder app) {
9130 if (app == null) {
9131 return null;
9132 }
9133
9134 synchronized (this) {
9135 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9136 final int NA = apps.size();
9137 for (int ia=0; ia<NA; ia++) {
9138 ProcessRecord p = apps.valueAt(ia);
9139 if (p.thread != null && p.thread.asBinder() == app) {
9140 return p;
9141 }
9142 }
9143 }
9144
Joe Onorato8a9b2202010-02-26 18:56:32 -08009145 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009146 return null;
9147 }
9148 }
9149
9150 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009151 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009152 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009153 * @param process which caused the error, null means the system server
9154 * @param activity which triggered the error, null if unknown
9155 * @param parent activity related to the error, null if unknown
9156 * @param subject line related to the error, null if absent
9157 * @param report in long form describing the error, null if absent
9158 * @param logFile to include in the report, null if none
9159 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009160 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009161 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009162 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9163 final String report, final File logFile,
9164 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009165 // NOTE -- this must never acquire the ActivityManagerService lock,
9166 // otherwise the watchdog may be prevented from resetting the system.
9167
Dan Egnora455d192010-03-12 08:52:28 -08009168 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009169 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009170 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009171 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009172 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009173 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009174 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009175 }
9176
Dan Egnora455d192010-03-12 08:52:28 -08009177 final String dropboxTag = prefix + eventType;
9178 final DropBoxManager dbox = (DropBoxManager)
9179 mContext.getSystemService(Context.DROPBOX_SERVICE);
9180
9181 // Exit early if the dropbox isn't configured to accept this report type.
9182 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9183
9184 final StringBuilder sb = new StringBuilder(1024);
9185 if (process == null || process.pid == MY_PID) {
9186 sb.append("Process: system_server\n");
9187 } else {
9188 sb.append("Process: ").append(process.processName).append("\n");
9189 }
9190 if (process != null) {
9191 int flags = process.info.flags;
9192 IPackageManager pm = ActivityThread.getPackageManager();
9193 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9194 for (String pkg : process.pkgList) {
9195 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009196 try {
Dan Egnora455d192010-03-12 08:52:28 -08009197 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9198 if (pi != null) {
9199 sb.append(" v").append(pi.versionCode);
9200 if (pi.versionName != null) {
9201 sb.append(" (").append(pi.versionName).append(")");
9202 }
9203 }
9204 } catch (RemoteException e) {
9205 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009206 }
Dan Egnora455d192010-03-12 08:52:28 -08009207 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009208 }
Dan Egnora455d192010-03-12 08:52:28 -08009209 }
9210 if (activity != null) {
9211 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9212 }
9213 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9214 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9215 }
9216 if (parent != null && parent != activity) {
9217 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9218 }
9219 if (subject != null) {
9220 sb.append("Subject: ").append(subject).append("\n");
9221 }
9222 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9223 sb.append("\n");
9224
9225 // Do the rest in a worker thread to avoid blocking the caller on I/O
9226 // (After this point, we shouldn't access AMS internal data structures.)
9227 Thread worker = new Thread("Error dump: " + dropboxTag) {
9228 @Override
9229 public void run() {
9230 if (report != null) {
9231 sb.append(report);
9232 }
9233 if (logFile != null) {
9234 try {
9235 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9236 } catch (IOException e) {
9237 Slog.e(TAG, "Error reading " + logFile, e);
9238 }
9239 }
9240 if (crashInfo != null && crashInfo.stackTrace != null) {
9241 sb.append(crashInfo.stackTrace);
9242 }
9243
9244 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9245 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9246 if (lines > 0) {
9247 sb.append("\n");
9248
9249 // Merge several logcat streams, and take the last N lines
9250 InputStreamReader input = null;
9251 try {
9252 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9253 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9254 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9255
9256 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9257 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9258 input = new InputStreamReader(logcat.getInputStream());
9259
9260 int num;
9261 char[] buf = new char[8192];
9262 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9263 } catch (IOException e) {
9264 Slog.e(TAG, "Error running logcat", e);
9265 } finally {
9266 if (input != null) try { input.close(); } catch (IOException e) {}
9267 }
9268 }
9269
9270 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009271 }
Dan Egnora455d192010-03-12 08:52:28 -08009272 };
9273
9274 if (process == null || process.pid == MY_PID) {
9275 worker.run(); // We may be about to die -- need to run this synchronously
9276 } else {
9277 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009278 }
9279 }
9280
9281 /**
9282 * Bring up the "unexpected error" dialog box for a crashing app.
9283 * Deal with edge cases (intercepts from instrumented applications,
9284 * ActivityController, error intent receivers, that sort of thing).
9285 * @param r the application crashing
9286 * @param crashInfo describing the failure
9287 */
9288 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009289 long timeMillis = System.currentTimeMillis();
9290 String shortMsg = crashInfo.exceptionClassName;
9291 String longMsg = crashInfo.exceptionMessage;
9292 String stackTrace = crashInfo.stackTrace;
9293 if (shortMsg != null && longMsg != null) {
9294 longMsg = shortMsg + ": " + longMsg;
9295 } else if (shortMsg != null) {
9296 longMsg = shortMsg;
9297 }
9298
Dan Egnor60d87622009-12-16 16:32:58 -08009299 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009300 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009301 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009302 try {
9303 String name = r != null ? r.processName : null;
9304 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009305 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009306 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009307 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009308 + " at watcher's request");
9309 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009310 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009311 }
9312 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009313 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009314 }
9315 }
9316
9317 final long origId = Binder.clearCallingIdentity();
9318
9319 // If this process is running instrumentation, finish it.
9320 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009321 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009322 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009323 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9324 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009325 Bundle info = new Bundle();
9326 info.putString("shortMsg", shortMsg);
9327 info.putString("longMsg", longMsg);
9328 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9329 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009330 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009331 }
9332
Dan Egnor60d87622009-12-16 16:32:58 -08009333 // If we can't identify the process or it's already exceeded its crash quota,
9334 // quit right away without showing a crash dialog.
9335 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009336 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009337 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009338 }
9339
9340 Message msg = Message.obtain();
9341 msg.what = SHOW_ERROR_MSG;
9342 HashMap data = new HashMap();
9343 data.put("result", result);
9344 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009345 msg.obj = data;
9346 mHandler.sendMessage(msg);
9347
9348 Binder.restoreCallingIdentity(origId);
9349 }
9350
9351 int res = result.get();
9352
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009353 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009354 synchronized (this) {
9355 if (r != null) {
9356 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9357 SystemClock.uptimeMillis());
9358 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009359 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009360 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009361 }
9362 }
9363
9364 if (appErrorIntent != null) {
9365 try {
9366 mContext.startActivity(appErrorIntent);
9367 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009368 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009371 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009372
9373 Intent createAppErrorIntentLocked(ProcessRecord r,
9374 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9375 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009376 if (report == null) {
9377 return null;
9378 }
9379 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9380 result.setComponent(r.errorReportReceiver);
9381 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9382 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9383 return result;
9384 }
9385
Dan Egnorb7f03672009-12-09 16:22:32 -08009386 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9387 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009388 if (r.errorReportReceiver == null) {
9389 return null;
9390 }
9391
9392 if (!r.crashing && !r.notResponding) {
9393 return null;
9394 }
9395
Dan Egnorb7f03672009-12-09 16:22:32 -08009396 ApplicationErrorReport report = new ApplicationErrorReport();
9397 report.packageName = r.info.packageName;
9398 report.installerPackageName = r.errorReportReceiver.getPackageName();
9399 report.processName = r.processName;
9400 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009401 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009402
Dan Egnorb7f03672009-12-09 16:22:32 -08009403 if (r.crashing) {
9404 report.type = ApplicationErrorReport.TYPE_CRASH;
9405 report.crashInfo = crashInfo;
9406 } else if (r.notResponding) {
9407 report.type = ApplicationErrorReport.TYPE_ANR;
9408 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009409
Dan Egnorb7f03672009-12-09 16:22:32 -08009410 report.anrInfo.activity = r.notRespondingReport.tag;
9411 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9412 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009413 }
9414
Dan Egnorb7f03672009-12-09 16:22:32 -08009415 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009416 }
9417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009418 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9419 // assume our apps are happy - lazy create the list
9420 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9421
9422 synchronized (this) {
9423
9424 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009425 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9426 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009427 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9428 // This one's in trouble, so we'll generate a report for it
9429 // crashes are higher priority (in case there's a crash *and* an anr)
9430 ActivityManager.ProcessErrorStateInfo report = null;
9431 if (app.crashing) {
9432 report = app.crashingReport;
9433 } else if (app.notResponding) {
9434 report = app.notRespondingReport;
9435 }
9436
9437 if (report != null) {
9438 if (errList == null) {
9439 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9440 }
9441 errList.add(report);
9442 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009443 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009444 " crashing = " + app.crashing +
9445 " notResponding = " + app.notResponding);
9446 }
9447 }
9448 }
9449 }
9450
9451 return errList;
9452 }
9453
9454 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9455 // Lazy instantiation of list
9456 List<ActivityManager.RunningAppProcessInfo> runList = null;
9457 synchronized (this) {
9458 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009459 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9460 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009461 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9462 // Generate process state info for running application
9463 ActivityManager.RunningAppProcessInfo currApp =
9464 new ActivityManager.RunningAppProcessInfo(app.processName,
9465 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009466 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009467 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009468 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009469 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9470 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9471 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009472 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9473 } else if (adj >= HOME_APP_ADJ) {
9474 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9475 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009476 } else if (adj >= SECONDARY_SERVER_ADJ) {
9477 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9478 } else if (adj >= VISIBLE_APP_ADJ) {
9479 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
9480 } else {
9481 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9482 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009483 currApp.importanceReasonCode = app.adjTypeCode;
9484 if (app.adjSource instanceof ProcessRecord) {
9485 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9486 } else if (app.adjSource instanceof HistoryRecord) {
9487 HistoryRecord r = (HistoryRecord)app.adjSource;
9488 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9489 }
9490 if (app.adjTarget instanceof ComponentName) {
9491 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9492 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009493 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009494 // + " lru=" + currApp.lru);
9495 if (runList == null) {
9496 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9497 }
9498 runList.add(currApp);
9499 }
9500 }
9501 }
9502 return runList;
9503 }
9504
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009505 public List<ApplicationInfo> getRunningExternalApplications() {
9506 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9507 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9508 if (runningApps != null && runningApps.size() > 0) {
9509 Set<String> extList = new HashSet<String>();
9510 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9511 if (app.pkgList != null) {
9512 for (String pkg : app.pkgList) {
9513 extList.add(pkg);
9514 }
9515 }
9516 }
9517 IPackageManager pm = ActivityThread.getPackageManager();
9518 for (String pkg : extList) {
9519 try {
9520 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9521 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9522 retList.add(info);
9523 }
9524 } catch (RemoteException e) {
9525 }
9526 }
9527 }
9528 return retList;
9529 }
9530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009531 @Override
9532 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009533 if (checkCallingPermission(android.Manifest.permission.DUMP)
9534 != PackageManager.PERMISSION_GRANTED) {
9535 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9536 + Binder.getCallingPid()
9537 + ", uid=" + Binder.getCallingUid()
9538 + " without permission "
9539 + android.Manifest.permission.DUMP);
9540 return;
9541 }
9542
9543 boolean dumpAll = false;
9544
9545 int opti = 0;
9546 while (opti < args.length) {
9547 String opt = args[opti];
9548 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9549 break;
9550 }
9551 opti++;
9552 if ("-a".equals(opt)) {
9553 dumpAll = true;
9554 } else if ("-h".equals(opt)) {
9555 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009556 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009557 pw.println(" cmd may be one of:");
9558 pw.println(" activities: activity stack state");
9559 pw.println(" broadcasts: broadcast state");
9560 pw.println(" intents: pending intent state");
9561 pw.println(" processes: process state");
9562 pw.println(" providers: content provider state");
9563 pw.println(" services: service state");
9564 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009565 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009566 } else {
9567 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009568 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009569 }
9570
9571 // Is the caller requesting to dump a particular piece of data?
9572 if (opti < args.length) {
9573 String cmd = args[opti];
9574 opti++;
9575 if ("activities".equals(cmd) || "a".equals(cmd)) {
9576 synchronized (this) {
9577 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009579 return;
9580 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9581 synchronized (this) {
9582 dumpBroadcastsLocked(fd, pw, args, opti, true);
9583 }
9584 return;
9585 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9586 synchronized (this) {
9587 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9588 }
9589 return;
9590 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9591 synchronized (this) {
9592 dumpProcessesLocked(fd, pw, args, opti, true);
9593 }
9594 return;
9595 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9596 synchronized (this) {
9597 dumpProvidersLocked(fd, pw, args, opti, true);
9598 }
9599 return;
9600 } else if ("service".equals(cmd)) {
9601 dumpService(fd, pw, args, opti, true);
9602 return;
9603 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9604 synchronized (this) {
9605 dumpServicesLocked(fd, pw, args, opti, true);
9606 }
9607 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009608 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009609 }
9610
9611 // No piece of data specified, dump everything.
9612 synchronized (this) {
9613 boolean needSep;
9614 if (dumpAll) {
9615 pw.println("Providers in Current Activity Manager State:");
9616 }
9617 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9618 if (needSep) {
9619 pw.println(" ");
9620 }
9621 if (dumpAll) {
9622 pw.println("-------------------------------------------------------------------------------");
9623 pw.println("Broadcasts in Current Activity Manager State:");
9624 }
9625 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9626 if (needSep) {
9627 pw.println(" ");
9628 }
9629 if (dumpAll) {
9630 pw.println("-------------------------------------------------------------------------------");
9631 pw.println("Services in Current Activity Manager State:");
9632 }
9633 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9634 if (needSep) {
9635 pw.println(" ");
9636 }
9637 if (dumpAll) {
9638 pw.println("-------------------------------------------------------------------------------");
9639 pw.println("PendingIntents in Current Activity Manager State:");
9640 }
9641 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9642 if (needSep) {
9643 pw.println(" ");
9644 }
9645 if (dumpAll) {
9646 pw.println("-------------------------------------------------------------------------------");
9647 pw.println("Activities in Current Activity Manager State:");
9648 }
9649 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9650 if (needSep) {
9651 pw.println(" ");
9652 }
9653 if (dumpAll) {
9654 pw.println("-------------------------------------------------------------------------------");
9655 pw.println("Processes in Current Activity Manager State:");
9656 }
9657 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9658 }
9659 }
9660
9661 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9662 int opti, boolean dumpAll, boolean needHeader) {
9663 if (needHeader) {
9664 pw.println(" Activity stack:");
9665 }
9666 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9667 pw.println(" ");
9668 pw.println(" Running activities (most recent first):");
9669 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9670 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009671 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009672 pw.println(" Activities waiting for another to become visible:");
9673 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9674 }
9675 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009677 pw.println(" Activities waiting to stop:");
9678 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9679 }
9680 if (mFinishingActivities.size() > 0) {
9681 pw.println(" ");
9682 pw.println(" Activities waiting to finish:");
9683 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009685
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009686 pw.println(" ");
9687 pw.println(" mPausingActivity: " + mPausingActivity);
9688 pw.println(" mResumedActivity: " + mResumedActivity);
9689 pw.println(" mFocusedActivity: " + mFocusedActivity);
9690 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009691
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009692 if (dumpAll && mRecentTasks.size() > 0) {
9693 pw.println(" ");
9694 pw.println("Recent tasks in Current Activity Manager State:");
9695
9696 final int N = mRecentTasks.size();
9697 for (int i=0; i<N; i++) {
9698 TaskRecord tr = mRecentTasks.get(i);
9699 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9700 pw.println(tr);
9701 mRecentTasks.get(i).dump(pw, " ");
9702 }
9703 }
9704
9705 pw.println(" ");
9706 pw.println(" mCurTask: " + mCurTask);
9707
9708 return true;
9709 }
9710
9711 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9712 int opti, boolean dumpAll) {
9713 boolean needSep = false;
9714 int numPers = 0;
9715
9716 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009717 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9718 final int NA = procs.size();
9719 for (int ia=0; ia<NA; ia++) {
9720 if (!needSep) {
9721 pw.println(" All known processes:");
9722 needSep = true;
9723 }
9724 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009725 pw.print(r.persistent ? " *PERS*" : " *APP*");
9726 pw.print(" UID "); pw.print(procs.keyAt(ia));
9727 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009728 r.dump(pw, " ");
9729 if (r.persistent) {
9730 numPers++;
9731 }
9732 }
9733 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009734 }
9735
9736 if (mLruProcesses.size() > 0) {
9737 if (needSep) pw.println(" ");
9738 needSep = true;
9739 pw.println(" Running processes (most recent first):");
9740 dumpProcessList(pw, this, mLruProcesses, " ",
9741 "App ", "PERS", true);
9742 needSep = true;
9743 }
9744
9745 synchronized (mPidsSelfLocked) {
9746 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009747 if (needSep) pw.println(" ");
9748 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009749 pw.println(" PID mappings:");
9750 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9751 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9752 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009753 }
9754 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009755 }
9756
9757 if (mForegroundProcesses.size() > 0) {
9758 if (needSep) pw.println(" ");
9759 needSep = true;
9760 pw.println(" Foreground Processes:");
9761 for (int i=0; i<mForegroundProcesses.size(); i++) {
9762 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9763 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009764 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009765 }
9766
9767 if (mPersistentStartingProcesses.size() > 0) {
9768 if (needSep) pw.println(" ");
9769 needSep = true;
9770 pw.println(" Persisent processes that are starting:");
9771 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9772 "Starting Norm", "Restarting PERS", false);
9773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009774
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009775 if (mStartingProcesses.size() > 0) {
9776 if (needSep) pw.println(" ");
9777 needSep = true;
9778 pw.println(" Processes that are starting:");
9779 dumpProcessList(pw, this, mStartingProcesses, " ",
9780 "Starting Norm", "Starting PERS", false);
9781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009783 if (mRemovedProcesses.size() > 0) {
9784 if (needSep) pw.println(" ");
9785 needSep = true;
9786 pw.println(" Processes that are being removed:");
9787 dumpProcessList(pw, this, mRemovedProcesses, " ",
9788 "Removed Norm", "Removed PERS", false);
9789 }
9790
9791 if (mProcessesOnHold.size() > 0) {
9792 if (needSep) pw.println(" ");
9793 needSep = true;
9794 pw.println(" Processes that are on old until the system is ready:");
9795 dumpProcessList(pw, this, mProcessesOnHold, " ",
9796 "OnHold Norm", "OnHold PERS", false);
9797 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009798
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009799 if (mProcessesToGc.size() > 0) {
9800 if (needSep) pw.println(" ");
9801 needSep = true;
9802 pw.println(" Processes that are waiting to GC:");
9803 long now = SystemClock.uptimeMillis();
9804 for (int i=0; i<mProcessesToGc.size(); i++) {
9805 ProcessRecord proc = mProcessesToGc.get(i);
9806 pw.print(" Process "); pw.println(proc);
9807 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
9808 pw.print(", last gced=");
9809 pw.print(now-proc.lastRequestedGc);
9810 pw.print(" ms ago, last lowMem=");
9811 pw.print(now-proc.lastLowMemory);
9812 pw.println(" ms ago");
9813
9814 }
9815 }
9816
9817 if (mProcessCrashTimes.getMap().size() > 0) {
9818 if (needSep) pw.println(" ");
9819 needSep = true;
9820 pw.println(" Time since processes crashed:");
9821 long now = SystemClock.uptimeMillis();
9822 for (Map.Entry<String, SparseArray<Long>> procs
9823 : mProcessCrashTimes.getMap().entrySet()) {
9824 SparseArray<Long> uids = procs.getValue();
9825 final int N = uids.size();
9826 for (int i=0; i<N; i++) {
9827 pw.print(" Process "); pw.print(procs.getKey());
9828 pw.print(" uid "); pw.print(uids.keyAt(i));
9829 pw.print(": last crashed ");
9830 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009831 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009832 }
9833 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009836 if (mBadProcesses.getMap().size() > 0) {
9837 if (needSep) pw.println(" ");
9838 needSep = true;
9839 pw.println(" Bad processes:");
9840 for (Map.Entry<String, SparseArray<Long>> procs
9841 : mBadProcesses.getMap().entrySet()) {
9842 SparseArray<Long> uids = procs.getValue();
9843 final int N = uids.size();
9844 for (int i=0; i<N; i++) {
9845 pw.print(" Bad process "); pw.print(procs.getKey());
9846 pw.print(" uid "); pw.print(uids.keyAt(i));
9847 pw.print(": crashed at time ");
9848 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009849 }
9850 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009851 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009852
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009853 pw.println(" ");
9854 pw.println(" mHomeProcess: " + mHomeProcess);
9855 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07009856 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009857 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
9858 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
9859 || mOrigWaitForDebugger) {
9860 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
9861 + " mDebugTransient=" + mDebugTransient
9862 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
9863 }
9864 if (mAlwaysFinishActivities || mController != null) {
9865 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
9866 + " mController=" + mController);
9867 }
9868 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009869 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009870 pw.println(" mStartRunning=" + mStartRunning
9871 + " mSystemReady=" + mSystemReady
9872 + " mBooting=" + mBooting
9873 + " mBooted=" + mBooted
9874 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009875 pw.println(" mGoingToSleep=" + mGoingToSleep);
9876 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07009877 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009878 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009879
9880 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009881 }
9882
9883 /**
9884 * There are three ways to call this:
9885 * - no service specified: dump all the services
9886 * - a flattened component name that matched an existing service was specified as the
9887 * first arg: dump that one service
9888 * - the first arg isn't the flattened component name of an existing service:
9889 * dump all services whose component contains the first arg as a substring
9890 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009891 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
9892 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009893 String[] newArgs;
9894 String componentNameString;
9895 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08009896 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009897 componentNameString = null;
9898 newArgs = EMPTY_STRING_ARRAY;
9899 r = null;
9900 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009901 componentNameString = args[opti];
9902 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
9904 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009905 newArgs = new String[args.length - opti];
9906 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009907 }
9908
9909 if (r != null) {
9910 dumpService(fd, pw, r, newArgs);
9911 } else {
9912 for (ServiceRecord r1 : mServices.values()) {
9913 if (componentNameString == null
9914 || r1.name.flattenToString().contains(componentNameString)) {
9915 dumpService(fd, pw, r1, newArgs);
9916 }
9917 }
9918 }
9919 }
9920
9921 /**
9922 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
9923 * there is a thread associated with the service.
9924 */
9925 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
9926 pw.println(" Service " + r.name.flattenToString());
9927 if (r.app != null && r.app.thread != null) {
9928 try {
9929 // flush anything that is already in the PrintWriter since the thread is going
9930 // to write to the file descriptor directly
9931 pw.flush();
9932 r.app.thread.dumpService(fd, r, args);
9933 pw.print("\n");
9934 } catch (RemoteException e) {
9935 pw.println("got a RemoteException while dumping the service");
9936 }
9937 }
9938 }
9939
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009940 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9941 int opti, boolean dumpAll) {
9942 boolean needSep = false;
9943
9944 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009945 if (mRegisteredReceivers.size() > 0) {
9946 pw.println(" ");
9947 pw.println(" Registered Receivers:");
9948 Iterator it = mRegisteredReceivers.values().iterator();
9949 while (it.hasNext()) {
9950 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009951 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009952 r.dump(pw, " ");
9953 }
9954 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009956 pw.println(" ");
9957 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009958 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009959 needSep = true;
9960 }
9961
9962 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
9963 || mPendingBroadcast != null) {
9964 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009966 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009967 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009968 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9969 pw.println(" Broadcast #" + i + ":");
9970 mParallelBroadcasts.get(i).dump(pw, " ");
9971 }
9972 if (mOrderedBroadcasts.size() > 0) {
9973 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07009974 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009975 }
9976 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9977 pw.println(" Serialized Broadcast #" + i + ":");
9978 mOrderedBroadcasts.get(i).dump(pw, " ");
9979 }
9980 pw.println(" ");
9981 pw.println(" Pending broadcast:");
9982 if (mPendingBroadcast != null) {
9983 mPendingBroadcast.dump(pw, " ");
9984 } else {
9985 pw.println(" (null)");
9986 }
9987 needSep = true;
9988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009989
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009990 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009991 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009992 pw.println(" Historical broadcasts:");
9993 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9994 BroadcastRecord r = mBroadcastHistory[i];
9995 if (r == null) {
9996 break;
9997 }
9998 pw.println(" Historical Broadcast #" + i + ":");
9999 r.dump(pw, " ");
10000 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010001 needSep = true;
10002 }
10003
10004 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010005 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010006 pw.println(" Sticky broadcasts:");
10007 StringBuilder sb = new StringBuilder(128);
10008 for (Map.Entry<String, ArrayList<Intent>> ent
10009 : mStickyBroadcasts.entrySet()) {
10010 pw.print(" * Sticky action "); pw.print(ent.getKey());
10011 pw.println(":");
10012 ArrayList<Intent> intents = ent.getValue();
10013 final int N = intents.size();
10014 for (int i=0; i<N; i++) {
10015 sb.setLength(0);
10016 sb.append(" Intent: ");
10017 intents.get(i).toShortString(sb, true, false);
10018 pw.println(sb.toString());
10019 Bundle bundle = intents.get(i).getExtras();
10020 if (bundle != null) {
10021 pw.print(" ");
10022 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010023 }
10024 }
10025 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010026 needSep = true;
10027 }
10028
10029 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010031 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032 pw.println(" mHandler:");
10033 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010034 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010035 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010036
10037 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038 }
10039
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010040 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10041 int opti, boolean dumpAll) {
10042 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010043
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010044 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010045 if (mServices.size() > 0) {
10046 pw.println(" Active services:");
10047 Iterator<ServiceRecord> it = mServices.values().iterator();
10048 while (it.hasNext()) {
10049 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010050 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010051 r.dump(pw, " ");
10052 }
10053 needSep = true;
10054 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010056
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010057 if (mPendingServices.size() > 0) {
10058 if (needSep) pw.println(" ");
10059 pw.println(" Pending services:");
10060 for (int i=0; i<mPendingServices.size(); i++) {
10061 ServiceRecord r = mPendingServices.get(i);
10062 pw.print(" * Pending "); pw.println(r);
10063 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010065 needSep = true;
10066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010067
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010068 if (mRestartingServices.size() > 0) {
10069 if (needSep) pw.println(" ");
10070 pw.println(" Restarting services:");
10071 for (int i=0; i<mRestartingServices.size(); i++) {
10072 ServiceRecord r = mRestartingServices.get(i);
10073 pw.print(" * Restarting "); pw.println(r);
10074 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010076 needSep = true;
10077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010078
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010079 if (mStoppingServices.size() > 0) {
10080 if (needSep) pw.println(" ");
10081 pw.println(" Stopping services:");
10082 for (int i=0; i<mStoppingServices.size(); i++) {
10083 ServiceRecord r = mStoppingServices.get(i);
10084 pw.print(" * Stopping "); pw.println(r);
10085 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010086 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010087 needSep = true;
10088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010089
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010090 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010091 if (mServiceConnections.size() > 0) {
10092 if (needSep) pw.println(" ");
10093 pw.println(" Connection bindings to services:");
10094 Iterator<ConnectionRecord> it
10095 = mServiceConnections.values().iterator();
10096 while (it.hasNext()) {
10097 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010098 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099 r.dump(pw, " ");
10100 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010101 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010102 }
10103 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010104
10105 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010106 }
10107
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010108 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10109 int opti, boolean dumpAll) {
10110 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010111
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010112 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010113 if (mProvidersByClass.size() > 0) {
10114 if (needSep) pw.println(" ");
10115 pw.println(" Published content providers (by class):");
10116 Iterator it = mProvidersByClass.entrySet().iterator();
10117 while (it.hasNext()) {
10118 Map.Entry e = (Map.Entry)it.next();
10119 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010120 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010121 r.dump(pw, " ");
10122 }
10123 needSep = true;
10124 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010125
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010126 if (mProvidersByName.size() > 0) {
10127 pw.println(" ");
10128 pw.println(" Authority to provider mappings:");
10129 Iterator it = mProvidersByName.entrySet().iterator();
10130 while (it.hasNext()) {
10131 Map.Entry e = (Map.Entry)it.next();
10132 ContentProviderRecord r = (ContentProviderRecord)e.getValue();
10133 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10134 pw.println(r);
10135 }
10136 needSep = true;
10137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010138 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010139
10140 if (mLaunchingProviders.size() > 0) {
10141 if (needSep) pw.println(" ");
10142 pw.println(" Launching content providers:");
10143 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10144 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10145 pw.println(mLaunchingProviders.get(i));
10146 }
10147 needSep = true;
10148 }
10149
10150 if (mGrantedUriPermissions.size() > 0) {
10151 pw.println();
10152 pw.println("Granted Uri Permissions:");
10153 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10154 int uid = mGrantedUriPermissions.keyAt(i);
10155 HashMap<Uri, UriPermission> perms
10156 = mGrantedUriPermissions.valueAt(i);
10157 pw.print(" * UID "); pw.print(uid);
10158 pw.println(" holds:");
10159 for (UriPermission perm : perms.values()) {
10160 pw.print(" "); pw.println(perm);
10161 perm.dump(pw, " ");
10162 }
10163 }
10164 needSep = true;
10165 }
10166
10167 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010168 }
10169
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010170 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10171 int opti, boolean dumpAll) {
10172 boolean needSep = false;
10173
10174 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010175 if (this.mIntentSenderRecords.size() > 0) {
10176 Iterator<WeakReference<PendingIntentRecord>> it
10177 = mIntentSenderRecords.values().iterator();
10178 while (it.hasNext()) {
10179 WeakReference<PendingIntentRecord> ref = it.next();
10180 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010181 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010183 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010184 rec.dump(pw, " ");
10185 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010186 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010187 }
10188 }
10189 }
10190 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010191
10192 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010193 }
10194
10195 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010196 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010197 TaskRecord lastTask = null;
10198 for (int i=list.size()-1; i>=0; i--) {
10199 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010200 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010201 if (lastTask != r.task) {
10202 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010203 pw.print(prefix);
10204 pw.print(full ? "* " : " ");
10205 pw.println(lastTask);
10206 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010207 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010208 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010209 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010210 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10211 pw.print(" #"); pw.print(i); pw.print(": ");
10212 pw.println(r);
10213 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010214 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010216 }
10217 }
10218
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010219 private static String buildOomTag(String prefix, String space, int val, int base) {
10220 if (val == base) {
10221 if (space == null) return prefix;
10222 return prefix + " ";
10223 }
10224 return prefix + "+" + Integer.toString(val-base);
10225 }
10226
10227 private static final int dumpProcessList(PrintWriter pw,
10228 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010229 String prefix, String normalLabel, String persistentLabel,
10230 boolean inclOomAdj) {
10231 int numPers = 0;
10232 for (int i=list.size()-1; i>=0; i--) {
10233 ProcessRecord r = (ProcessRecord)list.get(i);
10234 if (false) {
10235 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10236 + " #" + i + ":");
10237 r.dump(pw, prefix + " ");
10238 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010239 String oomAdj;
10240 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010241 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010242 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010243 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10244 } else if (r.setAdj >= HOME_APP_ADJ) {
10245 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10246 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10247 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10248 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10249 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10250 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10251 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10252 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10253 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010254 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010255 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010256 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010257 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010258 } else {
10259 oomAdj = Integer.toString(r.setAdj);
10260 }
10261 String schedGroup;
10262 switch (r.setSchedGroup) {
10263 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10264 schedGroup = "B";
10265 break;
10266 case Process.THREAD_GROUP_DEFAULT:
10267 schedGroup = "F";
10268 break;
10269 default:
10270 schedGroup = Integer.toString(r.setSchedGroup);
10271 break;
10272 }
10273 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010274 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010275 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010276 if (r.adjSource != null || r.adjTarget != null) {
10277 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010278 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010280 } else {
10281 pw.println(String.format("%s%s #%2d: %s",
10282 prefix, (r.persistent ? persistentLabel : normalLabel),
10283 i, r.toString()));
10284 }
10285 if (r.persistent) {
10286 numPers++;
10287 }
10288 }
10289 return numPers;
10290 }
10291
Dianne Hackborn472ad872010-04-07 17:31:48 -070010292 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010293 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010294 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010295 long uptime = SystemClock.uptimeMillis();
10296 long realtime = SystemClock.elapsedRealtime();
10297
10298 if (isCheckinRequest) {
10299 // short checkin version
10300 pw.println(uptime + "," + realtime);
10301 pw.flush();
10302 } else {
10303 pw.println("Applications Memory Usage (kB):");
10304 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10305 }
10306 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10307 ProcessRecord r = (ProcessRecord)list.get(i);
10308 if (r.thread != null) {
10309 if (!isCheckinRequest) {
10310 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10311 pw.flush();
10312 }
10313 try {
10314 r.thread.asBinder().dump(fd, args);
10315 } catch (RemoteException e) {
10316 if (!isCheckinRequest) {
10317 pw.println("Got RemoteException!");
10318 pw.flush();
10319 }
10320 }
10321 }
10322 }
10323 }
10324
10325 /**
10326 * Searches array of arguments for the specified string
10327 * @param args array of argument strings
10328 * @param value value to search for
10329 * @return true if the value is contained in the array
10330 */
10331 private static boolean scanArgs(String[] args, String value) {
10332 if (args != null) {
10333 for (String arg : args) {
10334 if (value.equals(arg)) {
10335 return true;
10336 }
10337 }
10338 }
10339 return false;
10340 }
10341
Dianne Hackborn75b03852009-06-12 15:43:26 -070010342 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010343 int count = mHistory.size();
10344
10345 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010346 int index = -1;
10347 for (int i=count-1; i>=0; i--) {
10348 Object o = mHistory.get(i);
10349 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010350 index = i;
10351 break;
10352 }
10353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354
10355 return index;
10356 }
10357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010358 private final void killServicesLocked(ProcessRecord app,
10359 boolean allowRestart) {
10360 // Report disconnected services.
10361 if (false) {
10362 // XXX we are letting the client link to the service for
10363 // death notifications.
10364 if (app.services.size() > 0) {
10365 Iterator it = app.services.iterator();
10366 while (it.hasNext()) {
10367 ServiceRecord r = (ServiceRecord)it.next();
10368 if (r.connections.size() > 0) {
10369 Iterator<ConnectionRecord> jt
10370 = r.connections.values().iterator();
10371 while (jt.hasNext()) {
10372 ConnectionRecord c = jt.next();
10373 if (c.binding.client != app) {
10374 try {
10375 //c.conn.connected(r.className, null);
10376 } catch (Exception e) {
10377 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010378 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010379 + r.shortName
10380 + " from app " + app.processName, e);
10381 }
10382 }
10383 }
10384 }
10385 }
10386 }
10387 }
10388
10389 // Clean up any connections this application has to other services.
10390 if (app.connections.size() > 0) {
10391 Iterator<ConnectionRecord> it = app.connections.iterator();
10392 while (it.hasNext()) {
10393 ConnectionRecord r = it.next();
10394 removeConnectionLocked(r, app, null);
10395 }
10396 }
10397 app.connections.clear();
10398
10399 if (app.services.size() != 0) {
10400 // Any services running in the application need to be placed
10401 // back in the pending list.
10402 Iterator it = app.services.iterator();
10403 while (it.hasNext()) {
10404 ServiceRecord sr = (ServiceRecord)it.next();
10405 synchronized (sr.stats.getBatteryStats()) {
10406 sr.stats.stopLaunchedLocked();
10407 }
10408 sr.app = null;
10409 sr.executeNesting = 0;
10410 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010411
10412 boolean hasClients = sr.bindings.size() > 0;
10413 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414 Iterator<IntentBindRecord> bindings
10415 = sr.bindings.values().iterator();
10416 while (bindings.hasNext()) {
10417 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010418 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010419 + ": shouldUnbind=" + b.hasBound);
10420 b.binder = null;
10421 b.requested = b.received = b.hasBound = false;
10422 }
10423 }
10424
10425 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010426 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010428 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010429 sr.crashCount, sr.shortName, app.pid);
10430 bringDownServiceLocked(sr, true);
10431 } else if (!allowRestart) {
10432 bringDownServiceLocked(sr, true);
10433 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010434 boolean canceled = scheduleServiceRestartLocked(sr, true);
10435
10436 // Should the service remain running? Note that in the
10437 // extreme case of so many attempts to deliver a command
10438 // that it failed, that we also will stop it here.
10439 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10440 if (sr.pendingStarts.size() == 0) {
10441 sr.startRequested = false;
10442 if (!hasClients) {
10443 // Whoops, no reason to restart!
10444 bringDownServiceLocked(sr, true);
10445 }
10446 }
10447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010448 }
10449 }
10450
10451 if (!allowRestart) {
10452 app.services.clear();
10453 }
10454 }
10455
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010456 // Make sure we have no more records on the stopping list.
10457 int i = mStoppingServices.size();
10458 while (i > 0) {
10459 i--;
10460 ServiceRecord sr = mStoppingServices.get(i);
10461 if (sr.app == app) {
10462 mStoppingServices.remove(i);
10463 }
10464 }
10465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010466 app.executingServices.clear();
10467 }
10468
10469 private final void removeDyingProviderLocked(ProcessRecord proc,
10470 ContentProviderRecord cpr) {
10471 synchronized (cpr) {
10472 cpr.launchingApp = null;
10473 cpr.notifyAll();
10474 }
10475
10476 mProvidersByClass.remove(cpr.info.name);
10477 String names[] = cpr.info.authority.split(";");
10478 for (int j = 0; j < names.length; j++) {
10479 mProvidersByName.remove(names[j]);
10480 }
10481
10482 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10483 while (cit.hasNext()) {
10484 ProcessRecord capp = cit.next();
10485 if (!capp.persistent && capp.thread != null
10486 && capp.pid != 0
10487 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010488 Slog.i(TAG, "Kill " + capp.processName
10489 + " (pid " + capp.pid + "): provider " + cpr.info.name
10490 + " in dying process " + proc.processName);
10491 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10492 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010493 Process.killProcess(capp.pid);
10494 }
10495 }
10496
10497 mLaunchingProviders.remove(cpr);
10498 }
10499
10500 /**
10501 * Main code for cleaning up a process when it has gone away. This is
10502 * called both as a result of the process dying, or directly when stopping
10503 * a process when running in single process mode.
10504 */
10505 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10506 boolean restarting, int index) {
10507 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010508 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010509 }
10510
Dianne Hackborn36124872009-10-08 16:22:03 -070010511 mProcessesToGc.remove(app);
10512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010513 // Dismiss any open dialogs.
10514 if (app.crashDialog != null) {
10515 app.crashDialog.dismiss();
10516 app.crashDialog = null;
10517 }
10518 if (app.anrDialog != null) {
10519 app.anrDialog.dismiss();
10520 app.anrDialog = null;
10521 }
10522 if (app.waitDialog != null) {
10523 app.waitDialog.dismiss();
10524 app.waitDialog = null;
10525 }
10526
10527 app.crashing = false;
10528 app.notResponding = false;
10529
10530 app.resetPackageList();
10531 app.thread = null;
10532 app.forcingToForeground = null;
10533 app.foregroundServices = false;
10534
10535 killServicesLocked(app, true);
10536
10537 boolean restart = false;
10538
10539 int NL = mLaunchingProviders.size();
10540
10541 // Remove published content providers.
10542 if (!app.pubProviders.isEmpty()) {
10543 Iterator it = app.pubProviders.values().iterator();
10544 while (it.hasNext()) {
10545 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10546 cpr.provider = null;
10547 cpr.app = null;
10548
10549 // See if someone is waiting for this provider... in which
10550 // case we don't remove it, but just let it restart.
10551 int i = 0;
10552 if (!app.bad) {
10553 for (; i<NL; i++) {
10554 if (mLaunchingProviders.get(i) == cpr) {
10555 restart = true;
10556 break;
10557 }
10558 }
10559 } else {
10560 i = NL;
10561 }
10562
10563 if (i >= NL) {
10564 removeDyingProviderLocked(app, cpr);
10565 NL = mLaunchingProviders.size();
10566 }
10567 }
10568 app.pubProviders.clear();
10569 }
10570
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010571 // Take care of any launching providers waiting for this process.
10572 if (checkAppInLaunchingProvidersLocked(app, false)) {
10573 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010574 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010576 // Unregister from connected content providers.
10577 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010578 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010579 while (it.hasNext()) {
10580 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10581 cpr.clients.remove(app);
10582 }
10583 app.conProviders.clear();
10584 }
10585
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010586 // At this point there may be remaining entries in mLaunchingProviders
10587 // where we were the only one waiting, so they are no longer of use.
10588 // Look for these and clean up if found.
10589 // XXX Commented out for now. Trying to figure out a way to reproduce
10590 // the actual situation to identify what is actually going on.
10591 if (false) {
10592 for (int i=0; i<NL; i++) {
10593 ContentProviderRecord cpr = (ContentProviderRecord)
10594 mLaunchingProviders.get(i);
10595 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10596 synchronized (cpr) {
10597 cpr.launchingApp = null;
10598 cpr.notifyAll();
10599 }
10600 }
10601 }
10602 }
10603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010604 skipCurrentReceiverLocked(app);
10605
10606 // Unregister any receivers.
10607 if (app.receivers.size() > 0) {
10608 Iterator<ReceiverList> it = app.receivers.iterator();
10609 while (it.hasNext()) {
10610 removeReceiverLocked(it.next());
10611 }
10612 app.receivers.clear();
10613 }
10614
Christopher Tate181fafa2009-05-14 11:12:14 -070010615 // If the app is undergoing backup, tell the backup manager about it
10616 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010617 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010618 try {
10619 IBackupManager bm = IBackupManager.Stub.asInterface(
10620 ServiceManager.getService(Context.BACKUP_SERVICE));
10621 bm.agentDisconnected(app.info.packageName);
10622 } catch (RemoteException e) {
10623 // can't happen; backup manager is local
10624 }
10625 }
10626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010627 // If the caller is restarting this app, then leave it in its
10628 // current lists and let the caller take care of it.
10629 if (restarting) {
10630 return;
10631 }
10632
10633 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010634 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010635 "Removing non-persistent process during cleanup: " + app);
10636 mProcessNames.remove(app.processName, app.info.uid);
10637 } else if (!app.removed) {
10638 // This app is persistent, so we need to keep its record around.
10639 // If it is not already on the pending app list, add it there
10640 // and start a new process for it.
10641 app.thread = null;
10642 app.forcingToForeground = null;
10643 app.foregroundServices = false;
10644 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10645 mPersistentStartingProcesses.add(app);
10646 restart = true;
10647 }
10648 }
10649 mProcessesOnHold.remove(app);
10650
The Android Open Source Project4df24232009-03-05 14:34:35 -080010651 if (app == mHomeProcess) {
10652 mHomeProcess = null;
10653 }
10654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010655 if (restart) {
10656 // We have components that still need to be running in the
10657 // process, so re-launch it.
10658 mProcessNames.put(app.processName, app.info.uid, app);
10659 startProcessLocked(app, "restart", app.processName);
10660 } else if (app.pid > 0 && app.pid != MY_PID) {
10661 // Goodbye!
10662 synchronized (mPidsSelfLocked) {
10663 mPidsSelfLocked.remove(app.pid);
10664 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10665 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010666 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 }
10668 }
10669
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010670 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10671 // Look through the content providers we are waiting to have launched,
10672 // and if any run in this process then either schedule a restart of
10673 // the process or kill the client waiting for it if this process has
10674 // gone bad.
10675 int NL = mLaunchingProviders.size();
10676 boolean restart = false;
10677 for (int i=0; i<NL; i++) {
10678 ContentProviderRecord cpr = (ContentProviderRecord)
10679 mLaunchingProviders.get(i);
10680 if (cpr.launchingApp == app) {
10681 if (!alwaysBad && !app.bad) {
10682 restart = true;
10683 } else {
10684 removeDyingProviderLocked(app, cpr);
10685 NL = mLaunchingProviders.size();
10686 }
10687 }
10688 }
10689 return restart;
10690 }
10691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010692 // =========================================================
10693 // SERVICES
10694 // =========================================================
10695
10696 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10697 ActivityManager.RunningServiceInfo info =
10698 new ActivityManager.RunningServiceInfo();
10699 info.service = r.name;
10700 if (r.app != null) {
10701 info.pid = r.app.pid;
10702 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010703 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010704 info.process = r.processName;
10705 info.foreground = r.isForeground;
10706 info.activeSince = r.createTime;
10707 info.started = r.startRequested;
10708 info.clientCount = r.connections.size();
10709 info.crashCount = r.crashCount;
10710 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010711 if (r.isForeground) {
10712 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10713 }
10714 if (r.startRequested) {
10715 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10716 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010717 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010718 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10719 }
10720 if (r.app != null && r.app.persistent) {
10721 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10722 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010723 for (ConnectionRecord conn : r.connections.values()) {
10724 if (conn.clientLabel != 0) {
10725 info.clientPackage = conn.binding.client.info.packageName;
10726 info.clientLabel = conn.clientLabel;
10727 break;
10728 }
10729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010730 return info;
10731 }
10732
10733 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10734 int flags) {
10735 synchronized (this) {
10736 ArrayList<ActivityManager.RunningServiceInfo> res
10737 = new ArrayList<ActivityManager.RunningServiceInfo>();
10738
10739 if (mServices.size() > 0) {
10740 Iterator<ServiceRecord> it = mServices.values().iterator();
10741 while (it.hasNext() && res.size() < maxNum) {
10742 res.add(makeRunningServiceInfoLocked(it.next()));
10743 }
10744 }
10745
10746 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10747 ServiceRecord r = mRestartingServices.get(i);
10748 ActivityManager.RunningServiceInfo info =
10749 makeRunningServiceInfoLocked(r);
10750 info.restarting = r.nextRestartTime;
10751 res.add(info);
10752 }
10753
10754 return res;
10755 }
10756 }
10757
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010758 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10759 synchronized (this) {
10760 ServiceRecord r = mServices.get(name);
10761 if (r != null) {
10762 for (ConnectionRecord conn : r.connections.values()) {
10763 if (conn.clientIntent != null) {
10764 return conn.clientIntent;
10765 }
10766 }
10767 }
10768 }
10769 return null;
10770 }
10771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772 private final ServiceRecord findServiceLocked(ComponentName name,
10773 IBinder token) {
10774 ServiceRecord r = mServices.get(name);
10775 return r == token ? r : null;
10776 }
10777
10778 private final class ServiceLookupResult {
10779 final ServiceRecord record;
10780 final String permission;
10781
10782 ServiceLookupResult(ServiceRecord _record, String _permission) {
10783 record = _record;
10784 permission = _permission;
10785 }
10786 };
10787
10788 private ServiceLookupResult findServiceLocked(Intent service,
10789 String resolvedType) {
10790 ServiceRecord r = null;
10791 if (service.getComponent() != null) {
10792 r = mServices.get(service.getComponent());
10793 }
10794 if (r == null) {
10795 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10796 r = mServicesByIntent.get(filter);
10797 }
10798
10799 if (r == null) {
10800 try {
10801 ResolveInfo rInfo =
10802 ActivityThread.getPackageManager().resolveService(
10803 service, resolvedType, 0);
10804 ServiceInfo sInfo =
10805 rInfo != null ? rInfo.serviceInfo : null;
10806 if (sInfo == null) {
10807 return null;
10808 }
10809
10810 ComponentName name = new ComponentName(
10811 sInfo.applicationInfo.packageName, sInfo.name);
10812 r = mServices.get(name);
10813 } catch (RemoteException ex) {
10814 // pm is in same process, this will never happen.
10815 }
10816 }
10817 if (r != null) {
10818 int callingPid = Binder.getCallingPid();
10819 int callingUid = Binder.getCallingUid();
10820 if (checkComponentPermission(r.permission,
10821 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10822 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010823 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010824 + " from pid=" + callingPid
10825 + ", uid=" + callingUid
10826 + " requires " + r.permission);
10827 return new ServiceLookupResult(null, r.permission);
10828 }
10829 return new ServiceLookupResult(r, null);
10830 }
10831 return null;
10832 }
10833
10834 private class ServiceRestarter implements Runnable {
10835 private ServiceRecord mService;
10836
10837 void setService(ServiceRecord service) {
10838 mService = service;
10839 }
10840
10841 public void run() {
10842 synchronized(ActivityManagerService.this) {
10843 performServiceRestartLocked(mService);
10844 }
10845 }
10846 }
10847
10848 private ServiceLookupResult retrieveServiceLocked(Intent service,
10849 String resolvedType, int callingPid, int callingUid) {
10850 ServiceRecord r = null;
10851 if (service.getComponent() != null) {
10852 r = mServices.get(service.getComponent());
10853 }
10854 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10855 r = mServicesByIntent.get(filter);
10856 if (r == null) {
10857 try {
10858 ResolveInfo rInfo =
10859 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010860 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010861 ServiceInfo sInfo =
10862 rInfo != null ? rInfo.serviceInfo : null;
10863 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010864 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010865 ": not found");
10866 return null;
10867 }
10868
10869 ComponentName name = new ComponentName(
10870 sInfo.applicationInfo.packageName, sInfo.name);
10871 r = mServices.get(name);
10872 if (r == null) {
10873 filter = new Intent.FilterComparison(service.cloneFilter());
10874 ServiceRestarter res = new ServiceRestarter();
10875 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10876 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10877 synchronized (stats) {
10878 ss = stats.getServiceStatsLocked(
10879 sInfo.applicationInfo.uid, sInfo.packageName,
10880 sInfo.name);
10881 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010882 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010883 res.setService(r);
10884 mServices.put(name, r);
10885 mServicesByIntent.put(filter, r);
10886
10887 // Make sure this component isn't in the pending list.
10888 int N = mPendingServices.size();
10889 for (int i=0; i<N; i++) {
10890 ServiceRecord pr = mPendingServices.get(i);
10891 if (pr.name.equals(name)) {
10892 mPendingServices.remove(i);
10893 i--;
10894 N--;
10895 }
10896 }
10897 }
10898 } catch (RemoteException ex) {
10899 // pm is in same process, this will never happen.
10900 }
10901 }
10902 if (r != null) {
10903 if (checkComponentPermission(r.permission,
10904 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
10905 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010906 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010907 + " from pid=" + Binder.getCallingPid()
10908 + ", uid=" + Binder.getCallingUid()
10909 + " requires " + r.permission);
10910 return new ServiceLookupResult(null, r.permission);
10911 }
10912 return new ServiceLookupResult(r, null);
10913 }
10914 return null;
10915 }
10916
10917 private final void bumpServiceExecutingLocked(ServiceRecord r) {
10918 long now = SystemClock.uptimeMillis();
10919 if (r.executeNesting == 0 && r.app != null) {
10920 if (r.app.executingServices.size() == 0) {
10921 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10922 msg.obj = r.app;
10923 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10924 }
10925 r.app.executingServices.add(r);
10926 }
10927 r.executeNesting++;
10928 r.executingStart = now;
10929 }
10930
10931 private final void sendServiceArgsLocked(ServiceRecord r,
10932 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010933 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010934 if (N == 0) {
10935 return;
10936 }
10937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 int i = 0;
10939 while (i < N) {
10940 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010941 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010942 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010943 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070010944 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010945 // If somehow we got a dummy start at the front, then
10946 // just drop it here.
10947 i++;
10948 continue;
10949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010950 bumpServiceExecutingLocked(r);
10951 if (!oomAdjusted) {
10952 oomAdjusted = true;
10953 updateOomAdjLocked(r.app);
10954 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010955 int flags = 0;
10956 if (si.deliveryCount > 0) {
10957 flags |= Service.START_FLAG_RETRY;
10958 }
10959 if (si.doneExecutingCount > 0) {
10960 flags |= Service.START_FLAG_REDELIVERY;
10961 }
10962 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
10963 si.deliveredTime = SystemClock.uptimeMillis();
10964 r.deliveredStarts.add(si);
10965 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010967 } catch (RemoteException e) {
10968 // Remote process gone... we'll let the normal cleanup take
10969 // care of this.
10970 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010971 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010972 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 break;
10974 }
10975 }
10976 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010977 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010978 } else {
10979 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010981 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010982 }
10983 }
10984 }
10985
10986 private final boolean requestServiceBindingLocked(ServiceRecord r,
10987 IntentBindRecord i, boolean rebind) {
10988 if (r.app == null || r.app.thread == null) {
10989 // If service is not currently running, can't yet bind.
10990 return false;
10991 }
10992 if ((!i.requested || rebind) && i.apps.size() > 0) {
10993 try {
10994 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010995 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 + ": shouldUnbind=" + i.hasBound);
10997 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10998 if (!rebind) {
10999 i.requested = true;
11000 }
11001 i.hasBound = true;
11002 i.doRebind = false;
11003 } catch (RemoteException e) {
11004 return false;
11005 }
11006 }
11007 return true;
11008 }
11009
11010 private final void requestServiceBindingsLocked(ServiceRecord r) {
11011 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11012 while (bindings.hasNext()) {
11013 IntentBindRecord i = bindings.next();
11014 if (!requestServiceBindingLocked(r, i, false)) {
11015 break;
11016 }
11017 }
11018 }
11019
11020 private final void realStartServiceLocked(ServiceRecord r,
11021 ProcessRecord app) throws RemoteException {
11022 if (app.thread == null) {
11023 throw new RemoteException();
11024 }
11025
11026 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011027 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011028
11029 app.services.add(r);
11030 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011031 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011032
11033 boolean created = false;
11034 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011035 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011037 mStringBuilder.setLength(0);
11038 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011039 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011040 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011041 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 synchronized (r.stats.getBatteryStats()) {
11043 r.stats.startLaunchedLocked();
11044 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011045 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011047 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011048 created = true;
11049 } finally {
11050 if (!created) {
11051 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011052 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 }
11054 }
11055
11056 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011057
11058 // If the service is in the started state, and there are no
11059 // pending arguments, then fake up one so its onStartCommand() will
11060 // be called.
11061 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11062 r.lastStartId++;
11063 if (r.lastStartId < 1) {
11064 r.lastStartId = 1;
11065 }
11066 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11067 }
11068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011069 sendServiceArgsLocked(r, true);
11070 }
11071
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011072 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11073 boolean allowCancel) {
11074 boolean canceled = false;
11075
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011076 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011077 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011078 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011079
11080 // Any delivered but not yet finished starts should be put back
11081 // on the pending list.
11082 final int N = r.deliveredStarts.size();
11083 if (N > 0) {
11084 for (int i=N-1; i>=0; i--) {
11085 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11086 if (si.intent == null) {
11087 // We'll generate this again if needed.
11088 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11089 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11090 r.pendingStarts.add(0, si);
11091 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11092 dur *= 2;
11093 if (minDuration < dur) minDuration = dur;
11094 if (resetTime < dur) resetTime = dur;
11095 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011096 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011097 + r.name);
11098 canceled = true;
11099 }
11100 }
11101 r.deliveredStarts.clear();
11102 }
11103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 r.totalRestartCount++;
11105 if (r.restartDelay == 0) {
11106 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011107 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011108 } else {
11109 // If it has been a "reasonably long time" since the service
11110 // was started, then reset our restart duration back to
11111 // the beginning, so we don't infinitely increase the duration
11112 // on a service that just occasionally gets killed (which is
11113 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011114 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011115 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011116 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011118 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011119 if (r.restartDelay < minDuration) {
11120 r.restartDelay = minDuration;
11121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011122 }
11123 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011124
11125 r.nextRestartTime = now + r.restartDelay;
11126
11127 // Make sure that we don't end up restarting a bunch of services
11128 // all at the same time.
11129 boolean repeat;
11130 do {
11131 repeat = false;
11132 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11133 ServiceRecord r2 = mRestartingServices.get(i);
11134 if (r2 != r && r.nextRestartTime
11135 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11136 && r.nextRestartTime
11137 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11138 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11139 r.restartDelay = r.nextRestartTime - now;
11140 repeat = true;
11141 break;
11142 }
11143 }
11144 } while (repeat);
11145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011146 if (!mRestartingServices.contains(r)) {
11147 mRestartingServices.add(r);
11148 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011149
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011150 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011153 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011155 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011157 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011158 r.shortName, r.restartDelay);
11159
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011160 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011161 }
11162
11163 final void performServiceRestartLocked(ServiceRecord r) {
11164 if (!mRestartingServices.contains(r)) {
11165 return;
11166 }
11167 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11168 }
11169
11170 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11171 if (r.restartDelay == 0) {
11172 return false;
11173 }
11174 r.resetRestartCounter();
11175 mRestartingServices.remove(r);
11176 mHandler.removeCallbacks(r.restarter);
11177 return true;
11178 }
11179
11180 private final boolean bringUpServiceLocked(ServiceRecord r,
11181 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011182 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011183 //r.dump(" ");
11184
Dianne Hackborn36124872009-10-08 16:22:03 -070011185 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186 sendServiceArgsLocked(r, false);
11187 return true;
11188 }
11189
11190 if (!whileRestarting && r.restartDelay > 0) {
11191 // If waiting for a restart, then do nothing.
11192 return true;
11193 }
11194
Joe Onorato8a9b2202010-02-26 18:56:32 -080011195 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011196 + " " + r.intent);
11197
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011198 // We are now bringing the service up, so no longer in the
11199 // restarting state.
11200 mRestartingServices.remove(r);
11201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 final String appName = r.processName;
11203 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11204 if (app != null && app.thread != null) {
11205 try {
11206 realStartServiceLocked(r, app);
11207 return true;
11208 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011209 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 }
11211
11212 // If a dead object exception was thrown -- fall through to
11213 // restart the application.
11214 }
11215
Dianne Hackborn36124872009-10-08 16:22:03 -070011216 // Not running -- get it started, and enqueue this service record
11217 // to be executed when the app comes up.
11218 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11219 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011220 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011221 + r.appInfo.packageName + "/"
11222 + r.appInfo.uid + " for service "
11223 + r.intent.getIntent() + ": process is bad");
11224 bringDownServiceLocked(r, true);
11225 return false;
11226 }
11227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011228 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011229 mPendingServices.add(r);
11230 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011232 return true;
11233 }
11234
11235 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011236 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 //r.dump(" ");
11238
11239 // Does it still need to run?
11240 if (!force && r.startRequested) {
11241 return;
11242 }
11243 if (r.connections.size() > 0) {
11244 if (!force) {
11245 // XXX should probably keep a count of the number of auto-create
11246 // connections directly in the service.
11247 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11248 while (it.hasNext()) {
11249 ConnectionRecord cr = it.next();
11250 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11251 return;
11252 }
11253 }
11254 }
11255
11256 // Report to all of the connections that the service is no longer
11257 // available.
11258 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11259 while (it.hasNext()) {
11260 ConnectionRecord c = it.next();
11261 try {
11262 // todo: shouldn't be a synchronous call!
11263 c.conn.connected(r.name, null);
11264 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011265 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 " to connection " + c.conn.asBinder() +
11267 " (in " + c.binding.client.processName + ")", e);
11268 }
11269 }
11270 }
11271
11272 // Tell the service that it has been unbound.
11273 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11274 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11275 while (it.hasNext()) {
11276 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011277 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 + ": hasBound=" + ibr.hasBound);
11279 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11280 try {
11281 bumpServiceExecutingLocked(r);
11282 updateOomAdjLocked(r.app);
11283 ibr.hasBound = false;
11284 r.app.thread.scheduleUnbindService(r,
11285 ibr.intent.getIntent());
11286 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011287 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011288 + r.shortName, e);
11289 serviceDoneExecutingLocked(r, true);
11290 }
11291 }
11292 }
11293 }
11294
Joe Onorato8a9b2202010-02-26 18:56:32 -080011295 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011296 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011297 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011298 System.identityHashCode(r), r.shortName,
11299 (r.app != null) ? r.app.pid : -1);
11300
11301 mServices.remove(r.name);
11302 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011303 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011304 r.totalRestartCount = 0;
11305 unscheduleServiceRestartLocked(r);
11306
11307 // Also make sure it is not on the pending list.
11308 int N = mPendingServices.size();
11309 for (int i=0; i<N; i++) {
11310 if (mPendingServices.get(i) == r) {
11311 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011312 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 TAG, "Removed pending service: " + r.shortName);
11314 i--;
11315 N--;
11316 }
11317 }
11318
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011319 r.cancelNotification();
11320 r.isForeground = false;
11321 r.foregroundId = 0;
11322 r.foregroundNoti = null;
11323
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011324 // Clear start entries.
11325 r.deliveredStarts.clear();
11326 r.pendingStarts.clear();
11327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011328 if (r.app != null) {
11329 synchronized (r.stats.getBatteryStats()) {
11330 r.stats.stopLaunchedLocked();
11331 }
11332 r.app.services.remove(r);
11333 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011335 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011336 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011337 bumpServiceExecutingLocked(r);
11338 mStoppingServices.add(r);
11339 updateOomAdjLocked(r.app);
11340 r.app.thread.scheduleStopService(r);
11341 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011342 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011343 + r.shortName, e);
11344 serviceDoneExecutingLocked(r, true);
11345 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011346 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011348 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011349 TAG, "Removed service that has no process: " + r.shortName);
11350 }
11351 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011352 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011353 TAG, "Removed service that is not running: " + r.shortName);
11354 }
11355 }
11356
11357 ComponentName startServiceLocked(IApplicationThread caller,
11358 Intent service, String resolvedType,
11359 int callingPid, int callingUid) {
11360 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011361 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 + " type=" + resolvedType + " args=" + service.getExtras());
11363
11364 if (caller != null) {
11365 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11366 if (callerApp == null) {
11367 throw new SecurityException(
11368 "Unable to find app for caller " + caller
11369 + " (pid=" + Binder.getCallingPid()
11370 + ") when starting service " + service);
11371 }
11372 }
11373
11374 ServiceLookupResult res =
11375 retrieveServiceLocked(service, resolvedType,
11376 callingPid, callingUid);
11377 if (res == null) {
11378 return null;
11379 }
11380 if (res.record == null) {
11381 return new ComponentName("!", res.permission != null
11382 ? res.permission : "private to package");
11383 }
11384 ServiceRecord r = res.record;
11385 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011386 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387 + r.shortName);
11388 }
11389 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011390 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011391 r.lastStartId++;
11392 if (r.lastStartId < 1) {
11393 r.lastStartId = 1;
11394 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011395 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011396 r.lastActivity = SystemClock.uptimeMillis();
11397 synchronized (r.stats.getBatteryStats()) {
11398 r.stats.startRunningLocked();
11399 }
11400 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11401 return new ComponentName("!", "Service process is bad");
11402 }
11403 return r.name;
11404 }
11405 }
11406
11407 public ComponentName startService(IApplicationThread caller, Intent service,
11408 String resolvedType) {
11409 // Refuse possible leaked file descriptors
11410 if (service != null && service.hasFileDescriptors() == true) {
11411 throw new IllegalArgumentException("File descriptors passed in Intent");
11412 }
11413
11414 synchronized(this) {
11415 final int callingPid = Binder.getCallingPid();
11416 final int callingUid = Binder.getCallingUid();
11417 final long origId = Binder.clearCallingIdentity();
11418 ComponentName res = startServiceLocked(caller, service,
11419 resolvedType, callingPid, callingUid);
11420 Binder.restoreCallingIdentity(origId);
11421 return res;
11422 }
11423 }
11424
11425 ComponentName startServiceInPackage(int uid,
11426 Intent service, String resolvedType) {
11427 synchronized(this) {
11428 final long origId = Binder.clearCallingIdentity();
11429 ComponentName res = startServiceLocked(null, service,
11430 resolvedType, -1, uid);
11431 Binder.restoreCallingIdentity(origId);
11432 return res;
11433 }
11434 }
11435
11436 public int stopService(IApplicationThread caller, Intent service,
11437 String resolvedType) {
11438 // Refuse possible leaked file descriptors
11439 if (service != null && service.hasFileDescriptors() == true) {
11440 throw new IllegalArgumentException("File descriptors passed in Intent");
11441 }
11442
11443 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011444 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011445 + " type=" + resolvedType);
11446
11447 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11448 if (caller != null && callerApp == null) {
11449 throw new SecurityException(
11450 "Unable to find app for caller " + caller
11451 + " (pid=" + Binder.getCallingPid()
11452 + ") when stopping service " + service);
11453 }
11454
11455 // If this service is active, make sure it is stopped.
11456 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11457 if (r != null) {
11458 if (r.record != null) {
11459 synchronized (r.record.stats.getBatteryStats()) {
11460 r.record.stats.stopRunningLocked();
11461 }
11462 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011463 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011464 final long origId = Binder.clearCallingIdentity();
11465 bringDownServiceLocked(r.record, false);
11466 Binder.restoreCallingIdentity(origId);
11467 return 1;
11468 }
11469 return -1;
11470 }
11471 }
11472
11473 return 0;
11474 }
11475
11476 public IBinder peekService(Intent service, String resolvedType) {
11477 // Refuse possible leaked file descriptors
11478 if (service != null && service.hasFileDescriptors() == true) {
11479 throw new IllegalArgumentException("File descriptors passed in Intent");
11480 }
11481
11482 IBinder ret = null;
11483
11484 synchronized(this) {
11485 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11486
11487 if (r != null) {
11488 // r.record is null if findServiceLocked() failed the caller permission check
11489 if (r.record == null) {
11490 throw new SecurityException(
11491 "Permission Denial: Accessing service " + r.record.name
11492 + " from pid=" + Binder.getCallingPid()
11493 + ", uid=" + Binder.getCallingUid()
11494 + " requires " + r.permission);
11495 }
11496 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11497 if (ib != null) {
11498 ret = ib.binder;
11499 }
11500 }
11501 }
11502
11503 return ret;
11504 }
11505
11506 public boolean stopServiceToken(ComponentName className, IBinder token,
11507 int startId) {
11508 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011509 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011510 + " " + token + " startId=" + startId);
11511 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011512 if (r != null) {
11513 if (startId >= 0) {
11514 // Asked to only stop if done with all work. Note that
11515 // to avoid leaks, we will take this as dropping all
11516 // start items up to and including this one.
11517 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11518 if (si != null) {
11519 while (r.deliveredStarts.size() > 0) {
11520 if (r.deliveredStarts.remove(0) == si) {
11521 break;
11522 }
11523 }
11524 }
11525
11526 if (r.lastStartId != startId) {
11527 return false;
11528 }
11529
11530 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011531 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011532 + " is last, but have " + r.deliveredStarts.size()
11533 + " remaining args");
11534 }
11535 }
11536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011537 synchronized (r.stats.getBatteryStats()) {
11538 r.stats.stopRunningLocked();
11539 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011540 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 }
11542 final long origId = Binder.clearCallingIdentity();
11543 bringDownServiceLocked(r, false);
11544 Binder.restoreCallingIdentity(origId);
11545 return true;
11546 }
11547 }
11548 return false;
11549 }
11550
11551 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011552 int id, Notification notification, boolean removeNotification) {
11553 final long origId = Binder.clearCallingIdentity();
11554 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011555 synchronized(this) {
11556 ServiceRecord r = findServiceLocked(className, token);
11557 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011558 if (id != 0) {
11559 if (notification == null) {
11560 throw new IllegalArgumentException("null notification");
11561 }
11562 if (r.foregroundId != id) {
11563 r.cancelNotification();
11564 r.foregroundId = id;
11565 }
11566 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11567 r.foregroundNoti = notification;
11568 r.isForeground = true;
11569 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 if (r.app != null) {
11571 updateServiceForegroundLocked(r.app, true);
11572 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011573 } else {
11574 if (r.isForeground) {
11575 r.isForeground = false;
11576 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011577 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011578 updateServiceForegroundLocked(r.app, true);
11579 }
11580 }
11581 if (removeNotification) {
11582 r.cancelNotification();
11583 r.foregroundId = 0;
11584 r.foregroundNoti = null;
11585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011586 }
11587 }
11588 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011589 } finally {
11590 Binder.restoreCallingIdentity(origId);
11591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011592 }
11593
11594 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11595 boolean anyForeground = false;
11596 for (ServiceRecord sr : (HashSet<ServiceRecord>)proc.services) {
11597 if (sr.isForeground) {
11598 anyForeground = true;
11599 break;
11600 }
11601 }
11602 if (anyForeground != proc.foregroundServices) {
11603 proc.foregroundServices = anyForeground;
11604 if (oomAdj) {
11605 updateOomAdjLocked();
11606 }
11607 }
11608 }
11609
11610 public int bindService(IApplicationThread caller, IBinder token,
11611 Intent service, String resolvedType,
11612 IServiceConnection connection, int flags) {
11613 // Refuse possible leaked file descriptors
11614 if (service != null && service.hasFileDescriptors() == true) {
11615 throw new IllegalArgumentException("File descriptors passed in Intent");
11616 }
11617
11618 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011619 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 + " type=" + resolvedType + " conn=" + connection.asBinder()
11621 + " flags=0x" + Integer.toHexString(flags));
11622 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11623 if (callerApp == null) {
11624 throw new SecurityException(
11625 "Unable to find app for caller " + caller
11626 + " (pid=" + Binder.getCallingPid()
11627 + ") when binding service " + service);
11628 }
11629
11630 HistoryRecord activity = null;
11631 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011632 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011634 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011635 return 0;
11636 }
11637 activity = (HistoryRecord)mHistory.get(aindex);
11638 }
11639
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011640 int clientLabel = 0;
11641 PendingIntent clientIntent = null;
11642
11643 if (callerApp.info.uid == Process.SYSTEM_UID) {
11644 // Hacky kind of thing -- allow system stuff to tell us
11645 // what they are, so we can report this elsewhere for
11646 // others to know why certain services are running.
11647 try {
11648 clientIntent = (PendingIntent)service.getParcelableExtra(
11649 Intent.EXTRA_CLIENT_INTENT);
11650 } catch (RuntimeException e) {
11651 }
11652 if (clientIntent != null) {
11653 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11654 if (clientLabel != 0) {
11655 // There are no useful extras in the intent, trash them.
11656 // System code calling with this stuff just needs to know
11657 // this will happen.
11658 service = service.cloneFilter();
11659 }
11660 }
11661 }
11662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663 ServiceLookupResult res =
11664 retrieveServiceLocked(service, resolvedType,
11665 Binder.getCallingPid(), Binder.getCallingUid());
11666 if (res == null) {
11667 return 0;
11668 }
11669 if (res.record == null) {
11670 return -1;
11671 }
11672 ServiceRecord s = res.record;
11673
11674 final long origId = Binder.clearCallingIdentity();
11675
11676 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011677 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011678 + s.shortName);
11679 }
11680
11681 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11682 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011683 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011684
11685 IBinder binder = connection.asBinder();
11686 s.connections.put(binder, c);
11687 b.connections.add(c);
11688 if (activity != null) {
11689 if (activity.connections == null) {
11690 activity.connections = new HashSet<ConnectionRecord>();
11691 }
11692 activity.connections.add(c);
11693 }
11694 b.client.connections.add(c);
11695 mServiceConnections.put(binder, c);
11696
11697 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11698 s.lastActivity = SystemClock.uptimeMillis();
11699 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11700 return 0;
11701 }
11702 }
11703
11704 if (s.app != null) {
11705 // This could have made the service more important.
11706 updateOomAdjLocked(s.app);
11707 }
11708
Joe Onorato8a9b2202010-02-26 18:56:32 -080011709 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011710 + ": received=" + b.intent.received
11711 + " apps=" + b.intent.apps.size()
11712 + " doRebind=" + b.intent.doRebind);
11713
11714 if (s.app != null && b.intent.received) {
11715 // Service is already running, so we can immediately
11716 // publish the connection.
11717 try {
11718 c.conn.connected(s.name, b.intent.binder);
11719 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011720 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011721 + " to connection " + c.conn.asBinder()
11722 + " (in " + c.binding.client.processName + ")", e);
11723 }
11724
11725 // If this is the first app connected back to this binding,
11726 // and the service had previously asked to be told when
11727 // rebound, then do so.
11728 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11729 requestServiceBindingLocked(s, b.intent, true);
11730 }
11731 } else if (!b.intent.requested) {
11732 requestServiceBindingLocked(s, b.intent, false);
11733 }
11734
11735 Binder.restoreCallingIdentity(origId);
11736 }
11737
11738 return 1;
11739 }
11740
11741 private void removeConnectionLocked(
11742 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11743 IBinder binder = c.conn.asBinder();
11744 AppBindRecord b = c.binding;
11745 ServiceRecord s = b.service;
11746 s.connections.remove(binder);
11747 b.connections.remove(c);
11748 if (c.activity != null && c.activity != skipAct) {
11749 if (c.activity.connections != null) {
11750 c.activity.connections.remove(c);
11751 }
11752 }
11753 if (b.client != skipApp) {
11754 b.client.connections.remove(c);
11755 }
11756 mServiceConnections.remove(binder);
11757
11758 if (b.connections.size() == 0) {
11759 b.intent.apps.remove(b.client);
11760 }
11761
Joe Onorato8a9b2202010-02-26 18:56:32 -080011762 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 + ": shouldUnbind=" + b.intent.hasBound);
11764 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11765 && b.intent.hasBound) {
11766 try {
11767 bumpServiceExecutingLocked(s);
11768 updateOomAdjLocked(s.app);
11769 b.intent.hasBound = false;
11770 // Assume the client doesn't want to know about a rebind;
11771 // we will deal with that later if it asks for one.
11772 b.intent.doRebind = false;
11773 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11774 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011775 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011776 serviceDoneExecutingLocked(s, true);
11777 }
11778 }
11779
11780 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11781 bringDownServiceLocked(s, false);
11782 }
11783 }
11784
11785 public boolean unbindService(IServiceConnection connection) {
11786 synchronized (this) {
11787 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011788 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011789 ConnectionRecord r = mServiceConnections.get(binder);
11790 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011791 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011792 + connection.asBinder());
11793 return false;
11794 }
11795
11796 final long origId = Binder.clearCallingIdentity();
11797
11798 removeConnectionLocked(r, null, null);
11799
11800 if (r.binding.service.app != null) {
11801 // This could have made the service less important.
11802 updateOomAdjLocked(r.binding.service.app);
11803 }
11804
11805 Binder.restoreCallingIdentity(origId);
11806 }
11807
11808 return true;
11809 }
11810
11811 public void publishService(IBinder token, Intent intent, IBinder service) {
11812 // Refuse possible leaked file descriptors
11813 if (intent != null && intent.hasFileDescriptors() == true) {
11814 throw new IllegalArgumentException("File descriptors passed in Intent");
11815 }
11816
11817 synchronized(this) {
11818 if (!(token instanceof ServiceRecord)) {
11819 throw new IllegalArgumentException("Invalid service token");
11820 }
11821 ServiceRecord r = (ServiceRecord)token;
11822
11823 final long origId = Binder.clearCallingIdentity();
11824
Joe Onorato8a9b2202010-02-26 18:56:32 -080011825 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011826 + " " + intent + ": " + service);
11827 if (r != null) {
11828 Intent.FilterComparison filter
11829 = new Intent.FilterComparison(intent);
11830 IntentBindRecord b = r.bindings.get(filter);
11831 if (b != null && !b.received) {
11832 b.binder = service;
11833 b.requested = true;
11834 b.received = true;
11835 if (r.connections.size() > 0) {
11836 Iterator<ConnectionRecord> it
11837 = r.connections.values().iterator();
11838 while (it.hasNext()) {
11839 ConnectionRecord c = it.next();
11840 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011841 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011842 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011843 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011844 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011845 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 TAG, "Published intent: " + intent);
11847 continue;
11848 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011849 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 try {
11851 c.conn.connected(r.name, service);
11852 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011853 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011854 " to connection " + c.conn.asBinder() +
11855 " (in " + c.binding.client.processName + ")", e);
11856 }
11857 }
11858 }
11859 }
11860
11861 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11862
11863 Binder.restoreCallingIdentity(origId);
11864 }
11865 }
11866 }
11867
11868 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11869 // Refuse possible leaked file descriptors
11870 if (intent != null && intent.hasFileDescriptors() == true) {
11871 throw new IllegalArgumentException("File descriptors passed in Intent");
11872 }
11873
11874 synchronized(this) {
11875 if (!(token instanceof ServiceRecord)) {
11876 throw new IllegalArgumentException("Invalid service token");
11877 }
11878 ServiceRecord r = (ServiceRecord)token;
11879
11880 final long origId = Binder.clearCallingIdentity();
11881
11882 if (r != null) {
11883 Intent.FilterComparison filter
11884 = new Intent.FilterComparison(intent);
11885 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011886 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011887 + " at " + b + ": apps="
11888 + (b != null ? b.apps.size() : 0));
11889 if (b != null) {
11890 if (b.apps.size() > 0) {
11891 // Applications have already bound since the last
11892 // unbind, so just rebind right here.
11893 requestServiceBindingLocked(r, b, true);
11894 } else {
11895 // Note to tell the service the next time there is
11896 // a new client.
11897 b.doRebind = true;
11898 }
11899 }
11900
11901 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11902
11903 Binder.restoreCallingIdentity(origId);
11904 }
11905 }
11906 }
11907
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011908 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 synchronized(this) {
11910 if (!(token instanceof ServiceRecord)) {
11911 throw new IllegalArgumentException("Invalid service token");
11912 }
11913 ServiceRecord r = (ServiceRecord)token;
11914 boolean inStopping = mStoppingServices.contains(token);
11915 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011916 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011917 + ": nesting=" + r.executeNesting
11918 + ", inStopping=" + inStopping);
11919 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011920 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011921 + " with incorrect token: given " + token
11922 + ", expected " + r);
11923 return;
11924 }
11925
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011926 if (type == 1) {
11927 // This is a call from a service start... take care of
11928 // book-keeping.
11929 r.callStart = true;
11930 switch (res) {
11931 case Service.START_STICKY_COMPATIBILITY:
11932 case Service.START_STICKY: {
11933 // We are done with the associated start arguments.
11934 r.findDeliveredStart(startId, true);
11935 // Don't stop if killed.
11936 r.stopIfKilled = false;
11937 break;
11938 }
11939 case Service.START_NOT_STICKY: {
11940 // We are done with the associated start arguments.
11941 r.findDeliveredStart(startId, true);
11942 if (r.lastStartId == startId) {
11943 // There is no more work, and this service
11944 // doesn't want to hang around if killed.
11945 r.stopIfKilled = true;
11946 }
11947 break;
11948 }
11949 case Service.START_REDELIVER_INTENT: {
11950 // We'll keep this item until they explicitly
11951 // call stop for it, but keep track of the fact
11952 // that it was delivered.
11953 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11954 if (si != null) {
11955 si.deliveryCount = 0;
11956 si.doneExecutingCount++;
11957 // Don't stop if killed.
11958 r.stopIfKilled = true;
11959 }
11960 break;
11961 }
11962 default:
11963 throw new IllegalArgumentException(
11964 "Unknown service start result: " + res);
11965 }
11966 if (res == Service.START_STICKY_COMPATIBILITY) {
11967 r.callStart = false;
11968 }
11969 }
11970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011971 final long origId = Binder.clearCallingIdentity();
11972 serviceDoneExecutingLocked(r, inStopping);
11973 Binder.restoreCallingIdentity(origId);
11974 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011975 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011976 + " with token " + token);
11977 }
11978 }
11979 }
11980
11981 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
11982 r.executeNesting--;
11983 if (r.executeNesting <= 0 && r.app != null) {
11984 r.app.executingServices.remove(r);
11985 if (r.app.executingServices.size() == 0) {
11986 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11987 }
11988 if (inStopping) {
11989 mStoppingServices.remove(r);
11990 }
11991 updateOomAdjLocked(r.app);
11992 }
11993 }
11994
11995 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011996 String anrMessage = null;
11997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011998 synchronized(this) {
11999 if (proc.executingServices.size() == 0 || proc.thread == null) {
12000 return;
12001 }
12002 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12003 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12004 ServiceRecord timeout = null;
12005 long nextTime = 0;
12006 while (it.hasNext()) {
12007 ServiceRecord sr = it.next();
12008 if (sr.executingStart < maxTime) {
12009 timeout = sr;
12010 break;
12011 }
12012 if (sr.executingStart > nextTime) {
12013 nextTime = sr.executingStart;
12014 }
12015 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012016 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012017 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012018 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012019 } else {
12020 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12021 msg.obj = proc;
12022 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12023 }
12024 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012025
12026 if (anrMessage != null) {
12027 appNotResponding(proc, null, null, anrMessage);
12028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012029 }
12030
12031 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012032 // BACKUP AND RESTORE
12033 // =========================================================
12034
12035 // Cause the target app to be launched if necessary and its backup agent
12036 // instantiated. The backup agent will invoke backupAgentCreated() on the
12037 // activity manager to announce its creation.
12038 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012039 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012040 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12041
12042 synchronized(this) {
12043 // !!! TODO: currently no check here that we're already bound
12044 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12045 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12046 synchronized (stats) {
12047 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12048 }
12049
12050 BackupRecord r = new BackupRecord(ss, app, backupMode);
12051 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12052 // startProcessLocked() returns existing proc's record if it's already running
12053 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012054 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012055 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012056 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012057 return false;
12058 }
12059
12060 r.app = proc;
12061 mBackupTarget = r;
12062 mBackupAppName = app.packageName;
12063
Christopher Tate6fa95972009-06-05 18:43:55 -070012064 // Try not to kill the process during backup
12065 updateOomAdjLocked(proc);
12066
Christopher Tate181fafa2009-05-14 11:12:14 -070012067 // If the process is already attached, schedule the creation of the backup agent now.
12068 // If it is not yet live, this will be done when it attaches to the framework.
12069 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012070 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012071 try {
12072 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12073 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012074 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012075 }
12076 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012077 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012078 }
12079 // Invariants: at this point, the target app process exists and the application
12080 // is either already running or in the process of coming up. mBackupTarget and
12081 // mBackupAppName describe the app, so that when it binds back to the AM we
12082 // know that it's scheduled for a backup-agent operation.
12083 }
12084
12085 return true;
12086 }
12087
12088 // A backup agent has just come up
12089 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012090 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012091 + " = " + agent);
12092
12093 synchronized(this) {
12094 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012095 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012096 return;
12097 }
12098
Christopher Tate043dadc2009-06-02 16:11:00 -070012099 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012100 try {
12101 IBackupManager bm = IBackupManager.Stub.asInterface(
12102 ServiceManager.getService(Context.BACKUP_SERVICE));
12103 bm.agentConnected(agentPackageName, agent);
12104 } catch (RemoteException e) {
12105 // can't happen; the backup manager service is local
12106 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012107 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012108 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012109 } finally {
12110 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012111 }
12112 }
12113 }
12114
12115 // done with this agent
12116 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012117 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012118 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012119 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012120 return;
12121 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012122
12123 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012124 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012125 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012126 return;
12127 }
12128
Christopher Tate181fafa2009-05-14 11:12:14 -070012129 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012130 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012131 return;
12132 }
12133
Christopher Tate6fa95972009-06-05 18:43:55 -070012134 ProcessRecord proc = mBackupTarget.app;
12135 mBackupTarget = null;
12136 mBackupAppName = null;
12137
12138 // Not backing this app up any more; reset its OOM adjustment
12139 updateOomAdjLocked(proc);
12140
Christopher Tatec7b31e32009-06-10 15:49:30 -070012141 // If the app crashed during backup, 'thread' will be null here
12142 if (proc.thread != null) {
12143 try {
12144 proc.thread.scheduleDestroyBackupAgent(appInfo);
12145 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012146 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012147 e.printStackTrace();
12148 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012149 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012150 }
12151 }
12152 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012153 // BROADCASTS
12154 // =========================================================
12155
Josh Bartel7f208742010-02-25 11:01:44 -060012156 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012157 List cur) {
12158 final ContentResolver resolver = mContext.getContentResolver();
12159 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12160 if (list == null) {
12161 return cur;
12162 }
12163 int N = list.size();
12164 for (int i=0; i<N; i++) {
12165 Intent intent = list.get(i);
12166 if (filter.match(resolver, intent, true, TAG) >= 0) {
12167 if (cur == null) {
12168 cur = new ArrayList<Intent>();
12169 }
12170 cur.add(intent);
12171 }
12172 }
12173 return cur;
12174 }
12175
12176 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012177 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012178 + mBroadcastsScheduled);
12179
12180 if (mBroadcastsScheduled) {
12181 return;
12182 }
12183 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12184 mBroadcastsScheduled = true;
12185 }
12186
12187 public Intent registerReceiver(IApplicationThread caller,
12188 IIntentReceiver receiver, IntentFilter filter, String permission) {
12189 synchronized(this) {
12190 ProcessRecord callerApp = null;
12191 if (caller != null) {
12192 callerApp = getRecordForAppLocked(caller);
12193 if (callerApp == null) {
12194 throw new SecurityException(
12195 "Unable to find app for caller " + caller
12196 + " (pid=" + Binder.getCallingPid()
12197 + ") when registering receiver " + receiver);
12198 }
12199 }
12200
12201 List allSticky = null;
12202
12203 // Look for any matching sticky broadcasts...
12204 Iterator actions = filter.actionsIterator();
12205 if (actions != null) {
12206 while (actions.hasNext()) {
12207 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012208 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012209 }
12210 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012211 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012212 }
12213
12214 // The first sticky in the list is returned directly back to
12215 // the client.
12216 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12217
Joe Onorato8a9b2202010-02-26 18:56:32 -080012218 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012219 + ": " + sticky);
12220
12221 if (receiver == null) {
12222 return sticky;
12223 }
12224
12225 ReceiverList rl
12226 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12227 if (rl == null) {
12228 rl = new ReceiverList(this, callerApp,
12229 Binder.getCallingPid(),
12230 Binder.getCallingUid(), receiver);
12231 if (rl.app != null) {
12232 rl.app.receivers.add(rl);
12233 } else {
12234 try {
12235 receiver.asBinder().linkToDeath(rl, 0);
12236 } catch (RemoteException e) {
12237 return sticky;
12238 }
12239 rl.linkedToDeath = true;
12240 }
12241 mRegisteredReceivers.put(receiver.asBinder(), rl);
12242 }
12243 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12244 rl.add(bf);
12245 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012246 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012247 }
12248 mReceiverResolver.addFilter(bf);
12249
12250 // Enqueue broadcasts for all existing stickies that match
12251 // this filter.
12252 if (allSticky != null) {
12253 ArrayList receivers = new ArrayList();
12254 receivers.add(bf);
12255
12256 int N = allSticky.size();
12257 for (int i=0; i<N; i++) {
12258 Intent intent = (Intent)allSticky.get(i);
12259 BroadcastRecord r = new BroadcastRecord(intent, null,
12260 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012261 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012262 if (mParallelBroadcasts.size() == 0) {
12263 scheduleBroadcastsLocked();
12264 }
12265 mParallelBroadcasts.add(r);
12266 }
12267 }
12268
12269 return sticky;
12270 }
12271 }
12272
12273 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012274 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012275
12276 boolean doNext = false;
12277
12278 synchronized(this) {
12279 ReceiverList rl
12280 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12281 if (rl != null) {
12282 if (rl.curBroadcast != null) {
12283 BroadcastRecord r = rl.curBroadcast;
12284 doNext = finishReceiverLocked(
12285 receiver.asBinder(), r.resultCode, r.resultData,
12286 r.resultExtras, r.resultAbort, true);
12287 }
12288
12289 if (rl.app != null) {
12290 rl.app.receivers.remove(rl);
12291 }
12292 removeReceiverLocked(rl);
12293 if (rl.linkedToDeath) {
12294 rl.linkedToDeath = false;
12295 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12296 }
12297 }
12298 }
12299
12300 if (!doNext) {
12301 return;
12302 }
12303
12304 final long origId = Binder.clearCallingIdentity();
12305 processNextBroadcast(false);
12306 trimApplications();
12307 Binder.restoreCallingIdentity(origId);
12308 }
12309
12310 void removeReceiverLocked(ReceiverList rl) {
12311 mRegisteredReceivers.remove(rl.receiver.asBinder());
12312 int N = rl.size();
12313 for (int i=0; i<N; i++) {
12314 mReceiverResolver.removeFilter(rl.get(i));
12315 }
12316 }
12317
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012318 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12319 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12320 ProcessRecord r = mLruProcesses.get(i);
12321 if (r.thread != null) {
12322 try {
12323 r.thread.dispatchPackageBroadcast(cmd, packages);
12324 } catch (RemoteException ex) {
12325 }
12326 }
12327 }
12328 }
12329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012330 private final int broadcastIntentLocked(ProcessRecord callerApp,
12331 String callerPackage, Intent intent, String resolvedType,
12332 IIntentReceiver resultTo, int resultCode, String resultData,
12333 Bundle map, String requiredPermission,
12334 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12335 intent = new Intent(intent);
12336
Joe Onorato8a9b2202010-02-26 18:56:32 -080012337 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012338 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12339 + " ordered=" + ordered);
12340 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012341 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012342 }
12343
12344 // Handle special intents: if this broadcast is from the package
12345 // manager about a package being removed, we need to remove all of
12346 // its activities from the history stack.
12347 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12348 intent.getAction());
12349 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12350 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012351 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012352 || uidRemoved) {
12353 if (checkComponentPermission(
12354 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12355 callingPid, callingUid, -1)
12356 == PackageManager.PERMISSION_GRANTED) {
12357 if (uidRemoved) {
12358 final Bundle intentExtras = intent.getExtras();
12359 final int uid = intentExtras != null
12360 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12361 if (uid >= 0) {
12362 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12363 synchronized (bs) {
12364 bs.removeUidStatsLocked(uid);
12365 }
12366 }
12367 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012368 // If resources are unvailble just force stop all
12369 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012370 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012371 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12372 if (list != null && (list.length > 0)) {
12373 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012374 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012375 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012376 sendPackageBroadcastLocked(
12377 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012378 }
12379 } else {
12380 Uri data = intent.getData();
12381 String ssp;
12382 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12383 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12384 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012385 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012386 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012387 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12388 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12389 new String[] {ssp});
12390 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012391 }
12392 }
12393 }
12394 } else {
12395 String msg = "Permission Denial: " + intent.getAction()
12396 + " broadcast from " + callerPackage + " (pid=" + callingPid
12397 + ", uid=" + callingUid + ")"
12398 + " requires "
12399 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012400 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012401 throw new SecurityException(msg);
12402 }
12403 }
12404
12405 /*
12406 * If this is the time zone changed action, queue up a message that will reset the timezone
12407 * of all currently running processes. This message will get queued up before the broadcast
12408 * happens.
12409 */
12410 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12411 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12412 }
12413
Dianne Hackborn854060af2009-07-09 18:14:31 -070012414 /*
12415 * Prevent non-system code (defined here to be non-persistent
12416 * processes) from sending protected broadcasts.
12417 */
12418 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12419 || callingUid == Process.SHELL_UID || callingUid == 0) {
12420 // Always okay.
12421 } else if (callerApp == null || !callerApp.persistent) {
12422 try {
12423 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12424 intent.getAction())) {
12425 String msg = "Permission Denial: not allowed to send broadcast "
12426 + intent.getAction() + " from pid="
12427 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012428 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012429 throw new SecurityException(msg);
12430 }
12431 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012432 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012433 return BROADCAST_SUCCESS;
12434 }
12435 }
12436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012437 // Add to the sticky list if requested.
12438 if (sticky) {
12439 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12440 callingPid, callingUid)
12441 != PackageManager.PERMISSION_GRANTED) {
12442 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12443 + callingPid + ", uid=" + callingUid
12444 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012445 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012446 throw new SecurityException(msg);
12447 }
12448 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012449 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012450 + " and enforce permission " + requiredPermission);
12451 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12452 }
12453 if (intent.getComponent() != null) {
12454 throw new SecurityException(
12455 "Sticky broadcasts can't target a specific component");
12456 }
12457 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12458 if (list == null) {
12459 list = new ArrayList<Intent>();
12460 mStickyBroadcasts.put(intent.getAction(), list);
12461 }
12462 int N = list.size();
12463 int i;
12464 for (i=0; i<N; i++) {
12465 if (intent.filterEquals(list.get(i))) {
12466 // This sticky already exists, replace it.
12467 list.set(i, new Intent(intent));
12468 break;
12469 }
12470 }
12471 if (i >= N) {
12472 list.add(new Intent(intent));
12473 }
12474 }
12475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012476 // Figure out who all will receive this broadcast.
12477 List receivers = null;
12478 List<BroadcastFilter> registeredReceivers = null;
12479 try {
12480 if (intent.getComponent() != null) {
12481 // Broadcast is going to one specific receiver class...
12482 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012483 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012484 if (ai != null) {
12485 receivers = new ArrayList();
12486 ResolveInfo ri = new ResolveInfo();
12487 ri.activityInfo = ai;
12488 receivers.add(ri);
12489 }
12490 } else {
12491 // Need to resolve the intent to interested receivers...
12492 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12493 == 0) {
12494 receivers =
12495 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012496 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012497 }
Mihai Preda074edef2009-05-18 17:13:31 +020012498 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012499 }
12500 } catch (RemoteException ex) {
12501 // pm is in same process, this will never happen.
12502 }
12503
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012504 final boolean replacePending =
12505 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12506
Joe Onorato8a9b2202010-02-26 18:56:32 -080012507 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012508 + " replacePending=" + replacePending);
12509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012510 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12511 if (!ordered && NR > 0) {
12512 // If we are not serializing this broadcast, then send the
12513 // registered receivers separately so they don't wait for the
12514 // components to be launched.
12515 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12516 callerPackage, callingPid, callingUid, requiredPermission,
12517 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012518 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012519 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012520 TAG, "Enqueueing parallel broadcast " + r
12521 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012522 boolean replaced = false;
12523 if (replacePending) {
12524 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12525 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012526 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012527 "***** DROPPING PARALLEL: " + intent);
12528 mParallelBroadcasts.set(i, r);
12529 replaced = true;
12530 break;
12531 }
12532 }
12533 }
12534 if (!replaced) {
12535 mParallelBroadcasts.add(r);
12536 scheduleBroadcastsLocked();
12537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012538 registeredReceivers = null;
12539 NR = 0;
12540 }
12541
12542 // Merge into one list.
12543 int ir = 0;
12544 if (receivers != null) {
12545 // A special case for PACKAGE_ADDED: do not allow the package
12546 // being added to see this broadcast. This prevents them from
12547 // using this as a back door to get run as soon as they are
12548 // installed. Maybe in the future we want to have a special install
12549 // broadcast or such for apps, but we'd like to deliberately make
12550 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012551 String skipPackages[] = null;
12552 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12553 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12554 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12555 Uri data = intent.getData();
12556 if (data != null) {
12557 String pkgName = data.getSchemeSpecificPart();
12558 if (pkgName != null) {
12559 skipPackages = new String[] { pkgName };
12560 }
12561 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012562 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012563 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012564 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012565 if (skipPackages != null && (skipPackages.length > 0)) {
12566 for (String skipPackage : skipPackages) {
12567 if (skipPackage != null) {
12568 int NT = receivers.size();
12569 for (int it=0; it<NT; it++) {
12570 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12571 if (curt.activityInfo.packageName.equals(skipPackage)) {
12572 receivers.remove(it);
12573 it--;
12574 NT--;
12575 }
12576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012577 }
12578 }
12579 }
12580
12581 int NT = receivers != null ? receivers.size() : 0;
12582 int it = 0;
12583 ResolveInfo curt = null;
12584 BroadcastFilter curr = null;
12585 while (it < NT && ir < NR) {
12586 if (curt == null) {
12587 curt = (ResolveInfo)receivers.get(it);
12588 }
12589 if (curr == null) {
12590 curr = registeredReceivers.get(ir);
12591 }
12592 if (curr.getPriority() >= curt.priority) {
12593 // Insert this broadcast record into the final list.
12594 receivers.add(it, curr);
12595 ir++;
12596 curr = null;
12597 it++;
12598 NT++;
12599 } else {
12600 // Skip to the next ResolveInfo in the final list.
12601 it++;
12602 curt = null;
12603 }
12604 }
12605 }
12606 while (ir < NR) {
12607 if (receivers == null) {
12608 receivers = new ArrayList();
12609 }
12610 receivers.add(registeredReceivers.get(ir));
12611 ir++;
12612 }
12613
12614 if ((receivers != null && receivers.size() > 0)
12615 || resultTo != null) {
12616 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12617 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012618 receivers, resultTo, resultCode, resultData, map, ordered,
12619 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012620 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012621 TAG, "Enqueueing ordered broadcast " + r
12622 + ": prev had " + mOrderedBroadcasts.size());
12623 if (DEBUG_BROADCAST) {
12624 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012625 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012626 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012627 boolean replaced = false;
12628 if (replacePending) {
12629 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12630 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012631 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012632 "***** DROPPING ORDERED: " + intent);
12633 mOrderedBroadcasts.set(i, r);
12634 replaced = true;
12635 break;
12636 }
12637 }
12638 }
12639 if (!replaced) {
12640 mOrderedBroadcasts.add(r);
12641 scheduleBroadcastsLocked();
12642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012643 }
12644
12645 return BROADCAST_SUCCESS;
12646 }
12647
12648 public final int broadcastIntent(IApplicationThread caller,
12649 Intent intent, String resolvedType, IIntentReceiver resultTo,
12650 int resultCode, String resultData, Bundle map,
12651 String requiredPermission, boolean serialized, boolean sticky) {
12652 // Refuse possible leaked file descriptors
12653 if (intent != null && intent.hasFileDescriptors() == true) {
12654 throw new IllegalArgumentException("File descriptors passed in Intent");
12655 }
12656
12657 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012658 int flags = intent.getFlags();
12659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012660 if (!mSystemReady) {
12661 // if the caller really truly claims to know what they're doing, go
12662 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012663 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12664 intent = new Intent(intent);
12665 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12666 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012667 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012668 + " before boot completion");
12669 throw new IllegalStateException("Cannot broadcast before boot completed");
12670 }
12671 }
12672
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012673 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12674 throw new IllegalArgumentException(
12675 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12676 }
12677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012678 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12679 final int callingPid = Binder.getCallingPid();
12680 final int callingUid = Binder.getCallingUid();
12681 final long origId = Binder.clearCallingIdentity();
12682 int res = broadcastIntentLocked(callerApp,
12683 callerApp != null ? callerApp.info.packageName : null,
12684 intent, resolvedType, resultTo,
12685 resultCode, resultData, map, requiredPermission, serialized,
12686 sticky, callingPid, callingUid);
12687 Binder.restoreCallingIdentity(origId);
12688 return res;
12689 }
12690 }
12691
12692 int broadcastIntentInPackage(String packageName, int uid,
12693 Intent intent, String resolvedType, IIntentReceiver resultTo,
12694 int resultCode, String resultData, Bundle map,
12695 String requiredPermission, boolean serialized, boolean sticky) {
12696 synchronized(this) {
12697 final long origId = Binder.clearCallingIdentity();
12698 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12699 resultTo, resultCode, resultData, map, requiredPermission,
12700 serialized, sticky, -1, uid);
12701 Binder.restoreCallingIdentity(origId);
12702 return res;
12703 }
12704 }
12705
12706 public final void unbroadcastIntent(IApplicationThread caller,
12707 Intent intent) {
12708 // Refuse possible leaked file descriptors
12709 if (intent != null && intent.hasFileDescriptors() == true) {
12710 throw new IllegalArgumentException("File descriptors passed in Intent");
12711 }
12712
12713 synchronized(this) {
12714 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12715 != PackageManager.PERMISSION_GRANTED) {
12716 String msg = "Permission Denial: unbroadcastIntent() from pid="
12717 + Binder.getCallingPid()
12718 + ", uid=" + Binder.getCallingUid()
12719 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012720 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012721 throw new SecurityException(msg);
12722 }
12723 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12724 if (list != null) {
12725 int N = list.size();
12726 int i;
12727 for (i=0; i<N; i++) {
12728 if (intent.filterEquals(list.get(i))) {
12729 list.remove(i);
12730 break;
12731 }
12732 }
12733 }
12734 }
12735 }
12736
12737 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12738 String resultData, Bundle resultExtras, boolean resultAbort,
12739 boolean explicit) {
12740 if (mOrderedBroadcasts.size() == 0) {
12741 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012742 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012743 }
12744 return false;
12745 }
12746 BroadcastRecord r = mOrderedBroadcasts.get(0);
12747 if (r.receiver == null) {
12748 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012749 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012750 }
12751 return false;
12752 }
12753 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012754 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012755 return false;
12756 }
12757 int state = r.state;
12758 r.state = r.IDLE;
12759 if (state == r.IDLE) {
12760 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012761 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012762 }
12763 }
12764 r.receiver = null;
12765 r.intent.setComponent(null);
12766 if (r.curApp != null) {
12767 r.curApp.curReceiver = null;
12768 }
12769 if (r.curFilter != null) {
12770 r.curFilter.receiverList.curBroadcast = null;
12771 }
12772 r.curFilter = null;
12773 r.curApp = null;
12774 r.curComponent = null;
12775 r.curReceiver = null;
12776 mPendingBroadcast = null;
12777
12778 r.resultCode = resultCode;
12779 r.resultData = resultData;
12780 r.resultExtras = resultExtras;
12781 r.resultAbort = resultAbort;
12782
12783 // We will process the next receiver right now if this is finishing
12784 // an app receiver (which is always asynchronous) or after we have
12785 // come back from calling a receiver.
12786 return state == BroadcastRecord.APP_RECEIVE
12787 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12788 }
12789
12790 public void finishReceiver(IBinder who, int resultCode, String resultData,
12791 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012792 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012793
12794 // Refuse possible leaked file descriptors
12795 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12796 throw new IllegalArgumentException("File descriptors passed in Bundle");
12797 }
12798
12799 boolean doNext;
12800
12801 final long origId = Binder.clearCallingIdentity();
12802
12803 synchronized(this) {
12804 doNext = finishReceiverLocked(
12805 who, resultCode, resultData, resultExtras, resultAbort, true);
12806 }
12807
12808 if (doNext) {
12809 processNextBroadcast(false);
12810 }
12811 trimApplications();
12812
12813 Binder.restoreCallingIdentity(origId);
12814 }
12815
12816 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
12817 if (r.nextReceiver > 0) {
12818 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12819 if (curReceiver instanceof BroadcastFilter) {
12820 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012821 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012822 System.identityHashCode(r),
12823 r.intent.getAction(),
12824 r.nextReceiver - 1,
12825 System.identityHashCode(bf));
12826 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012827 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012828 System.identityHashCode(r),
12829 r.intent.getAction(),
12830 r.nextReceiver - 1,
12831 ((ResolveInfo)curReceiver).toString());
12832 }
12833 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012834 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012835 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012836 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012837 System.identityHashCode(r),
12838 r.intent.getAction(),
12839 r.nextReceiver,
12840 "NONE");
12841 }
12842 }
12843
12844 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012845 ProcessRecord app = null;
12846 String anrMessage = null;
12847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012848 synchronized (this) {
12849 if (mOrderedBroadcasts.size() == 0) {
12850 return;
12851 }
12852 long now = SystemClock.uptimeMillis();
12853 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012854 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012855 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012856 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080012857 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012858 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012859 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012860 return;
12861 }
12862
Joe Onorato8a9b2202010-02-26 18:56:32 -080012863 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012864 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012865 r.anrCount++;
12866
12867 // Current receiver has passed its expiration date.
12868 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012869 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012870 return;
12871 }
12872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012873 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012874 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012875 logBroadcastReceiverDiscard(r);
12876 if (curReceiver instanceof BroadcastFilter) {
12877 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12878 if (bf.receiverList.pid != 0
12879 && bf.receiverList.pid != MY_PID) {
12880 synchronized (this.mPidsSelfLocked) {
12881 app = this.mPidsSelfLocked.get(
12882 bf.receiverList.pid);
12883 }
12884 }
12885 } else {
12886 app = r.curApp;
12887 }
12888
12889 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012890 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012891 }
12892
12893 if (mPendingBroadcast == r) {
12894 mPendingBroadcast = null;
12895 }
12896
12897 // Move on to the next receiver.
12898 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12899 r.resultExtras, r.resultAbort, true);
12900 scheduleBroadcastsLocked();
12901 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012902
12903 if (anrMessage != null) {
12904 appNotResponding(app, null, null, anrMessage);
12905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012906 }
12907
12908 private final void processCurBroadcastLocked(BroadcastRecord r,
12909 ProcessRecord app) throws RemoteException {
12910 if (app.thread == null) {
12911 throw new RemoteException();
12912 }
12913 r.receiver = app.thread.asBinder();
12914 r.curApp = app;
12915 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012916 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012917
12918 // Tell the application to launch this receiver.
12919 r.intent.setComponent(r.curComponent);
12920
12921 boolean started = false;
12922 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012923 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012924 "Delivering to component " + r.curComponent
12925 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012926 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012927 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
12928 r.resultCode, r.resultData, r.resultExtras, r.ordered);
12929 started = true;
12930 } finally {
12931 if (!started) {
12932 r.receiver = null;
12933 r.curApp = null;
12934 app.curReceiver = null;
12935 }
12936 }
12937
12938 }
12939
12940 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012941 Intent intent, int resultCode, String data, Bundle extras,
12942 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012943 if (app != null && app.thread != null) {
12944 // If we have an app thread, do the call through that so it is
12945 // correctly ordered with other one-way calls.
12946 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012947 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012948 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012949 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012950 }
12951 }
12952
12953 private final void deliverToRegisteredReceiver(BroadcastRecord r,
12954 BroadcastFilter filter, boolean ordered) {
12955 boolean skip = false;
12956 if (filter.requiredPermission != null) {
12957 int perm = checkComponentPermission(filter.requiredPermission,
12958 r.callingPid, r.callingUid, -1);
12959 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012960 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012961 + r.intent.toString()
12962 + " from " + r.callerPackage + " (pid="
12963 + r.callingPid + ", uid=" + r.callingUid + ")"
12964 + " requires " + filter.requiredPermission
12965 + " due to registered receiver " + filter);
12966 skip = true;
12967 }
12968 }
12969 if (r.requiredPermission != null) {
12970 int perm = checkComponentPermission(r.requiredPermission,
12971 filter.receiverList.pid, filter.receiverList.uid, -1);
12972 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012973 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012974 + r.intent.toString()
12975 + " to " + filter.receiverList.app
12976 + " (pid=" + filter.receiverList.pid
12977 + ", uid=" + filter.receiverList.uid + ")"
12978 + " requires " + r.requiredPermission
12979 + " due to sender " + r.callerPackage
12980 + " (uid " + r.callingUid + ")");
12981 skip = true;
12982 }
12983 }
12984
12985 if (!skip) {
12986 // If this is not being sent as an ordered broadcast, then we
12987 // don't want to touch the fields that keep track of the current
12988 // state of ordered broadcasts.
12989 if (ordered) {
12990 r.receiver = filter.receiverList.receiver.asBinder();
12991 r.curFilter = filter;
12992 filter.receiverList.curBroadcast = r;
12993 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012994 if (filter.receiverList.app != null) {
12995 // Bump hosting application to no longer be in background
12996 // scheduling class. Note that we can't do that if there
12997 // isn't an app... but we can only be in that case for
12998 // things that directly call the IActivityManager API, which
12999 // are already core system stuff so don't matter for this.
13000 r.curApp = filter.receiverList.app;
13001 filter.receiverList.app.curReceiver = r;
13002 updateOomAdjLocked();
13003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013004 }
13005 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013006 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013007 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013008 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013009 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013010 }
13011 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13012 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013013 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013014 if (ordered) {
13015 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13016 }
13017 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013018 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013019 if (ordered) {
13020 r.receiver = null;
13021 r.curFilter = null;
13022 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013023 if (filter.receiverList.app != null) {
13024 filter.receiverList.app.curReceiver = null;
13025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013026 }
13027 }
13028 }
13029 }
13030
Dianne Hackborn12527f92009-11-11 17:39:50 -080013031 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13032 if (r.callingUid < 0) {
13033 // This was from a registerReceiver() call; ignore it.
13034 return;
13035 }
13036 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13037 MAX_BROADCAST_HISTORY-1);
13038 r.finishTime = SystemClock.uptimeMillis();
13039 mBroadcastHistory[0] = r;
13040 }
13041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013042 private final void processNextBroadcast(boolean fromMsg) {
13043 synchronized(this) {
13044 BroadcastRecord r;
13045
Joe Onorato8a9b2202010-02-26 18:56:32 -080013046 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013047 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013048 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013049
13050 updateCpuStats();
13051
13052 if (fromMsg) {
13053 mBroadcastsScheduled = false;
13054 }
13055
13056 // First, deliver any non-serialized broadcasts right away.
13057 while (mParallelBroadcasts.size() > 0) {
13058 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013059 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013060 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013061 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013062 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013063 for (int i=0; i<N; i++) {
13064 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013065 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013066 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013067 + target + ": " + r);
13068 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13069 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013070 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013071 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013072 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013073 }
13074
13075 // Now take care of the next serialized one...
13076
13077 // If we are waiting for a process to come up to handle the next
13078 // broadcast, then do nothing at this point. Just in case, we
13079 // check that the process we're waiting for still exists.
13080 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013081 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013082 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013083 + mPendingBroadcast.curApp);
13084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013085
13086 boolean isDead;
13087 synchronized (mPidsSelfLocked) {
13088 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13089 }
13090 if (!isDead) {
13091 // It's still alive, so keep waiting
13092 return;
13093 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013094 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013095 + " died before responding to broadcast");
13096 mPendingBroadcast = null;
13097 }
13098 }
13099
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013100 boolean looped = false;
13101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013102 do {
13103 if (mOrderedBroadcasts.size() == 0) {
13104 // No more broadcasts pending, so all done!
13105 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013106 if (looped) {
13107 // If we had finished the last ordered broadcast, then
13108 // make sure all processes have correct oom and sched
13109 // adjustments.
13110 updateOomAdjLocked();
13111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013112 return;
13113 }
13114 r = mOrderedBroadcasts.get(0);
13115 boolean forceReceive = false;
13116
13117 // Ensure that even if something goes awry with the timeout
13118 // detection, we catch "hung" broadcasts here, discard them,
13119 // and continue to make progress.
13120 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
13121 long now = SystemClock.uptimeMillis();
13122 if (r.dispatchTime > 0) {
13123 if ((numReceivers > 0) &&
13124 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013125 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013126 + " now=" + now
13127 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013128 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013129 + " intent=" + r.intent
13130 + " numReceivers=" + numReceivers
13131 + " nextReceiver=" + r.nextReceiver
13132 + " state=" + r.state);
13133 broadcastTimeout(); // forcibly finish this broadcast
13134 forceReceive = true;
13135 r.state = BroadcastRecord.IDLE;
13136 }
13137 }
13138
13139 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013140 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013141 "processNextBroadcast() called when not idle (state="
13142 + r.state + ")");
13143 return;
13144 }
13145
13146 if (r.receivers == null || r.nextReceiver >= numReceivers
13147 || r.resultAbort || forceReceive) {
13148 // No more receivers for this broadcast! Send the final
13149 // result if requested...
13150 if (r.resultTo != null) {
13151 try {
13152 if (DEBUG_BROADCAST) {
13153 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013154 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013155 + " seq=" + seq + " app=" + r.callerApp);
13156 }
13157 performReceive(r.callerApp, r.resultTo,
13158 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013159 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013160 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013161 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013162 }
13163 }
13164
Joe Onorato8a9b2202010-02-26 18:56:32 -080013165 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013166 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13167
Joe Onorato8a9b2202010-02-26 18:56:32 -080013168 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013169 + r);
13170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013171 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013172 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013173 mOrderedBroadcasts.remove(0);
13174 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013175 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013176 continue;
13177 }
13178 } while (r == null);
13179
13180 // Get the next receiver...
13181 int recIdx = r.nextReceiver++;
13182
13183 // Keep track of when this receiver started, and make sure there
13184 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013185 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013186 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013187 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013188
Joe Onorato8a9b2202010-02-26 18:56:32 -080013189 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013190 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013191 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013192 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013193 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013194 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013195 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013196 }
13197
13198 Object nextReceiver = r.receivers.get(recIdx);
13199 if (nextReceiver instanceof BroadcastFilter) {
13200 // Simple case: this is a registered receiver who gets
13201 // a direct call.
13202 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013203 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013204 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013205 + filter + ": " + r);
13206 deliverToRegisteredReceiver(r, filter, r.ordered);
13207 if (r.receiver == null || !r.ordered) {
13208 // The receiver has already finished, so schedule to
13209 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013210 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13211 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013212 r.state = BroadcastRecord.IDLE;
13213 scheduleBroadcastsLocked();
13214 }
13215 return;
13216 }
13217
13218 // Hard case: need to instantiate the receiver, possibly
13219 // starting its application process to host it.
13220
13221 ResolveInfo info =
13222 (ResolveInfo)nextReceiver;
13223
13224 boolean skip = false;
13225 int perm = checkComponentPermission(info.activityInfo.permission,
13226 r.callingPid, r.callingUid,
13227 info.activityInfo.exported
13228 ? -1 : info.activityInfo.applicationInfo.uid);
13229 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013230 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013231 + r.intent.toString()
13232 + " from " + r.callerPackage + " (pid=" + r.callingPid
13233 + ", uid=" + r.callingUid + ")"
13234 + " requires " + info.activityInfo.permission
13235 + " due to receiver " + info.activityInfo.packageName
13236 + "/" + info.activityInfo.name);
13237 skip = true;
13238 }
13239 if (r.callingUid != Process.SYSTEM_UID &&
13240 r.requiredPermission != null) {
13241 try {
13242 perm = ActivityThread.getPackageManager().
13243 checkPermission(r.requiredPermission,
13244 info.activityInfo.applicationInfo.packageName);
13245 } catch (RemoteException e) {
13246 perm = PackageManager.PERMISSION_DENIED;
13247 }
13248 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013249 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013250 + r.intent + " to "
13251 + info.activityInfo.applicationInfo.packageName
13252 + " requires " + r.requiredPermission
13253 + " due to sender " + r.callerPackage
13254 + " (uid " + r.callingUid + ")");
13255 skip = true;
13256 }
13257 }
13258 if (r.curApp != null && r.curApp.crashing) {
13259 // If the target process is crashing, just skip it.
13260 skip = true;
13261 }
13262
13263 if (skip) {
13264 r.receiver = null;
13265 r.curFilter = null;
13266 r.state = BroadcastRecord.IDLE;
13267 scheduleBroadcastsLocked();
13268 return;
13269 }
13270
13271 r.state = BroadcastRecord.APP_RECEIVE;
13272 String targetProcess = info.activityInfo.processName;
13273 r.curComponent = new ComponentName(
13274 info.activityInfo.applicationInfo.packageName,
13275 info.activityInfo.name);
13276 r.curReceiver = info.activityInfo;
13277
13278 // Is this receiver's application already running?
13279 ProcessRecord app = getProcessRecordLocked(targetProcess,
13280 info.activityInfo.applicationInfo.uid);
13281 if (app != null && app.thread != null) {
13282 try {
13283 processCurBroadcastLocked(r, app);
13284 return;
13285 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013286 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013287 + r.curComponent, e);
13288 }
13289
13290 // If a dead object exception was thrown -- fall through to
13291 // restart the application.
13292 }
13293
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013294 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013295 if ((r.curApp=startProcessLocked(targetProcess,
13296 info.activityInfo.applicationInfo, true,
13297 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013298 "broadcast", r.curComponent,
13299 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13300 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013301 // Ah, this recipient is unavailable. Finish it if necessary,
13302 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013303 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013304 + info.activityInfo.applicationInfo.packageName + "/"
13305 + info.activityInfo.applicationInfo.uid + " for broadcast "
13306 + r.intent + ": process is bad");
13307 logBroadcastReceiverDiscard(r);
13308 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13309 r.resultExtras, r.resultAbort, true);
13310 scheduleBroadcastsLocked();
13311 r.state = BroadcastRecord.IDLE;
13312 return;
13313 }
13314
13315 mPendingBroadcast = r;
13316 }
13317 }
13318
13319 // =========================================================
13320 // INSTRUMENTATION
13321 // =========================================================
13322
13323 public boolean startInstrumentation(ComponentName className,
13324 String profileFile, int flags, Bundle arguments,
13325 IInstrumentationWatcher watcher) {
13326 // Refuse possible leaked file descriptors
13327 if (arguments != null && arguments.hasFileDescriptors()) {
13328 throw new IllegalArgumentException("File descriptors passed in Bundle");
13329 }
13330
13331 synchronized(this) {
13332 InstrumentationInfo ii = null;
13333 ApplicationInfo ai = null;
13334 try {
13335 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013336 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013337 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013338 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013339 } catch (PackageManager.NameNotFoundException e) {
13340 }
13341 if (ii == null) {
13342 reportStartInstrumentationFailure(watcher, className,
13343 "Unable to find instrumentation info for: " + className);
13344 return false;
13345 }
13346 if (ai == null) {
13347 reportStartInstrumentationFailure(watcher, className,
13348 "Unable to find instrumentation target package: " + ii.targetPackage);
13349 return false;
13350 }
13351
13352 int match = mContext.getPackageManager().checkSignatures(
13353 ii.targetPackage, ii.packageName);
13354 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13355 String msg = "Permission Denial: starting instrumentation "
13356 + className + " from pid="
13357 + Binder.getCallingPid()
13358 + ", uid=" + Binder.getCallingPid()
13359 + " not allowed because package " + ii.packageName
13360 + " does not have a signature matching the target "
13361 + ii.targetPackage;
13362 reportStartInstrumentationFailure(watcher, className, msg);
13363 throw new SecurityException(msg);
13364 }
13365
13366 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013367 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013368 ProcessRecord app = addAppLocked(ai);
13369 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013370 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013371 app.instrumentationProfileFile = profileFile;
13372 app.instrumentationArguments = arguments;
13373 app.instrumentationWatcher = watcher;
13374 app.instrumentationResultClass = className;
13375 Binder.restoreCallingIdentity(origId);
13376 }
13377
13378 return true;
13379 }
13380
13381 /**
13382 * Report errors that occur while attempting to start Instrumentation. Always writes the
13383 * error to the logs, but if somebody is watching, send the report there too. This enables
13384 * the "am" command to report errors with more information.
13385 *
13386 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13387 * @param cn The component name of the instrumentation.
13388 * @param report The error report.
13389 */
13390 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13391 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013392 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013393 try {
13394 if (watcher != null) {
13395 Bundle results = new Bundle();
13396 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13397 results.putString("Error", report);
13398 watcher.instrumentationStatus(cn, -1, results);
13399 }
13400 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013401 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013402 }
13403 }
13404
13405 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13406 if (app.instrumentationWatcher != null) {
13407 try {
13408 // NOTE: IInstrumentationWatcher *must* be oneway here
13409 app.instrumentationWatcher.instrumentationFinished(
13410 app.instrumentationClass,
13411 resultCode,
13412 results);
13413 } catch (RemoteException e) {
13414 }
13415 }
13416 app.instrumentationWatcher = null;
13417 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013418 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013419 app.instrumentationProfileFile = null;
13420 app.instrumentationArguments = null;
13421
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013422 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013423 }
13424
13425 public void finishInstrumentation(IApplicationThread target,
13426 int resultCode, Bundle results) {
13427 // Refuse possible leaked file descriptors
13428 if (results != null && results.hasFileDescriptors()) {
13429 throw new IllegalArgumentException("File descriptors passed in Intent");
13430 }
13431
13432 synchronized(this) {
13433 ProcessRecord app = getRecordForAppLocked(target);
13434 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013435 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013436 return;
13437 }
13438 final long origId = Binder.clearCallingIdentity();
13439 finishInstrumentationLocked(app, resultCode, results);
13440 Binder.restoreCallingIdentity(origId);
13441 }
13442 }
13443
13444 // =========================================================
13445 // CONFIGURATION
13446 // =========================================================
13447
13448 public ConfigurationInfo getDeviceConfigurationInfo() {
13449 ConfigurationInfo config = new ConfigurationInfo();
13450 synchronized (this) {
13451 config.reqTouchScreen = mConfiguration.touchscreen;
13452 config.reqKeyboardType = mConfiguration.keyboard;
13453 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013454 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13455 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013456 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13457 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013458 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13459 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013460 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13461 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013462 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013463 }
13464 return config;
13465 }
13466
13467 public Configuration getConfiguration() {
13468 Configuration ci;
13469 synchronized(this) {
13470 ci = new Configuration(mConfiguration);
13471 }
13472 return ci;
13473 }
13474
13475 public void updateConfiguration(Configuration values) {
13476 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13477 "updateConfiguration()");
13478
13479 synchronized(this) {
13480 if (values == null && mWindowManager != null) {
13481 // sentinel: fetch the current configuration from the window manager
13482 values = mWindowManager.computeNewConfiguration();
13483 }
13484
13485 final long origId = Binder.clearCallingIdentity();
13486 updateConfigurationLocked(values, null);
13487 Binder.restoreCallingIdentity(origId);
13488 }
13489 }
13490
13491 /**
13492 * Do either or both things: (1) change the current configuration, and (2)
13493 * make sure the given activity is running with the (now) current
13494 * configuration. Returns true if the activity has been left running, or
13495 * false if <var>starting</var> is being destroyed to match the new
13496 * configuration.
13497 */
13498 public boolean updateConfigurationLocked(Configuration values,
13499 HistoryRecord starting) {
13500 int changes = 0;
13501
13502 boolean kept = true;
13503
13504 if (values != null) {
13505 Configuration newConfig = new Configuration(mConfiguration);
13506 changes = newConfig.updateFrom(values);
13507 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013508 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013509 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013510 }
13511
Doug Zongker2bec3d42009-12-04 12:52:44 -080013512 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013513
13514 if (values.locale != null) {
13515 saveLocaleLocked(values.locale,
13516 !values.locale.equals(mConfiguration.locale),
13517 values.userSetLocale);
13518 }
13519
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013520 mConfigurationSeq++;
13521 if (mConfigurationSeq <= 0) {
13522 mConfigurationSeq = 1;
13523 }
13524 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013525 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013526 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013527
13528 AttributeCache ac = AttributeCache.instance();
13529 if (ac != null) {
13530 ac.updateConfiguration(mConfiguration);
13531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013532
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013533 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13534 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13535 msg.obj = new Configuration(mConfiguration);
13536 mHandler.sendMessage(msg);
13537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013538
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013539 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13540 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013541 try {
13542 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013543 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013544 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013545 app.thread.scheduleConfigurationChanged(mConfiguration);
13546 }
13547 } catch (Exception e) {
13548 }
13549 }
13550 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013551 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13552 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013553 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13554 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013555 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13556 broadcastIntentLocked(null, null,
13557 new Intent(Intent.ACTION_LOCALE_CHANGED),
13558 null, null, 0, null, null,
13559 null, false, false, MY_PID, Process.SYSTEM_UID);
13560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013561 }
13562 }
13563
13564 if (changes != 0 && starting == null) {
13565 // If the configuration changed, and the caller is not already
13566 // in the process of starting an activity, then find the top
13567 // activity to check if its configuration needs to change.
13568 starting = topRunningActivityLocked(null);
13569 }
13570
13571 if (starting != null) {
13572 kept = ensureActivityConfigurationLocked(starting, changes);
13573 if (kept) {
13574 // If this didn't result in the starting activity being
13575 // destroyed, then we need to make sure at this point that all
13576 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013577 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013578 + ", ensuring others are correct.");
13579 ensureActivitiesVisibleLocked(starting, changes);
13580 }
13581 }
13582
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013583 if (values != null && mWindowManager != null) {
13584 mWindowManager.setNewConfiguration(mConfiguration);
13585 }
13586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013587 return kept;
13588 }
13589
13590 private final boolean relaunchActivityLocked(HistoryRecord r,
13591 int changes, boolean andResume) {
13592 List<ResultInfo> results = null;
13593 List<Intent> newIntents = null;
13594 if (andResume) {
13595 results = r.results;
13596 newIntents = r.newIntents;
13597 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013598 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013599 + " with results=" + results + " newIntents=" + newIntents
13600 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013601 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13602 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013603 r.task.taskId, r.shortComponentName);
13604
13605 r.startFreezingScreenLocked(r.app, 0);
13606
13607 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013608 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013609 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013610 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013611 // Note: don't need to call pauseIfSleepingLocked() here, because
13612 // the caller will only pass in 'andResume' if this activity is
13613 // currently resumed, which implies we aren't sleeping.
13614 } catch (RemoteException e) {
13615 return false;
13616 }
13617
13618 if (andResume) {
13619 r.results = null;
13620 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013621 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013622 }
13623
13624 return true;
13625 }
13626
13627 /**
13628 * Make sure the given activity matches the current configuration. Returns
13629 * false if the activity had to be destroyed. Returns true if the
13630 * configuration is the same, or the activity will remain running as-is
13631 * for whatever reason. Ensures the HistoryRecord is updated with the
13632 * correct configuration and all other bookkeeping is handled.
13633 */
13634 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13635 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013636 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013637 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13638 "Skipping config check (will change): " + r);
13639 return true;
13640 }
13641
Joe Onorato8a9b2202010-02-26 18:56:32 -080013642 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013643 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013644
13645 // Short circuit: if the two configurations are the exact same
13646 // object (the common case), then there is nothing to do.
13647 Configuration newConfig = mConfiguration;
13648 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013649 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013650 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013651 return true;
13652 }
13653
13654 // We don't worry about activities that are finishing.
13655 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013656 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013657 "Configuration doesn't matter in finishing " + r);
13658 r.stopFreezingScreenLocked(false);
13659 return true;
13660 }
13661
13662 // Okay we now are going to make this activity have the new config.
13663 // But then we need to figure out how it needs to deal with that.
13664 Configuration oldConfig = r.configuration;
13665 r.configuration = newConfig;
13666
13667 // If the activity isn't currently running, just leave the new
13668 // configuration and it will pick that up next time it starts.
13669 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013670 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013671 "Configuration doesn't matter not running " + r);
13672 r.stopFreezingScreenLocked(false);
13673 return true;
13674 }
13675
13676 // If the activity isn't persistent, there is a chance we will
13677 // need to restart it.
13678 if (!r.persistent) {
13679
13680 // Figure out what has changed between the two configurations.
13681 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013682 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013683 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013684 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013685 + Integer.toHexString(r.info.configChanges)
13686 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013687 }
13688 if ((changes&(~r.info.configChanges)) != 0) {
13689 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13690 r.configChangeFlags |= changes;
13691 r.startFreezingScreenLocked(r.app, globalChanges);
13692 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013693 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013694 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013695 destroyActivityLocked(r, true);
13696 } else if (r.state == ActivityState.PAUSING) {
13697 // A little annoying: we are waiting for this activity to
13698 // finish pausing. Let's not do anything now, but just
13699 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013700 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013701 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013702 r.configDestroy = true;
13703 return true;
13704 } else if (r.state == ActivityState.RESUMED) {
13705 // Try to optimize this case: the configuration is changing
13706 // and we need to restart the top, resumed activity.
13707 // Instead of doing the normal handshaking, just say
13708 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013709 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013710 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013711 relaunchActivityLocked(r, r.configChangeFlags, true);
13712 r.configChangeFlags = 0;
13713 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013714 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013715 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013716 relaunchActivityLocked(r, r.configChangeFlags, false);
13717 r.configChangeFlags = 0;
13718 }
13719
13720 // All done... tell the caller we weren't able to keep this
13721 // activity around.
13722 return false;
13723 }
13724 }
13725
13726 // Default case: the activity can handle this new configuration, so
13727 // hand it over. Note that we don't need to give it the new
13728 // configuration, since we always send configuration changes to all
13729 // process when they happen so it can just use whatever configuration
13730 // it last got.
13731 if (r.app != null && r.app.thread != null) {
13732 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013733 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013734 r.app.thread.scheduleActivityConfigurationChanged(r);
13735 } catch (RemoteException e) {
13736 // If process died, whatever.
13737 }
13738 }
13739 r.stopFreezingScreenLocked(false);
13740
13741 return true;
13742 }
13743
13744 /**
13745 * Save the locale. You must be inside a synchronized (this) block.
13746 */
13747 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13748 if(isDiff) {
13749 SystemProperties.set("user.language", l.getLanguage());
13750 SystemProperties.set("user.region", l.getCountry());
13751 }
13752
13753 if(isPersist) {
13754 SystemProperties.set("persist.sys.language", l.getLanguage());
13755 SystemProperties.set("persist.sys.country", l.getCountry());
13756 SystemProperties.set("persist.sys.localevar", l.getVariant());
13757 }
13758 }
13759
13760 // =========================================================
13761 // LIFETIME MANAGEMENT
13762 // =========================================================
13763
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013764 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13765 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013766 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013767 // This adjustment has already been computed. If we are calling
13768 // from the top, we may have already computed our adjustment with
13769 // an earlier hidden adjustment that isn't really for us... if
13770 // so, use the new hidden adjustment.
13771 if (!recursed && app.hidden) {
13772 app.curAdj = hiddenAdj;
13773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013774 return app.curAdj;
13775 }
13776
13777 if (app.thread == null) {
13778 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013779 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013780 return (app.curAdj=EMPTY_APP_ADJ);
13781 }
13782
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013783 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
13784 // The max adjustment doesn't allow this app to be anything
13785 // below foreground, so it is not worth doing work for it.
13786 app.adjType = "fixed";
13787 app.adjSeq = mAdjSeq;
13788 app.curRawAdj = app.maxAdj;
13789 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
13790 return (app.curAdj=app.maxAdj);
13791 }
13792
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013793 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013794 app.adjSource = null;
13795 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013796 app.empty = false;
13797 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013798
The Android Open Source Project4df24232009-03-05 14:34:35 -080013799 // Determine the importance of the process, starting with most
13800 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013801 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013802 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013803 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013804 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013805 // The last app on the list is the foreground app.
13806 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013807 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013808 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013809 } else if (app.instrumentationClass != null) {
13810 // Don't want to kill running instrumentation.
13811 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013812 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013813 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013814 } else if (app.persistentActivities > 0) {
13815 // Special persistent activities... shouldn't be used these days.
13816 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013817 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013818 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013819 } else if (app.curReceiver != null ||
13820 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13821 // An app that is currently receiving a broadcast also
13822 // counts as being in the foreground.
13823 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013824 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013825 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013826 } else if (app.executingServices.size() > 0) {
13827 // An app that is currently executing a service callback also
13828 // counts as being in the foreground.
13829 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013830 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013831 app.adjType = "exec-service";
13832 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013833 // The user is aware of this app, so make it visible.
13834 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013835 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013836 app.adjType = "foreground-service";
13837 } else if (app.forcingToForeground != null) {
13838 // The user is aware of this app, so make it visible.
13839 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013840 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013841 app.adjType = "force-foreground";
13842 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080013843 } else if (app == mHomeProcess) {
13844 // This process is hosting what we currently consider to be the
13845 // home app, so we don't want to let it go into the background.
13846 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013847 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013848 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013849 } else if ((N=app.activities.size()) != 0) {
13850 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013851 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013852 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013853 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013854 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013855 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013856 for (int j=0; j<N; j++) {
13857 if (((HistoryRecord)app.activities.get(j)).visible) {
13858 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013859 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013860 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013861 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013862 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013863 break;
13864 }
13865 }
13866 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013867 // A very not-needed process. If this is lower in the lru list,
13868 // we will push it in to the empty bucket.
13869 app.hidden = true;
13870 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013871 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013872 adj = hiddenAdj;
13873 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013874 }
13875
Joe Onorato8a9b2202010-02-26 18:56:32 -080013876 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013877
The Android Open Source Project4df24232009-03-05 14:34:35 -080013878 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013879 // there are applications dependent on our services or providers, but
13880 // this gives us a baseline and makes sure we don't get into an
13881 // infinite recursion.
13882 app.adjSeq = mAdjSeq;
13883 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013884
Christopher Tate6fa95972009-06-05 18:43:55 -070013885 if (mBackupTarget != null && app == mBackupTarget.app) {
13886 // If possible we want to avoid killing apps while they're being backed up
13887 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013888 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070013889 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013890 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013891 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013892 }
13893 }
13894
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013895 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
13896 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013897 final long now = SystemClock.uptimeMillis();
13898 // This process is more important if the top activity is
13899 // bound to the service.
13900 Iterator jt = app.services.iterator();
13901 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13902 ServiceRecord s = (ServiceRecord)jt.next();
13903 if (s.startRequested) {
13904 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13905 // This service has seen some activity within
13906 // recent memory, so we will keep its process ahead
13907 // of the background processes.
13908 if (adj > SECONDARY_SERVER_ADJ) {
13909 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013910 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013911 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013912 }
13913 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013914 // If we have let the service slide into the background
13915 // state, still have some text describing what it is doing
13916 // even though the service no longer has an impact.
13917 if (adj > SECONDARY_SERVER_ADJ) {
13918 app.adjType = "started-bg-services";
13919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013920 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013921 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
13922 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013923 Iterator<ConnectionRecord> kt
13924 = s.connections.values().iterator();
13925 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
13926 // XXX should compute this based on the max of
13927 // all connected clients.
13928 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013929 if (cr.binding.client == app) {
13930 // Binding to ourself is not interesting.
13931 continue;
13932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013933 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
13934 ProcessRecord client = cr.binding.client;
13935 int myHiddenAdj = hiddenAdj;
13936 if (myHiddenAdj > client.hiddenAdj) {
13937 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
13938 myHiddenAdj = client.hiddenAdj;
13939 } else {
13940 myHiddenAdj = VISIBLE_APP_ADJ;
13941 }
13942 }
13943 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013944 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013945 if (adj > clientAdj) {
13946 adj = clientAdj > VISIBLE_APP_ADJ
13947 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013948 if (!client.hidden) {
13949 app.hidden = false;
13950 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013951 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013952 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13953 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013954 app.adjSource = cr.binding.client;
13955 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013956 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013957 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13958 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13959 schedGroup = Process.THREAD_GROUP_DEFAULT;
13960 }
13961 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013962 }
13963 HistoryRecord a = cr.activity;
13964 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013965 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013966 //}
13967 if (a != null && adj > FOREGROUND_APP_ADJ &&
13968 (a.state == ActivityState.RESUMED
13969 || a.state == ActivityState.PAUSING)) {
13970 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013971 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013972 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013973 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013974 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13975 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013976 app.adjSource = a;
13977 app.adjTarget = s.serviceInfo.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013978 }
13979 }
13980 }
13981 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013982
13983 // Finally, f this process has active services running in it, we
13984 // would like to avoid killing it unless it would prevent the current
13985 // application from running. By default we put the process in
13986 // with the rest of the background processes; as we scan through
13987 // its services we may bump it up from there.
13988 if (adj > hiddenAdj) {
13989 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013990 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013991 app.adjType = "bg-services";
13992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013993 }
13994
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013995 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
13996 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013997 Iterator jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013998 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
13999 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014000 ContentProviderRecord cpr = (ContentProviderRecord)jt.next();
14001 if (cpr.clients.size() != 0) {
14002 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14003 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14004 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014005 if (client == app) {
14006 // Being our own client is not interesting.
14007 continue;
14008 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014009 int myHiddenAdj = hiddenAdj;
14010 if (myHiddenAdj > client.hiddenAdj) {
14011 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14012 myHiddenAdj = client.hiddenAdj;
14013 } else {
14014 myHiddenAdj = FOREGROUND_APP_ADJ;
14015 }
14016 }
14017 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014018 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014019 if (adj > clientAdj) {
14020 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014021 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014022 if (!client.hidden) {
14023 app.hidden = false;
14024 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014025 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014026 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14027 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014028 app.adjSource = client;
14029 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014030 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014031 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14032 schedGroup = Process.THREAD_GROUP_DEFAULT;
14033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014034 }
14035 }
14036 // If the provider has external (non-framework) process
14037 // dependencies, ensure that its adjustment is at least
14038 // FOREGROUND_APP_ADJ.
14039 if (cpr.externals != 0) {
14040 if (adj > FOREGROUND_APP_ADJ) {
14041 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014042 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014043 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014044 app.adjType = "provider";
14045 app.adjTarget = cpr.info.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014046 }
14047 }
14048 }
14049 }
14050
14051 app.curRawAdj = adj;
14052
Joe Onorato8a9b2202010-02-26 18:56:32 -080014053 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014054 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14055 if (adj > app.maxAdj) {
14056 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014057 if (app.maxAdj <= VISIBLE_APP_ADJ) {
14058 schedGroup = Process.THREAD_GROUP_DEFAULT;
14059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014060 }
14061
14062 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014063 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014065 return adj;
14066 }
14067
14068 /**
14069 * Ask a given process to GC right now.
14070 */
14071 final void performAppGcLocked(ProcessRecord app) {
14072 try {
14073 app.lastRequestedGc = SystemClock.uptimeMillis();
14074 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014075 if (app.reportLowMemory) {
14076 app.reportLowMemory = false;
14077 app.thread.scheduleLowMemory();
14078 } else {
14079 app.thread.processInBackground();
14080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014081 }
14082 } catch (Exception e) {
14083 // whatever.
14084 }
14085 }
14086
14087 /**
14088 * Returns true if things are idle enough to perform GCs.
14089 */
Josh Bartel7f208742010-02-25 11:01:44 -060014090 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014091 return mParallelBroadcasts.size() == 0
14092 && mOrderedBroadcasts.size() == 0
14093 && (mSleeping || (mResumedActivity != null &&
14094 mResumedActivity.idle));
14095 }
14096
14097 /**
14098 * Perform GCs on all processes that are waiting for it, but only
14099 * if things are idle.
14100 */
14101 final void performAppGcsLocked() {
14102 final int N = mProcessesToGc.size();
14103 if (N <= 0) {
14104 return;
14105 }
Josh Bartel7f208742010-02-25 11:01:44 -060014106 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014107 while (mProcessesToGc.size() > 0) {
14108 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014109 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
14110 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14111 <= SystemClock.uptimeMillis()) {
14112 // To avoid spamming the system, we will GC processes one
14113 // at a time, waiting a few seconds between each.
14114 performAppGcLocked(proc);
14115 scheduleAppGcsLocked();
14116 return;
14117 } else {
14118 // It hasn't been long enough since we last GCed this
14119 // process... put it in the list to wait for its time.
14120 addProcessToGcListLocked(proc);
14121 break;
14122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014123 }
14124 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014125
14126 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014127 }
14128 }
14129
14130 /**
14131 * If all looks good, perform GCs on all processes waiting for them.
14132 */
14133 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014134 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014135 performAppGcsLocked();
14136 return;
14137 }
14138 // Still not idle, wait some more.
14139 scheduleAppGcsLocked();
14140 }
14141
14142 /**
14143 * Schedule the execution of all pending app GCs.
14144 */
14145 final void scheduleAppGcsLocked() {
14146 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014147
14148 if (mProcessesToGc.size() > 0) {
14149 // Schedule a GC for the time to the next process.
14150 ProcessRecord proc = mProcessesToGc.get(0);
14151 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14152
14153 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14154 long now = SystemClock.uptimeMillis();
14155 if (when < (now+GC_TIMEOUT)) {
14156 when = now + GC_TIMEOUT;
14157 }
14158 mHandler.sendMessageAtTime(msg, when);
14159 }
14160 }
14161
14162 /**
14163 * Add a process to the array of processes waiting to be GCed. Keeps the
14164 * list in sorted order by the last GC time. The process can't already be
14165 * on the list.
14166 */
14167 final void addProcessToGcListLocked(ProcessRecord proc) {
14168 boolean added = false;
14169 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14170 if (mProcessesToGc.get(i).lastRequestedGc <
14171 proc.lastRequestedGc) {
14172 added = true;
14173 mProcessesToGc.add(i+1, proc);
14174 break;
14175 }
14176 }
14177 if (!added) {
14178 mProcessesToGc.add(0, proc);
14179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014180 }
14181
14182 /**
14183 * Set up to ask a process to GC itself. This will either do it
14184 * immediately, or put it on the list of processes to gc the next
14185 * time things are idle.
14186 */
14187 final void scheduleAppGcLocked(ProcessRecord app) {
14188 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014189 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014190 return;
14191 }
14192 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014193 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014194 scheduleAppGcsLocked();
14195 }
14196 }
14197
14198 private final boolean updateOomAdjLocked(
14199 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14200 app.hiddenAdj = hiddenAdj;
14201
14202 if (app.thread == null) {
14203 return true;
14204 }
14205
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014206 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014207
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014208 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014209 if (app.curRawAdj != app.setRawAdj) {
14210 if (app.curRawAdj > FOREGROUND_APP_ADJ
14211 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14212 // If this app is transitioning from foreground to
14213 // non-foreground, have it do a gc.
14214 scheduleAppGcLocked(app);
14215 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14216 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14217 // Likewise do a gc when an app is moving in to the
14218 // background (such as a service stopping).
14219 scheduleAppGcLocked(app);
14220 }
14221 app.setRawAdj = app.curRawAdj;
14222 }
14223 if (adj != app.setAdj) {
14224 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014225 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014226 TAG, "Set app " + app.processName +
14227 " oom adj to " + adj);
14228 app.setAdj = adj;
14229 } else {
14230 return false;
14231 }
14232 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014233 if (app.setSchedGroup != app.curSchedGroup) {
14234 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014235 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014236 "Setting process group of " + app.processName
14237 + " to " + app.curSchedGroup);
14238 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014239 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014240 try {
14241 Process.setProcessGroup(app.pid, app.curSchedGroup);
14242 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014243 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014244 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014245 e.printStackTrace();
14246 } finally {
14247 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014248 }
14249 }
14250 if (false) {
14251 if (app.thread != null) {
14252 try {
14253 app.thread.setSchedulingGroup(app.curSchedGroup);
14254 } catch (RemoteException e) {
14255 }
14256 }
14257 }
14258 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014259 }
14260
14261 return true;
14262 }
14263
14264 private final HistoryRecord resumedAppLocked() {
14265 HistoryRecord resumedActivity = mResumedActivity;
14266 if (resumedActivity == null || resumedActivity.app == null) {
14267 resumedActivity = mPausingActivity;
14268 if (resumedActivity == null || resumedActivity.app == null) {
14269 resumedActivity = topRunningActivityLocked(null);
14270 }
14271 }
14272 return resumedActivity;
14273 }
14274
14275 private final boolean updateOomAdjLocked(ProcessRecord app) {
14276 final HistoryRecord TOP_ACT = resumedAppLocked();
14277 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14278 int curAdj = app.curAdj;
14279 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14280 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14281
14282 mAdjSeq++;
14283
14284 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14285 if (res) {
14286 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14287 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14288 if (nowHidden != wasHidden) {
14289 // Changed to/from hidden state, so apps after it in the LRU
14290 // list may also be changed.
14291 updateOomAdjLocked();
14292 }
14293 }
14294 return res;
14295 }
14296
14297 private final boolean updateOomAdjLocked() {
14298 boolean didOomAdj = true;
14299 final HistoryRecord TOP_ACT = resumedAppLocked();
14300 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14301
14302 if (false) {
14303 RuntimeException e = new RuntimeException();
14304 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014305 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014306 }
14307
14308 mAdjSeq++;
14309
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014310 // Let's determine how many processes we have running vs.
14311 // how many slots we have for background processes; we may want
14312 // to put multiple processes in a slot of there are enough of
14313 // them.
14314 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14315 int factor = (mLruProcesses.size()-4)/numSlots;
14316 if (factor < 1) factor = 1;
14317 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014318 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014320 // First try updating the OOM adjustment for each of the
14321 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014322 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014323 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14324 while (i > 0) {
14325 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014326 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014327 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014328 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014329 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014330 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014331 step++;
14332 if (step >= factor) {
14333 step = 0;
14334 curHiddenAdj++;
14335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014336 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014337 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014338 if (!app.killedBackground) {
14339 numHidden++;
14340 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014341 Slog.i(TAG, "No longer want " + app.processName
14342 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014343 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14344 app.processName, app.setAdj, "too many background");
14345 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014346 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014347 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014348 }
14349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014350 } else {
14351 didOomAdj = false;
14352 }
14353 }
14354
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014355 // If we return false, we will fall back on killing processes to
14356 // have a fixed limit. Do this if a limit has been requested; else
14357 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014358 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14359 }
14360
14361 private final void trimApplications() {
14362 synchronized (this) {
14363 int i;
14364
14365 // First remove any unused application processes whose package
14366 // has been removed.
14367 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14368 final ProcessRecord app = mRemovedProcesses.get(i);
14369 if (app.activities.size() == 0
14370 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014371 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014372 TAG, "Exiting empty application process "
14373 + app.processName + " ("
14374 + (app.thread != null ? app.thread.asBinder() : null)
14375 + ")\n");
14376 if (app.pid > 0 && app.pid != MY_PID) {
14377 Process.killProcess(app.pid);
14378 } else {
14379 try {
14380 app.thread.scheduleExit();
14381 } catch (Exception e) {
14382 // Ignore exceptions.
14383 }
14384 }
14385 cleanUpApplicationRecordLocked(app, false, -1);
14386 mRemovedProcesses.remove(i);
14387
14388 if (app.persistent) {
14389 if (app.persistent) {
14390 addAppLocked(app.info);
14391 }
14392 }
14393 }
14394 }
14395
14396 // Now try updating the OOM adjustment for each of the
14397 // application processes based on their current state.
14398 // If the setOomAdj() API is not supported, then go with our
14399 // back-up plan...
14400 if (!updateOomAdjLocked()) {
14401
14402 // Count how many processes are running services.
14403 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014404 for (i=mLruProcesses.size()-1; i>=0; i--) {
14405 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014406
14407 if (app.persistent || app.services.size() != 0
14408 || app.curReceiver != null
14409 || app.persistentActivities > 0) {
14410 // Don't count processes holding services against our
14411 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014412 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014413 TAG, "Not trimming app " + app + " with services: "
14414 + app.services);
14415 numServiceProcs++;
14416 }
14417 }
14418
14419 int curMaxProcs = mProcessLimit;
14420 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14421 if (mAlwaysFinishActivities) {
14422 curMaxProcs = 1;
14423 }
14424 curMaxProcs += numServiceProcs;
14425
14426 // Quit as many processes as we can to get down to the desired
14427 // process count. First remove any processes that no longer
14428 // have activites running in them.
14429 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014430 i<mLruProcesses.size()
14431 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014432 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014433 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014434 // Quit an application only if it is not currently
14435 // running any activities.
14436 if (!app.persistent && app.activities.size() == 0
14437 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014438 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014439 TAG, "Exiting empty application process "
14440 + app.processName + " ("
14441 + (app.thread != null ? app.thread.asBinder() : null)
14442 + ")\n");
14443 if (app.pid > 0 && app.pid != MY_PID) {
14444 Process.killProcess(app.pid);
14445 } else {
14446 try {
14447 app.thread.scheduleExit();
14448 } catch (Exception e) {
14449 // Ignore exceptions.
14450 }
14451 }
14452 // todo: For now we assume the application is not buggy
14453 // or evil, and will quit as a result of our request.
14454 // Eventually we need to drive this off of the death
14455 // notification, and kill the process if it takes too long.
14456 cleanUpApplicationRecordLocked(app, false, i);
14457 i--;
14458 }
14459 }
14460
14461 // If we still have too many processes, now from the least
14462 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014463 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014464 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014465 " of " + curMaxProcs + " processes");
14466 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014467 i<mLruProcesses.size()
14468 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014469 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014470 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014471 // Quit the application only if we have a state saved for
14472 // all of its activities.
14473 boolean canQuit = !app.persistent && app.curReceiver == null
14474 && app.services.size() == 0
14475 && app.persistentActivities == 0;
14476 int NUMA = app.activities.size();
14477 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014478 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014479 TAG, "Looking to quit " + app.processName);
14480 for (j=0; j<NUMA && canQuit; j++) {
14481 HistoryRecord r = (HistoryRecord)app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014482 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014483 TAG, " " + r.intent.getComponent().flattenToShortString()
14484 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14485 canQuit = (r.haveState || !r.stateNotNeeded)
14486 && !r.visible && r.stopped;
14487 }
14488 if (canQuit) {
14489 // Finish all of the activities, and then the app itself.
14490 for (j=0; j<NUMA; j++) {
14491 HistoryRecord r = (HistoryRecord)app.activities.get(j);
14492 if (!r.finishing) {
14493 destroyActivityLocked(r, false);
14494 }
14495 r.resultTo = null;
14496 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014497 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014498 + app.processName + " ("
14499 + (app.thread != null ? app.thread.asBinder() : null)
14500 + ")\n");
14501 if (app.pid > 0 && app.pid != MY_PID) {
14502 Process.killProcess(app.pid);
14503 } else {
14504 try {
14505 app.thread.scheduleExit();
14506 } catch (Exception e) {
14507 // Ignore exceptions.
14508 }
14509 }
14510 // todo: For now we assume the application is not buggy
14511 // or evil, and will quit as a result of our request.
14512 // Eventually we need to drive this off of the death
14513 // notification, and kill the process if it takes too long.
14514 cleanUpApplicationRecordLocked(app, false, i);
14515 i--;
14516 //dump();
14517 }
14518 }
14519
14520 }
14521
14522 int curMaxActivities = MAX_ACTIVITIES;
14523 if (mAlwaysFinishActivities) {
14524 curMaxActivities = 1;
14525 }
14526
14527 // Finally, if there are too many activities now running, try to
14528 // finish as many as we can to get back down to the limit.
14529 for ( i=0;
14530 i<mLRUActivities.size()
14531 && mLRUActivities.size() > curMaxActivities;
14532 i++) {
14533 final HistoryRecord r
14534 = (HistoryRecord)mLRUActivities.get(i);
14535
14536 // We can finish this one if we have its icicle saved and
14537 // it is not persistent.
14538 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14539 && r.stopped && !r.persistent && !r.finishing) {
14540 final int origSize = mLRUActivities.size();
14541 destroyActivityLocked(r, true);
14542
14543 // This will remove it from the LRU list, so keep
14544 // our index at the same value. Note that this check to
14545 // see if the size changes is just paranoia -- if
14546 // something unexpected happens, we don't want to end up
14547 // in an infinite loop.
14548 if (origSize > mLRUActivities.size()) {
14549 i--;
14550 }
14551 }
14552 }
14553 }
14554 }
14555
14556 /** This method sends the specified signal to each of the persistent apps */
14557 public void signalPersistentProcesses(int sig) throws RemoteException {
14558 if (sig != Process.SIGNAL_USR1) {
14559 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14560 }
14561
14562 synchronized (this) {
14563 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14564 != PackageManager.PERMISSION_GRANTED) {
14565 throw new SecurityException("Requires permission "
14566 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14567 }
14568
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014569 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14570 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014571 if (r.thread != null && r.persistent) {
14572 Process.sendSignal(r.pid, sig);
14573 }
14574 }
14575 }
14576 }
14577
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014578 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014579 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014580
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014581 try {
14582 synchronized (this) {
14583 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14584 // its own permission.
14585 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14586 != PackageManager.PERMISSION_GRANTED) {
14587 throw new SecurityException("Requires permission "
14588 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014589 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014590
14591 if (start && fd == null) {
14592 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014593 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014594
14595 ProcessRecord proc = null;
14596 try {
14597 int pid = Integer.parseInt(process);
14598 synchronized (mPidsSelfLocked) {
14599 proc = mPidsSelfLocked.get(pid);
14600 }
14601 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014602 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014603
14604 if (proc == null) {
14605 HashMap<String, SparseArray<ProcessRecord>> all
14606 = mProcessNames.getMap();
14607 SparseArray<ProcessRecord> procs = all.get(process);
14608 if (procs != null && procs.size() > 0) {
14609 proc = procs.valueAt(0);
14610 }
14611 }
14612
14613 if (proc == null || proc.thread == null) {
14614 throw new IllegalArgumentException("Unknown process: " + process);
14615 }
14616
14617 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14618 if (isSecure) {
14619 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14620 throw new SecurityException("Process not debuggable: " + proc);
14621 }
14622 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014623
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014624 proc.thread.profilerControl(start, path, fd);
14625 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014626 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014627 }
14628 } catch (RemoteException e) {
14629 throw new IllegalStateException("Process disappeared");
14630 } finally {
14631 if (fd != null) {
14632 try {
14633 fd.close();
14634 } catch (IOException e) {
14635 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014636 }
14637 }
14638 }
14639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014640 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14641 public void monitor() {
14642 synchronized (this) { }
14643 }
14644}