blob: c61f90ec7ed0d3495a94fe412c2232f1e0905a0a [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
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
20import com.android.internal.app.HeavyWeightSwitcherActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070022import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import com.android.server.IntentResolver;
24import com.android.server.ProcessMap;
25import com.android.server.ProcessStats;
26import com.android.server.SystemServer;
27import com.android.server.Watchdog;
28import com.android.server.WindowManagerService;
29
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020037import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070039import android.app.IActivityController;
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -080040import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
51import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070052import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080053import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020054import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080055import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.content.ComponentName;
57import android.content.ContentResolver;
58import android.content.Context;
59import android.content.Intent;
60import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070061import android.content.IIntentReceiver;
62import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070063import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ActivityInfo;
65import android.content.pm.ApplicationInfo;
66import android.content.pm.ConfigurationInfo;
67import android.content.pm.IPackageDataObserver;
68import android.content.pm.IPackageManager;
69import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080070import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070072import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.ProviderInfo;
74import android.content.pm.ResolveInfo;
75import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070076import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.res.Configuration;
78import android.graphics.Bitmap;
79import android.net.Uri;
80import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080081import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080082import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070083import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080084import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080086import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.FileUtils;
88import android.os.Handler;
89import android.os.IBinder;
90import android.os.IPermissionController;
91import android.os.Looper;
92import android.os.Message;
93import android.os.Parcel;
94import android.os.ParcelFileDescriptor;
95import android.os.PowerManager;
96import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070097import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.os.RemoteException;
99import android.os.ServiceManager;
100import android.os.SystemClock;
101import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.util.Config;
104import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800105import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800106import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.util.PrintWriterPrinter;
108import android.util.SparseArray;
109import android.view.Gravity;
110import android.view.LayoutInflater;
111import android.view.View;
112import android.view.WindowManager;
113import android.view.WindowManagerPolicy;
114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import java.io.File;
116import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200118import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800119import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.PrintWriter;
121import java.lang.IllegalStateException;
122import java.lang.ref.WeakReference;
123import java.util.ArrayList;
124import java.util.HashMap;
125import java.util.HashSet;
126import java.util.Iterator;
127import java.util.List;
128import java.util.Locale;
129import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700130import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700131import java.util.concurrent.atomic.AtomicBoolean;
132import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133
134public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
135 static final String TAG = "ActivityManager";
136 static final boolean DEBUG = false;
137 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
138 static final boolean DEBUG_SWITCH = localLOGV || false;
139 static final boolean DEBUG_TASKS = localLOGV || false;
140 static final boolean DEBUG_PAUSE = localLOGV || false;
141 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
142 static final boolean DEBUG_TRANSITION = localLOGV || false;
143 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700144 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean DEBUG_SERVICE = localLOGV || false;
146 static final boolean DEBUG_VISBILITY = localLOGV || false;
147 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700148 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800149 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700151 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700152 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700153 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final boolean VALIDATE_TOKENS = false;
155 static final boolean SHOW_ACTIVITY_START_TIME = true;
156
157 // Control over CPU and battery monitoring.
158 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
159 static final boolean MONITOR_CPU_USAGE = true;
160 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
161 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
162 static final boolean MONITOR_THREAD_CPU_USAGE = false;
163
Dianne Hackborn1655be42009-05-08 14:29:01 -0700164 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700165 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 private static final String SYSTEM_SECURE = "ro.secure";
168
169 // This is the maximum number of application processes we would like
170 // to have running. Due to the asynchronous nature of things, we can
171 // temporarily go beyond this limit.
172 static final int MAX_PROCESSES = 2;
173
174 // Set to false to leave processes running indefinitely, relying on
175 // the kernel killing them as resources are required.
176 static final boolean ENFORCE_PROCESS_LIMIT = false;
177
178 // This is the maximum number of activities that we would like to have
179 // running at a given time.
180 static final int MAX_ACTIVITIES = 20;
181
182 // Maximum number of recent tasks that we can remember.
183 static final int MAX_RECENT_TASKS = 20;
184
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700185 // Amount of time after a call to stopAppSwitches() during which we will
186 // prevent further untrusted switches from happening.
187 static final long APP_SWITCH_DELAY_TIME = 5*1000;
188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 // How long until we reset a task when the user returns to it. Currently
190 // 30 minutes.
191 static final long ACTIVITY_INACTIVE_RESET_TIME = 1000*60*30;
192
193 // Set to true to disable the icon that is shown while a new activity
194 // is being started.
195 static final boolean SHOW_APP_STARTING_ICON = true;
196
197 // How long we wait until giving up on the last activity to pause. This
198 // is short because it directly impacts the responsiveness of starting the
199 // next activity.
200 static final int PAUSE_TIMEOUT = 500;
201
202 /**
203 * How long we can hold the launch wake lock before giving up.
204 */
205 static final int LAUNCH_TIMEOUT = 10*1000;
206
207 // How long we wait for a launched process to attach to the activity manager
208 // before we decide it's never going to come up for real.
209 static final int PROC_START_TIMEOUT = 10*1000;
210
211 // How long we wait until giving up on the last activity telling us it
212 // is idle.
213 static final int IDLE_TIMEOUT = 10*1000;
214
215 // How long to wait after going idle before forcing apps to GC.
216 static final int GC_TIMEOUT = 5*1000;
217
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700218 // The minimum amount of time between successive GC requests for a process.
219 static final int GC_MIN_INTERVAL = 60*1000;
220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 // How long we wait until giving up on an activity telling us it has
222 // finished destroying itself.
223 static final int DESTROY_TIMEOUT = 10*1000;
224
225 // How long we allow a receiver to run before giving up on it.
226 static final int BROADCAST_TIMEOUT = 10*1000;
227
228 // How long we wait for a service to finish executing.
229 static final int SERVICE_TIMEOUT = 20*1000;
230
231 // How long a service needs to be running until restarting its process
232 // is no longer considered to be a relaunch of the service.
233 static final int SERVICE_RESTART_DURATION = 5*1000;
234
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700235 // How long a service needs to be running until it will start back at
236 // SERVICE_RESTART_DURATION after being killed.
237 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
238
239 // Multiplying factor to increase restart duration time by, for each time
240 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
241 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
242
243 // The minimum amount of time between restarting services that we allow.
244 // That is, when multiple services are restarting, we won't allow each
245 // to restart less than this amount of time from the last one.
246 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 // Maximum amount of time for there to be no activity on a service before
249 // we consider it non-essential and allow its process to go on the
250 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700251 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252
253 // How long we wait until we timeout on key dispatching.
254 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
255
256 // The minimum time we allow between crashes, for us to consider this
257 // application to be bad and stop and its services and reject broadcasts.
258 static final int MIN_CRASH_INTERVAL = 60*1000;
259
260 // How long we wait until we timeout on key dispatching during instrumentation.
261 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
262
263 // OOM adjustments for processes in various states:
264
265 // This is a process without anything currently running in it. Definitely
266 // the first to go! Value set in system/rootdir/init.rc on startup.
267 // This value is initalized in the constructor, careful when refering to
268 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270
271 // This is a process only hosting activities that are not visible,
272 // so it can be killed without any disruption. Value set in
273 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800274 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 static int HIDDEN_APP_MIN_ADJ;
276
The Android Open Source Project4df24232009-03-05 14:34:35 -0800277 // This is a process holding the home application -- we want to try
278 // avoiding killing it, even if it would normally be in the background,
279 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800280 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800281
Christopher Tate6fa95972009-06-05 18:43:55 -0700282 // This is a process currently hosting a backup operation. Killing it
283 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 // This is a process holding a secondary server -- killing it will not
287 // have much of an impact as far as the user is concerned. Value set in
288 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
291 // This is a process only hosting activities that are visible to the
292 // user, so we'd prefer they don't disappear. Value set in
293 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800294 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295
296 // This is the process running the current foreground app. We'd really
297 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800298 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299
300 // This is a process running a core server, such as telephony. Definitely
301 // don't want to kill it, but doing so is not completely fatal.
302 static final int CORE_SERVER_ADJ = -12;
303
304 // The system process runs at the default adjustment.
305 static final int SYSTEM_ADJ = -16;
306
307 // Memory pages are 4K.
308 static final int PAGE_SIZE = 4*1024;
309
310 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800311 static final int EMPTY_APP_MEM;
312 static final int HIDDEN_APP_MEM;
313 static final int HOME_APP_MEM;
314 static final int BACKUP_APP_MEM;
315 static final int SECONDARY_SERVER_MEM;
316 static final int VISIBLE_APP_MEM;
317 static final int FOREGROUND_APP_MEM;
318
319 // The minimum number of hidden apps we want to be able to keep around,
320 // without empty apps being able to push them out of memory.
321 static final int MIN_HIDDEN_APPS = 2;
322
Dianne Hackborn8633e682010-04-22 16:03:41 -0700323 // The maximum number of hidden processes we will keep around before
324 // killing them; this is just a control to not let us go too crazy with
325 // keeping around processes on devices with large amounts of RAM.
326 static final int MAX_HIDDEN_APPS = 15;
327
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800328 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700329 // been idle for less than 15 seconds.
330 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800331
332 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700333 // been idle for less than 120 seconds.
334 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800335
336 static {
337 // These values are set in system/rootdir/init.rc on startup.
338 FOREGROUND_APP_ADJ =
339 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_ADJ"));
340 VISIBLE_APP_ADJ =
341 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
342 SECONDARY_SERVER_ADJ =
343 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
344 BACKUP_APP_ADJ =
345 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_ADJ"));
346 HOME_APP_ADJ =
347 Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
348 HIDDEN_APP_MIN_ADJ =
349 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
350 EMPTY_APP_ADJ =
351 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_ADJ"));
352 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ-1;
353 FOREGROUND_APP_MEM =
354 Integer.valueOf(SystemProperties.get("ro.FOREGROUND_APP_MEM"))*PAGE_SIZE;
355 VISIBLE_APP_MEM =
356 Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
357 SECONDARY_SERVER_MEM =
358 Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
359 BACKUP_APP_MEM =
360 Integer.valueOf(SystemProperties.get("ro.BACKUP_APP_MEM"))*PAGE_SIZE;
361 HOME_APP_MEM =
362 Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
363 HIDDEN_APP_MEM =
364 Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
365 EMPTY_APP_MEM =
366 Integer.valueOf(SystemProperties.get("ro.EMPTY_APP_MEM"))*PAGE_SIZE;
367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368
Dan Egnor42471dd2010-01-07 17:25:22 -0800369 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370
371 static final String[] EMPTY_STRING_ARRAY = new String[0];
372
373 enum ActivityState {
374 INITIALIZING,
375 RESUMED,
376 PAUSING,
377 PAUSED,
378 STOPPING,
379 STOPPED,
380 FINISHING,
381 DESTROYING,
382 DESTROYED
383 }
384
385 /**
386 * The back history of all previous (and possibly still
387 * running) activities. It contains HistoryRecord objects.
388 */
389 final ArrayList mHistory = new ArrayList();
390
391 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700392 * Description of a request to start a new activity, which has been held
393 * due to app switches being disabled.
394 */
395 class PendingActivityLaunch {
396 HistoryRecord r;
397 HistoryRecord sourceRecord;
398 Uri[] grantedUriPermissions;
399 int grantedMode;
400 boolean onlyIfNeeded;
401 }
402
403 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
404 = new ArrayList<PendingActivityLaunch>();
405
406 /**
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -0800407 * List of people waiting to find out about the next launched activity.
408 */
409 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
410 = new ArrayList<IActivityManager.WaitResult>();
411
412 /**
413 * List of people waiting to find out about the next visible activity.
414 */
415 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
416 = new ArrayList<IActivityManager.WaitResult>();
417
418 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 * List of all active broadcasts that are to be executed immediately
420 * (without waiting for another broadcast to finish). Currently this only
421 * contains broadcasts to registered receivers, to avoid spinning up
422 * a bunch of processes to execute IntentReceiver components.
423 */
424 final ArrayList<BroadcastRecord> mParallelBroadcasts
425 = new ArrayList<BroadcastRecord>();
426
427 /**
428 * List of all active broadcasts that are to be executed one at a time.
429 * The object at the top of the list is the currently activity broadcasts;
430 * those after it are waiting for the top to finish..
431 */
432 final ArrayList<BroadcastRecord> mOrderedBroadcasts
433 = new ArrayList<BroadcastRecord>();
434
435 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800436 * Historical data of past broadcasts, for debugging.
437 */
438 static final int MAX_BROADCAST_HISTORY = 100;
439 final BroadcastRecord[] mBroadcastHistory
440 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
441
442 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 * Set when we current have a BROADCAST_INTENT_MSG in flight.
444 */
445 boolean mBroadcastsScheduled = false;
446
447 /**
448 * Set to indicate whether to issue an onUserLeaving callback when a
449 * newly launched activity is being brought in front of us.
450 */
451 boolean mUserLeaving = false;
452
453 /**
454 * When we are in the process of pausing an activity, before starting the
455 * next one, this variable holds the activity that is currently being paused.
456 */
457 HistoryRecord mPausingActivity = null;
458
459 /**
460 * Current activity that is resumed, or null if there is none.
461 */
462 HistoryRecord mResumedActivity = null;
463
464 /**
465 * Activity we have told the window manager to have key focus.
466 */
467 HistoryRecord mFocusedActivity = null;
468
469 /**
470 * This is the last activity that we put into the paused state. This is
471 * used to determine if we need to do an activity transition while sleeping,
472 * when we normally hold the top activity paused.
473 */
474 HistoryRecord mLastPausedActivity = null;
475
476 /**
477 * List of activities that are waiting for a new activity
478 * to become visible before completing whatever operation they are
479 * supposed to do.
480 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700481 final ArrayList<HistoryRecord> mWaitingVisibleActivities
482 = new ArrayList<HistoryRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483
484 /**
485 * List of activities that are ready to be stopped, but waiting
486 * for the next activity to settle down before doing so. It contains
487 * HistoryRecord objects.
488 */
489 final ArrayList<HistoryRecord> mStoppingActivities
490 = new ArrayList<HistoryRecord>();
491
492 /**
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700493 * Animations that for the current transition have requested not to
494 * be considered for the transition animation.
495 */
496 final ArrayList<HistoryRecord> mNoAnimActivities
497 = new ArrayList<HistoryRecord>();
498
499 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 * List of intents that were used to start the most recent tasks.
501 */
502 final ArrayList<TaskRecord> mRecentTasks
503 = new ArrayList<TaskRecord>();
504
505 /**
506 * List of activities that are ready to be finished, but waiting
507 * for the previous activity to settle down before doing so. It contains
508 * HistoryRecord objects.
509 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700510 final ArrayList<HistoryRecord> mFinishingActivities
511 = new ArrayList<HistoryRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512
513 /**
514 * All of the applications we currently have running organized by name.
515 * The keys are strings of the application package name (as
516 * returned by the package manager), and the keys are ApplicationRecord
517 * objects.
518 */
519 final ProcessMap<ProcessRecord> mProcessNames
520 = new ProcessMap<ProcessRecord>();
521
522 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700523 * The currently running heavy-weight process, if any.
524 */
525 ProcessRecord mHeavyWeightProcess = null;
526
527 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 * The last time that various processes have crashed.
529 */
530 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
531
532 /**
533 * Set of applications that we consider to be bad, and will reject
534 * incoming broadcasts from (which the user has no control over).
535 * Processes are added to this set when they have crashed twice within
536 * a minimum amount of time; they are removed from it when they are
537 * later restarted (hopefully due to some user action). The value is the
538 * time it was added to the list.
539 */
540 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
541
542 /**
543 * All of the processes we currently have running organized by pid.
544 * The keys are the pid running the application.
545 *
546 * <p>NOTE: This object is protected by its own lock, NOT the global
547 * activity manager lock!
548 */
549 final SparseArray<ProcessRecord> mPidsSelfLocked
550 = new SparseArray<ProcessRecord>();
551
552 /**
553 * All of the processes that have been forced to be foreground. The key
554 * is the pid of the caller who requested it (we hold a death
555 * link on it).
556 */
557 abstract class ForegroundToken implements IBinder.DeathRecipient {
558 int pid;
559 IBinder token;
560 }
561 final SparseArray<ForegroundToken> mForegroundProcesses
562 = new SparseArray<ForegroundToken>();
563
564 /**
565 * List of records for processes that someone had tried to start before the
566 * system was ready. We don't start them at that point, but ensure they
567 * are started by the time booting is complete.
568 */
569 final ArrayList<ProcessRecord> mProcessesOnHold
570 = new ArrayList<ProcessRecord>();
571
572 /**
573 * List of records for processes that we have started and are waiting
574 * for them to call back. This is really only needed when running in
575 * single processes mode, in which case we do not have a unique pid for
576 * each process.
577 */
578 final ArrayList<ProcessRecord> mStartingProcesses
579 = new ArrayList<ProcessRecord>();
580
581 /**
582 * List of persistent applications that are in the process
583 * of being started.
584 */
585 final ArrayList<ProcessRecord> mPersistentStartingProcesses
586 = new ArrayList<ProcessRecord>();
587
588 /**
589 * Processes that are being forcibly torn down.
590 */
591 final ArrayList<ProcessRecord> mRemovedProcesses
592 = new ArrayList<ProcessRecord>();
593
594 /**
595 * List of running applications, sorted by recent usage.
596 * The first entry in the list is the least recently used.
597 * It contains ApplicationRecord objects. This list does NOT include
598 * any persistent application records (since we never want to exit them).
599 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800600 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 = new ArrayList<ProcessRecord>();
602
603 /**
604 * List of processes that should gc as soon as things are idle.
605 */
606 final ArrayList<ProcessRecord> mProcessesToGc
607 = new ArrayList<ProcessRecord>();
608
609 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800610 * This is the process holding what we currently consider to be
611 * the "home" activity.
612 */
613 private ProcessRecord mHomeProcess;
614
615 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 * List of running activities, sorted by recent usage.
617 * The first entry in the list is the least recently used.
618 * It contains HistoryRecord objects.
619 */
620 private final ArrayList mLRUActivities = new ArrayList();
621
622 /**
623 * Set of PendingResultRecord objects that are currently active.
624 */
625 final HashSet mPendingResultRecords = new HashSet();
626
627 /**
628 * Set of IntentSenderRecord objects that are currently active.
629 */
630 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
631 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
632
633 /**
634 * Intent broadcast that we have tried to start, but are
635 * waiting for its application's process to be created. We only
636 * need one (instead of a list) because we always process broadcasts
637 * one at a time, so no others can be started while waiting for this
638 * one.
639 */
640 BroadcastRecord mPendingBroadcast = null;
641
642 /**
643 * Keeps track of all IIntentReceivers that have been registered for
644 * broadcasts. Hash keys are the receiver IBinder, hash value is
645 * a ReceiverList.
646 */
647 final HashMap mRegisteredReceivers = new HashMap();
648
649 /**
650 * Resolver for broadcast intents to registered receivers.
651 * Holds BroadcastFilter (subclass of IntentFilter).
652 */
653 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
654 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
655 @Override
656 protected boolean allowFilterResult(
657 BroadcastFilter filter, List<BroadcastFilter> dest) {
658 IBinder target = filter.receiverList.receiver.asBinder();
659 for (int i=dest.size()-1; i>=0; i--) {
660 if (dest.get(i).receiverList.receiver.asBinder() == target) {
661 return false;
662 }
663 }
664 return true;
665 }
666 };
667
668 /**
669 * State of all active sticky broadcasts. Keys are the action of the
670 * sticky Intent, values are an ArrayList of all broadcasted intents with
671 * that action (which should usually be one).
672 */
673 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
674 new HashMap<String, ArrayList<Intent>>();
675
676 /**
677 * All currently running services.
678 */
679 final HashMap<ComponentName, ServiceRecord> mServices =
680 new HashMap<ComponentName, ServiceRecord>();
681
682 /**
683 * All currently running services indexed by the Intent used to start them.
684 */
685 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
686 new HashMap<Intent.FilterComparison, ServiceRecord>();
687
688 /**
689 * All currently bound service connections. Keys are the IBinder of
690 * the client's IServiceConnection.
691 */
692 final HashMap<IBinder, ConnectionRecord> mServiceConnections
693 = new HashMap<IBinder, ConnectionRecord>();
694
695 /**
696 * List of services that we have been asked to start,
697 * but haven't yet been able to. It is used to hold start requests
698 * while waiting for their corresponding application thread to get
699 * going.
700 */
701 final ArrayList<ServiceRecord> mPendingServices
702 = new ArrayList<ServiceRecord>();
703
704 /**
705 * List of services that are scheduled to restart following a crash.
706 */
707 final ArrayList<ServiceRecord> mRestartingServices
708 = new ArrayList<ServiceRecord>();
709
710 /**
711 * List of services that are in the process of being stopped.
712 */
713 final ArrayList<ServiceRecord> mStoppingServices
714 = new ArrayList<ServiceRecord>();
715
716 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700717 * Backup/restore process management
718 */
719 String mBackupAppName = null;
720 BackupRecord mBackupTarget = null;
721
722 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 * List of PendingThumbnailsRecord objects of clients who are still
724 * waiting to receive all of the thumbnails for a task.
725 */
726 final ArrayList mPendingThumbnails = new ArrayList();
727
728 /**
729 * List of HistoryRecord objects that have been finished and must
730 * still report back to a pending thumbnail receiver.
731 */
732 final ArrayList mCancelledThumbnails = new ArrayList();
733
734 /**
735 * All of the currently running global content providers. Keys are a
736 * string containing the provider name and values are a
737 * ContentProviderRecord object containing the data about it. Note
738 * that a single provider may be published under multiple names, so
739 * there may be multiple entries here for a single one in mProvidersByClass.
740 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700741 final HashMap<String, ContentProviderRecord> mProvidersByName
742 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743
744 /**
745 * All of the currently running global content providers. Keys are a
746 * string containing the provider's implementation class and values are a
747 * ContentProviderRecord object containing the data about it.
748 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700749 final HashMap<String, ContentProviderRecord> mProvidersByClass
750 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800751
752 /**
753 * List of content providers who have clients waiting for them. The
754 * application is currently being launched and the provider will be
755 * removed from this list once it is published.
756 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700757 final ArrayList<ContentProviderRecord> mLaunchingProviders
758 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759
760 /**
761 * Global set of specific Uri permissions that have been granted.
762 */
763 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
764 = new SparseArray<HashMap<Uri, UriPermission>>();
765
766 /**
767 * Thread-local storage used to carry caller permissions over through
768 * indirect content-provider access.
769 * @see #ActivityManagerService.openContentUri()
770 */
771 private class Identity {
772 public int pid;
773 public int uid;
774
775 Identity(int _pid, int _uid) {
776 pid = _pid;
777 uid = _uid;
778 }
779 }
780 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
781
782 /**
783 * All information we have collected about the runtime performance of
784 * any user id that can impact battery performance.
785 */
786 final BatteryStatsService mBatteryStatsService;
787
788 /**
789 * information about component usage
790 */
791 final UsageStatsService mUsageStatsService;
792
793 /**
794 * Current configuration information. HistoryRecord objects are given
795 * a reference to this object to indicate which configuration they are
796 * currently running in, so this object must be kept immutable.
797 */
798 Configuration mConfiguration = new Configuration();
799
800 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800801 * Current sequencing integer of the configuration, for skipping old
802 * configurations.
803 */
804 int mConfigurationSeq = 0;
805
806 /**
Dianne Hackbornd49258f2010-03-26 00:44:29 -0700807 * Set when we know we are going to be calling updateConfiguration()
808 * soon, so want to skip intermediate config checks.
809 */
810 boolean mConfigWillChange;
811
812 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700813 * Hardware-reported OpenGLES version.
814 */
815 final int GL_ES_VERSION;
816
817 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818 * List of initialization arguments to pass to all processes when binding applications to them.
819 * For example, references to the commonly used services.
820 */
821 HashMap<String, IBinder> mAppBindArgs;
822
823 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700824 * Temporary to avoid allocations. Protected by main lock.
825 */
826 final StringBuilder mStringBuilder = new StringBuilder(256);
827
828 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 * Used to control how we initialize the service.
830 */
831 boolean mStartRunning = false;
832 ComponentName mTopComponent;
833 String mTopAction;
834 String mTopData;
835 boolean mSystemReady = false;
836 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700837 boolean mWaitingUpdate = false;
838 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839
840 Context mContext;
841
842 int mFactoryTest;
843
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700844 boolean mCheckedForSetup;
845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700847 * The time at which we will allow normal application switches again,
848 * after a call to {@link #stopAppSwitches()}.
849 */
850 long mAppSwitchesAllowedTime;
851
852 /**
853 * This is set to true after the first switch after mAppSwitchesAllowedTime
854 * is set; any switches after that will clear the time.
855 */
856 boolean mDidAppSwitch;
857
858 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 * Set while we are wanting to sleep, to prevent any
860 * activities from being started/resumed.
861 */
862 boolean mSleeping = false;
863
864 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700865 * Set if we are shutting down the system, similar to sleeping.
866 */
867 boolean mShuttingDown = false;
868
869 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 * Set when the system is going to sleep, until we have
871 * successfully paused the current activity and released our wake lock.
872 * At that point the system is allowed to actually sleep.
873 */
874 PowerManager.WakeLock mGoingToSleep;
875
876 /**
877 * We don't want to allow the device to go to sleep while in the process
878 * of launching an activity. This is primarily to allow alarm intent
879 * receivers to launch an activity and get that to run before the device
880 * goes back to sleep.
881 */
882 PowerManager.WakeLock mLaunchingActivity;
883
884 /**
885 * Task identifier that activities are currently being started
886 * in. Incremented each time a new task is created.
887 * todo: Replace this with a TokenSpace class that generates non-repeating
888 * integers that won't wrap.
889 */
890 int mCurTask = 1;
891
892 /**
893 * Current sequence id for oom_adj computation traversal.
894 */
895 int mAdjSeq = 0;
896
897 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700898 * Current sequence id for process LRU updating.
899 */
900 int mLruSeq = 0;
901
902 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
904 * is set, indicating the user wants processes started in such a way
905 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
906 * running in each process (thus no pre-initialized process, etc).
907 */
908 boolean mSimpleProcessManagement = false;
909
910 /**
911 * System monitoring: number of processes that died since the last
912 * N procs were started.
913 */
914 int[] mProcDeaths = new int[20];
915
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700916 /**
917 * This is set if we had to do a delayed dexopt of an app before launching
918 * it, to increasing the ANR timeouts in that case.
919 */
920 boolean mDidDexOpt;
921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 String mDebugApp = null;
923 boolean mWaitForDebugger = false;
924 boolean mDebugTransient = false;
925 String mOrigDebugApp = null;
926 boolean mOrigWaitForDebugger = false;
927 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700928 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700930 final RemoteCallbackList<IActivityWatcher> mWatchers
931 = new RemoteCallbackList<IActivityWatcher>();
932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 /**
934 * Callback of last caller to {@link #requestPss}.
935 */
936 Runnable mRequestPssCallback;
937
938 /**
939 * Remaining processes for which we are waiting results from the last
940 * call to {@link #requestPss}.
941 */
942 final ArrayList<ProcessRecord> mRequestPssList
943 = new ArrayList<ProcessRecord>();
944
945 /**
946 * Runtime statistics collection thread. This object's lock is used to
947 * protect all related state.
948 */
949 final Thread mProcessStatsThread;
950
951 /**
952 * Used to collect process stats when showing not responding dialog.
953 * Protected by mProcessStatsThread.
954 */
955 final ProcessStats mProcessStats = new ProcessStats(
956 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700957 final AtomicLong mLastCpuTime = new AtomicLong(0);
958 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 long mLastWriteTime = 0;
961
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700962 long mInitialStartTime = 0;
963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 /**
965 * Set to true after the system has finished booting.
966 */
967 boolean mBooted = false;
968
969 int mProcessLimit = 0;
970
971 WindowManagerService mWindowManager;
972
973 static ActivityManagerService mSelf;
974 static ActivityThread mSystemThread;
975
976 private final class AppDeathRecipient implements IBinder.DeathRecipient {
977 final ProcessRecord mApp;
978 final int mPid;
979 final IApplicationThread mAppThread;
980
981 AppDeathRecipient(ProcessRecord app, int pid,
982 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800983 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 TAG, "New death recipient " + this
985 + " for thread " + thread.asBinder());
986 mApp = app;
987 mPid = pid;
988 mAppThread = thread;
989 }
990
991 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800992 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 TAG, "Death received in " + this
994 + " for thread " + mAppThread.asBinder());
995 removeRequestedPss(mApp);
996 synchronized(ActivityManagerService.this) {
997 appDiedLocked(mApp, mPid, mAppThread);
998 }
999 }
1000 }
1001
1002 static final int SHOW_ERROR_MSG = 1;
1003 static final int SHOW_NOT_RESPONDING_MSG = 2;
1004 static final int SHOW_FACTORY_ERROR_MSG = 3;
1005 static final int UPDATE_CONFIGURATION_MSG = 4;
1006 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
1007 static final int WAIT_FOR_DEBUGGER_MSG = 6;
1008 static final int BROADCAST_INTENT_MSG = 7;
1009 static final int BROADCAST_TIMEOUT_MSG = 8;
1010 static final int PAUSE_TIMEOUT_MSG = 9;
1011 static final int IDLE_TIMEOUT_MSG = 10;
1012 static final int IDLE_NOW_MSG = 11;
1013 static final int SERVICE_TIMEOUT_MSG = 12;
1014 static final int UPDATE_TIME_ZONE = 13;
1015 static final int SHOW_UID_ERROR_MSG = 14;
1016 static final int IM_FEELING_LUCKY_MSG = 15;
1017 static final int LAUNCH_TIMEOUT_MSG = 16;
1018 static final int DESTROY_TIMEOUT_MSG = 17;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 static final int RESUME_TOP_ACTIVITY_MSG = 19;
1020 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001021 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001022 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001023 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001024 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
1025 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026
1027 AlertDialog mUidAlert;
1028
1029 final Handler mHandler = new Handler() {
1030 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001031 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 //}
1033
1034 public void handleMessage(Message msg) {
1035 switch (msg.what) {
1036 case SHOW_ERROR_MSG: {
1037 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 synchronized (ActivityManagerService.this) {
1039 ProcessRecord proc = (ProcessRecord)data.get("app");
1040 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001041 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 return;
1043 }
1044 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001045 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001046 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 d.show();
1048 proc.crashDialog = d;
1049 } else {
1050 // The device is asleep, so just pretend that the user
1051 // saw a crash dialog and hit "force quit".
1052 res.set(0);
1053 }
1054 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001055
1056 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 } break;
1058 case SHOW_NOT_RESPONDING_MSG: {
1059 synchronized (ActivityManagerService.this) {
1060 HashMap data = (HashMap) msg.obj;
1061 ProcessRecord proc = (ProcessRecord)data.get("app");
1062 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001063 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 return;
1065 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001066
1067 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1068 null, null, 0, null, null, null,
1069 false, false, MY_PID, Process.SYSTEM_UID);
1070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1072 mContext, proc, (HistoryRecord)data.get("activity"));
1073 d.show();
1074 proc.anrDialog = d;
1075 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001076
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001077 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001078 } break;
1079 case SHOW_FACTORY_ERROR_MSG: {
1080 Dialog d = new FactoryErrorDialog(
1081 mContext, msg.getData().getCharSequence("msg"));
1082 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001083 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 } break;
1085 case UPDATE_CONFIGURATION_MSG: {
1086 final ContentResolver resolver = mContext.getContentResolver();
1087 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1088 } break;
1089 case GC_BACKGROUND_PROCESSES_MSG: {
1090 synchronized (ActivityManagerService.this) {
1091 performAppGcsIfAppropriateLocked();
1092 }
1093 } break;
1094 case WAIT_FOR_DEBUGGER_MSG: {
1095 synchronized (ActivityManagerService.this) {
1096 ProcessRecord app = (ProcessRecord)msg.obj;
1097 if (msg.arg1 != 0) {
1098 if (!app.waitedForDebugger) {
1099 Dialog d = new AppWaitingForDebuggerDialog(
1100 ActivityManagerService.this,
1101 mContext, app);
1102 app.waitDialog = d;
1103 app.waitedForDebugger = true;
1104 d.show();
1105 }
1106 } else {
1107 if (app.waitDialog != null) {
1108 app.waitDialog.dismiss();
1109 app.waitDialog = null;
1110 }
1111 }
1112 }
1113 } break;
1114 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001115 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 TAG, "Received BROADCAST_INTENT_MSG");
1117 processNextBroadcast(true);
1118 } break;
1119 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001120 if (mDidDexOpt) {
1121 mDidDexOpt = false;
1122 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1123 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1124 return;
1125 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001126 // Only process broadcast timeouts if the system is ready. That way
1127 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1128 // to do heavy lifting for system up
1129 if (mSystemReady) {
1130 broadcastTimeout();
1131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 } break;
1133 case PAUSE_TIMEOUT_MSG: {
1134 IBinder token = (IBinder)msg.obj;
1135 // We don't at this point know if the activity is fullscreen,
1136 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001137 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 activityPaused(token, null, true);
1139 } break;
1140 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001141 if (mDidDexOpt) {
1142 mDidDexOpt = false;
1143 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1144 nmsg.obj = msg.obj;
1145 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1146 return;
1147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 // We don't at this point know if the activity is fullscreen,
1149 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001150 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001151 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001152 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 } break;
1154 case DESTROY_TIMEOUT_MSG: {
1155 IBinder token = (IBinder)msg.obj;
1156 // We don't at this point know if the activity is fullscreen,
1157 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001158 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 activityDestroyed(token);
1160 } break;
1161 case IDLE_NOW_MSG: {
1162 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001163 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 } break;
1165 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001166 if (mDidDexOpt) {
1167 mDidDexOpt = false;
1168 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1169 nmsg.obj = msg.obj;
1170 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1171 return;
1172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 serviceTimeout((ProcessRecord)msg.obj);
1174 } break;
1175 case UPDATE_TIME_ZONE: {
1176 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001177 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1178 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 if (r.thread != null) {
1180 try {
1181 r.thread.updateTimeZone();
1182 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001183 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 }
1185 }
1186 }
1187 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001188 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 case SHOW_UID_ERROR_MSG: {
1190 // XXX This is a temporary dialog, no need to localize.
1191 AlertDialog d = new BaseErrorDialog(mContext);
1192 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1193 d.setCancelable(false);
1194 d.setTitle("System UIDs Inconsistent");
1195 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1196 d.setButton("I'm Feeling Lucky",
1197 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1198 mUidAlert = d;
1199 d.show();
1200 } break;
1201 case IM_FEELING_LUCKY_MSG: {
1202 if (mUidAlert != null) {
1203 mUidAlert.dismiss();
1204 mUidAlert = null;
1205 }
1206 } break;
1207 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001208 if (mDidDexOpt) {
1209 mDidDexOpt = false;
1210 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1211 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1212 return;
1213 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 synchronized (ActivityManagerService.this) {
1215 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001216 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 mLaunchingActivity.release();
1218 }
1219 }
1220 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 case RESUME_TOP_ACTIVITY_MSG: {
1222 synchronized (ActivityManagerService.this) {
1223 resumeTopActivityLocked(null);
1224 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001225 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001227 if (mDidDexOpt) {
1228 mDidDexOpt = false;
1229 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1230 nmsg.obj = msg.obj;
1231 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1232 return;
1233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 ProcessRecord app = (ProcessRecord)msg.obj;
1235 synchronized (ActivityManagerService.this) {
1236 processStartTimedOutLocked(app);
1237 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001238 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001239 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1240 synchronized (ActivityManagerService.this) {
1241 doPendingActivityLaunchesLocked(true);
1242 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001243 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001244 case KILL_APPLICATION_MSG: {
1245 synchronized (ActivityManagerService.this) {
1246 int uid = msg.arg1;
1247 boolean restart = (msg.arg2 == 1);
1248 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001249 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001250 }
1251 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001252 case FINALIZE_PENDING_INTENT_MSG: {
1253 ((PendingIntentRecord)msg.obj).completeFinalize();
1254 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001255 case POST_HEAVY_NOTIFICATION_MSG: {
1256 INotificationManager inm = NotificationManager.getService();
1257 if (inm == null) {
1258 return;
1259 }
1260
1261 HistoryRecord root = (HistoryRecord)msg.obj;
1262 ProcessRecord process = root.app;
1263 if (process == null) {
1264 return;
1265 }
1266
1267 try {
1268 Context context = mContext.createPackageContext(process.info.packageName, 0);
1269 String text = mContext.getString(R.string.heavy_weight_notification,
1270 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1271 Notification notification = new Notification();
1272 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1273 notification.when = 0;
1274 notification.flags = Notification.FLAG_ONGOING_EVENT;
1275 notification.tickerText = text;
1276 notification.defaults = 0; // please be quiet
1277 notification.sound = null;
1278 notification.vibrate = null;
1279 notification.setLatestEventInfo(context, text,
1280 mContext.getText(R.string.heavy_weight_notification_detail),
1281 PendingIntent.getActivity(mContext, 0, root.intent,
1282 PendingIntent.FLAG_CANCEL_CURRENT));
1283
1284 try {
1285 int[] outId = new int[1];
1286 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1287 notification, outId);
1288 } catch (RuntimeException e) {
1289 Slog.w(ActivityManagerService.TAG,
1290 "Error showing notification for heavy-weight app", e);
1291 } catch (RemoteException e) {
1292 }
1293 } catch (NameNotFoundException e) {
1294 Log.w(TAG, "Unable to create context for heavy notification", e);
1295 }
1296 } break;
1297 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1298 INotificationManager inm = NotificationManager.getService();
1299 if (inm == null) {
1300 return;
1301 }
1302 try {
1303 inm.cancelNotification("android",
1304 R.string.heavy_weight_notification);
1305 } catch (RuntimeException e) {
1306 Slog.w(ActivityManagerService.TAG,
1307 "Error canceling notification for service", e);
1308 } catch (RemoteException e) {
1309 }
1310 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 }
1312 }
1313 };
1314
1315 public static void setSystemProcess() {
1316 try {
1317 ActivityManagerService m = mSelf;
1318
1319 ServiceManager.addService("activity", m);
1320 ServiceManager.addService("meminfo", new MemBinder(m));
1321 if (MONITOR_CPU_USAGE) {
1322 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 ServiceManager.addService("permission", new PermissionController(m));
1325
1326 ApplicationInfo info =
1327 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001328 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001329 mSystemThread.installSystemApplicationInfo(info);
1330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 synchronized (mSelf) {
1332 ProcessRecord app = mSelf.newProcessRecordLocked(
1333 mSystemThread.getApplicationThread(), info,
1334 info.processName);
1335 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001336 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 app.maxAdj = SYSTEM_ADJ;
1338 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1339 synchronized (mSelf.mPidsSelfLocked) {
1340 mSelf.mPidsSelfLocked.put(app.pid, app);
1341 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001342 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 }
1344 } catch (PackageManager.NameNotFoundException e) {
1345 throw new RuntimeException(
1346 "Unable to find android system package", e);
1347 }
1348 }
1349
1350 public void setWindowManager(WindowManagerService wm) {
1351 mWindowManager = wm;
1352 }
1353
1354 public static final Context main(int factoryTest) {
1355 AThread thr = new AThread();
1356 thr.start();
1357
1358 synchronized (thr) {
1359 while (thr.mService == null) {
1360 try {
1361 thr.wait();
1362 } catch (InterruptedException e) {
1363 }
1364 }
1365 }
1366
1367 ActivityManagerService m = thr.mService;
1368 mSelf = m;
1369 ActivityThread at = ActivityThread.systemMain();
1370 mSystemThread = at;
1371 Context context = at.getSystemContext();
1372 m.mContext = context;
1373 m.mFactoryTest = factoryTest;
1374 PowerManager pm =
1375 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1376 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1377 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1378 m.mLaunchingActivity.setReferenceCounted(false);
1379
1380 m.mBatteryStatsService.publish(context);
1381 m.mUsageStatsService.publish(context);
1382
1383 synchronized (thr) {
1384 thr.mReady = true;
1385 thr.notifyAll();
1386 }
1387
1388 m.startRunning(null, null, null, null);
1389
1390 return context;
1391 }
1392
1393 public static ActivityManagerService self() {
1394 return mSelf;
1395 }
1396
1397 static class AThread extends Thread {
1398 ActivityManagerService mService;
1399 boolean mReady = false;
1400
1401 public AThread() {
1402 super("ActivityManager");
1403 }
1404
1405 public void run() {
1406 Looper.prepare();
1407
1408 android.os.Process.setThreadPriority(
1409 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1410
1411 ActivityManagerService m = new ActivityManagerService();
1412
1413 synchronized (this) {
1414 mService = m;
1415 notifyAll();
1416 }
1417
1418 synchronized (this) {
1419 while (!mReady) {
1420 try {
1421 wait();
1422 } catch (InterruptedException e) {
1423 }
1424 }
1425 }
1426
1427 Looper.loop();
1428 }
1429 }
1430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 static class MemBinder extends Binder {
1432 ActivityManagerService mActivityManagerService;
1433 MemBinder(ActivityManagerService activityManagerService) {
1434 mActivityManagerService = activityManagerService;
1435 }
1436
1437 @Override
1438 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1439 ActivityManagerService service = mActivityManagerService;
1440 ArrayList<ProcessRecord> procs;
1441 synchronized (mActivityManagerService) {
1442 if (args != null && args.length > 0
1443 && args[0].charAt(0) != '-') {
1444 procs = new ArrayList<ProcessRecord>();
1445 int pid = -1;
1446 try {
1447 pid = Integer.parseInt(args[0]);
1448 } catch (NumberFormatException e) {
1449
1450 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001451 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1452 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 if (proc.pid == pid) {
1454 procs.add(proc);
1455 } else if (proc.processName.equals(args[0])) {
1456 procs.add(proc);
1457 }
1458 }
1459 if (procs.size() <= 0) {
1460 pw.println("No process found for: " + args[0]);
1461 return;
1462 }
1463 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001464 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 }
1466 }
1467 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1468 }
1469 }
1470
1471 static class CpuBinder extends Binder {
1472 ActivityManagerService mActivityManagerService;
1473 CpuBinder(ActivityManagerService activityManagerService) {
1474 mActivityManagerService = activityManagerService;
1475 }
1476
1477 @Override
1478 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1479 synchronized (mActivityManagerService.mProcessStatsThread) {
1480 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1481 }
1482 }
1483 }
1484
1485 private ActivityManagerService() {
1486 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1487 if (v != null && Integer.getInteger(v) != 0) {
1488 mSimpleProcessManagement = true;
1489 }
1490 v = System.getenv("ANDROID_DEBUG_APP");
1491 if (v != null) {
1492 mSimpleProcessManagement = true;
1493 }
1494
Joe Onorato8a9b2202010-02-26 18:56:32 -08001495 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 File dataDir = Environment.getDataDirectory();
1498 File systemDir = new File(dataDir, "system");
1499 systemDir.mkdirs();
1500 mBatteryStatsService = new BatteryStatsService(new File(
1501 systemDir, "batterystats.bin").toString());
1502 mBatteryStatsService.getActiveStatistics().readLocked();
1503 mBatteryStatsService.getActiveStatistics().writeLocked();
1504
1505 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001506 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507
Jack Palevichb90d28c2009-07-22 15:35:24 -07001508 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1509 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1510
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001511 mConfiguration.setToDefaults();
1512 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 mProcessStats.init();
1514
1515 // Add ourself to the Watchdog monitors.
1516 Watchdog.getInstance().addMonitor(this);
1517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 mProcessStatsThread = new Thread("ProcessStats") {
1519 public void run() {
1520 while (true) {
1521 try {
1522 try {
1523 synchronized(this) {
1524 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001525 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001527 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 // + ", write delay=" + nextWriteDelay);
1529 if (nextWriteDelay < nextCpuDelay) {
1530 nextCpuDelay = nextWriteDelay;
1531 }
1532 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001533 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 this.wait(nextCpuDelay);
1535 }
1536 }
1537 } catch (InterruptedException e) {
1538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 updateCpuStatsNow();
1540 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001541 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 }
1543 }
1544 }
1545 };
1546 mProcessStatsThread.start();
1547 }
1548
1549 @Override
1550 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1551 throws RemoteException {
1552 try {
1553 return super.onTransact(code, data, reply, flags);
1554 } catch (RuntimeException e) {
1555 // The activity manager only throws security exceptions, so let's
1556 // log all others.
1557 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001558 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 }
1560 throw e;
1561 }
1562 }
1563
1564 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001565 final long now = SystemClock.uptimeMillis();
1566 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1567 return;
1568 }
1569 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1570 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 mProcessStatsThread.notify();
1572 }
1573 }
1574 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 void updateCpuStatsNow() {
1577 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001578 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 final long now = SystemClock.uptimeMillis();
1580 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001583 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1584 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 haveNewCpuStats = true;
1586 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001587 //Slog.i(TAG, mProcessStats.printCurrentState());
1588 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 // + mProcessStats.getTotalCpuPercent() + "%");
1590
Joe Onorato8a9b2202010-02-26 18:56:32 -08001591 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 if ("true".equals(SystemProperties.get("events.cpu"))) {
1593 int user = mProcessStats.getLastUserTime();
1594 int system = mProcessStats.getLastSystemTime();
1595 int iowait = mProcessStats.getLastIoWaitTime();
1596 int irq = mProcessStats.getLastIrqTime();
1597 int softIrq = mProcessStats.getLastSoftIrqTime();
1598 int idle = mProcessStats.getLastIdleTime();
1599
1600 int total = user + system + iowait + irq + softIrq + idle;
1601 if (total == 0) total = 1;
1602
Doug Zongker2bec3d42009-12-04 12:52:44 -08001603 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 ((user+system+iowait+irq+softIrq) * 100) / total,
1605 (user * 100) / total,
1606 (system * 100) / total,
1607 (iowait * 100) / total,
1608 (irq * 100) / total,
1609 (softIrq * 100) / total);
1610 }
1611 }
1612
Amith Yamasanie43530a2009-08-21 13:11:37 -07001613 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001614 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001615 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616 synchronized(mPidsSelfLocked) {
1617 if (haveNewCpuStats) {
1618 if (mBatteryStatsService.isOnBattery()) {
1619 final int N = mProcessStats.countWorkingStats();
1620 for (int i=0; i<N; i++) {
1621 ProcessStats.Stats st
1622 = mProcessStats.getWorkingStats(i);
1623 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1624 if (pr != null) {
1625 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1626 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001627 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001628 } else {
1629 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001630 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001631 if (ps != null) {
1632 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001633 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 }
1636 }
1637 }
1638 }
1639 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1642 mLastWriteTime = now;
1643 mBatteryStatsService.getActiveStatistics().writeLocked();
1644 }
1645 }
1646 }
1647 }
1648
1649 /**
1650 * Initialize the application bind args. These are passed to each
1651 * process when the bindApplication() IPC is sent to the process. They're
1652 * lazily setup to make sure the services are running when they're asked for.
1653 */
1654 private HashMap<String, IBinder> getCommonServicesLocked() {
1655 if (mAppBindArgs == null) {
1656 mAppBindArgs = new HashMap<String, IBinder>();
1657
1658 // Setup the application init args
1659 mAppBindArgs.put("package", ServiceManager.getService("package"));
1660 mAppBindArgs.put("window", ServiceManager.getService("window"));
1661 mAppBindArgs.put(Context.ALARM_SERVICE,
1662 ServiceManager.getService(Context.ALARM_SERVICE));
1663 }
1664 return mAppBindArgs;
1665 }
1666
1667 private final void setFocusedActivityLocked(HistoryRecord r) {
1668 if (mFocusedActivity != r) {
1669 mFocusedActivity = r;
1670 mWindowManager.setFocusedApp(r, true);
1671 }
1672 }
1673
Dianne Hackborn906497c2010-05-10 15:57:38 -07001674 private final void updateLruProcessInternalLocked(ProcessRecord app,
1675 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001677 int lrui = mLruProcesses.indexOf(app);
1678 if (lrui >= 0) mLruProcesses.remove(lrui);
1679
1680 int i = mLruProcesses.size()-1;
1681 int skipTop = 0;
1682
Dianne Hackborn906497c2010-05-10 15:57:38 -07001683 app.lruSeq = mLruSeq;
1684
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001685 // compute the new weight for this process.
1686 if (updateActivityTime) {
1687 app.lastActivityTime = SystemClock.uptimeMillis();
1688 }
1689 if (app.activities.size() > 0) {
1690 // If this process has activities, we more strongly want to keep
1691 // it around.
1692 app.lruWeight = app.lastActivityTime;
1693 } else if (app.pubProviders.size() > 0) {
1694 // If this process contains content providers, we want to keep
1695 // it a little more strongly.
1696 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1697 // Also don't let it kick out the first few "real" hidden processes.
1698 skipTop = MIN_HIDDEN_APPS;
1699 } else {
1700 // If this process doesn't have activities, we less strongly
1701 // want to keep it around, and generally want to avoid getting
1702 // in front of any very recently used activities.
1703 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1704 // Also don't let it kick out the first few "real" hidden processes.
1705 skipTop = MIN_HIDDEN_APPS;
1706 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001707
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001708 while (i >= 0) {
1709 ProcessRecord p = mLruProcesses.get(i);
1710 // If this app shouldn't be in front of the first N background
1711 // apps, then skip over that many that are currently hidden.
1712 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1713 skipTop--;
1714 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001715 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001716 mLruProcesses.add(i+1, app);
1717 break;
1718 }
1719 i--;
1720 }
1721 if (i < 0) {
1722 mLruProcesses.add(0, app);
1723 }
1724
Dianne Hackborn906497c2010-05-10 15:57:38 -07001725 // If the app is currently using a content provider or service,
1726 // bump those processes as well.
1727 if (app.connections.size() > 0) {
1728 for (ConnectionRecord cr : app.connections) {
1729 if (cr.binding != null && cr.binding.service != null
1730 && cr.binding.service.app != null
1731 && cr.binding.service.app.lruSeq != mLruSeq) {
1732 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1733 updateActivityTime, i+1);
1734 }
1735 }
1736 }
1737 if (app.conProviders.size() > 0) {
1738 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1739 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1740 updateLruProcessInternalLocked(cpr.app, oomAdj,
1741 updateActivityTime, i+1);
1742 }
1743 }
1744 }
1745
Joe Onorato8a9b2202010-02-26 18:56:32 -08001746 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 if (oomAdj) {
1748 updateOomAdjLocked();
1749 }
1750 }
1751
Dianne Hackborn906497c2010-05-10 15:57:38 -07001752 private final void updateLruProcessLocked(ProcessRecord app,
1753 boolean oomAdj, boolean updateActivityTime) {
1754 mLruSeq++;
1755 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1756 }
1757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 private final boolean updateLRUListLocked(HistoryRecord r) {
1759 final boolean hadit = mLRUActivities.remove(r);
1760 mLRUActivities.add(r);
1761 return hadit;
1762 }
1763
1764 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1765 int i = mHistory.size()-1;
1766 while (i >= 0) {
1767 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1768 if (!r.finishing && r != notTop) {
1769 return r;
1770 }
1771 i--;
1772 }
1773 return null;
1774 }
1775
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001776 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1777 int i = mHistory.size()-1;
1778 while (i >= 0) {
1779 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1780 if (!r.finishing && !r.delayedResume && r != notTop) {
1781 return r;
1782 }
1783 i--;
1784 }
1785 return null;
1786 }
1787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 /**
1789 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001790 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 *
1792 * @param token If non-null, any history records matching this token will be skipped.
1793 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1794 *
1795 * @return Returns the HistoryRecord of the next activity on the stack.
1796 */
1797 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1798 int i = mHistory.size()-1;
1799 while (i >= 0) {
1800 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1801 // Note: the taskId check depends on real taskId fields being non-zero
1802 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1803 return r;
1804 }
1805 i--;
1806 }
1807 return null;
1808 }
1809
1810 private final ProcessRecord getProcessRecordLocked(
1811 String processName, int uid) {
1812 if (uid == Process.SYSTEM_UID) {
1813 // The system gets to run in any process. If there are multiple
1814 // processes with the same uid, just pick the first (this
1815 // should never happen).
1816 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1817 processName);
1818 return procs != null ? procs.valueAt(0) : null;
1819 }
1820 ProcessRecord proc = mProcessNames.get(processName, uid);
1821 return proc;
1822 }
1823
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001824 private void ensurePackageDexOpt(String packageName) {
1825 IPackageManager pm = ActivityThread.getPackageManager();
1826 try {
1827 if (pm.performDexOpt(packageName)) {
1828 mDidDexOpt = true;
1829 }
1830 } catch (RemoteException e) {
1831 }
1832 }
1833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001834 private boolean isNextTransitionForward() {
1835 int transit = mWindowManager.getPendingAppTransition();
1836 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1837 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1838 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1839 }
1840
1841 private final boolean realStartActivityLocked(HistoryRecord r,
1842 ProcessRecord app, boolean andResume, boolean checkConfig)
1843 throws RemoteException {
1844
1845 r.startFreezingScreenLocked(app, 0);
1846 mWindowManager.setAppVisibility(r, true);
1847
1848 // Have the window manager re-evaluate the orientation of
1849 // the screen based on the new activity order. Note that
1850 // as a result of this, it can call back into the activity
1851 // manager with a new orientation. We don't care about that,
1852 // because the activity is not currently running so we are
1853 // just restarting it anyway.
1854 if (checkConfig) {
1855 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001856 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 r.mayFreezeScreenLocked(app) ? r : null);
1858 updateConfigurationLocked(config, r);
1859 }
1860
1861 r.app = app;
1862
Joe Onorato8a9b2202010-02-26 18:56:32 -08001863 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864
1865 int idx = app.activities.indexOf(r);
1866 if (idx < 0) {
1867 app.activities.add(r);
1868 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001869 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870
1871 try {
1872 if (app.thread == null) {
1873 throw new RemoteException();
1874 }
1875 List<ResultInfo> results = null;
1876 List<Intent> newIntents = null;
1877 if (andResume) {
1878 results = r.results;
1879 newIntents = r.newIntents;
1880 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001881 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001882 + " icicle=" + r.icicle
1883 + " with results=" + results + " newIntents=" + newIntents
1884 + " andResume=" + andResume);
1885 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001886 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 System.identityHashCode(r),
1888 r.task.taskId, r.shortComponentName);
1889 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001890 if (r.isHomeActivity) {
1891 mHomeProcess = app;
1892 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001893 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001895 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 r.info, r.icicle, results, newIntents, !andResume,
1897 isNextTransitionForward());
Dianne Hackborn860755f2010-06-03 18:47:52 -07001898
1899 if ((app.info.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
1900 // This may be a heavy-weight process! Note that the package
1901 // manager will ensure that only activity can run in the main
1902 // process of the .apk, which is the only thing that will be
1903 // considered heavy-weight.
1904 if (app.processName.equals(app.info.packageName)) {
1905 if (mHeavyWeightProcess != null && mHeavyWeightProcess != app) {
1906 Log.w(TAG, "Starting new heavy weight process " + app
1907 + " when already running " + mHeavyWeightProcess);
1908 }
1909 mHeavyWeightProcess = app;
1910 Message msg = mHandler.obtainMessage(POST_HEAVY_NOTIFICATION_MSG);
1911 msg.obj = r;
1912 mHandler.sendMessage(msg);
1913 }
1914 }
1915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916 } catch (RemoteException e) {
1917 if (r.launchFailed) {
1918 // This is the second time we failed -- finish activity
1919 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001920 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001921 + r.intent.getComponent().flattenToShortString()
1922 + ", giving up", e);
1923 appDiedLocked(app, app.pid, app.thread);
1924 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1925 "2nd-crash");
1926 return false;
1927 }
1928
1929 // This is the first time we failed -- restart process and
1930 // retry.
1931 app.activities.remove(r);
1932 throw e;
1933 }
1934
1935 r.launchFailed = false;
1936 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001937 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 + " being launched, but already in LRU list");
1939 }
1940
1941 if (andResume) {
1942 // As part of the process of launching, ActivityThread also performs
1943 // a resume.
1944 r.state = ActivityState.RESUMED;
1945 r.icicle = null;
1946 r.haveState = false;
1947 r.stopped = false;
1948 mResumedActivity = r;
1949 r.task.touchActiveTime();
1950 completeResumeLocked(r);
1951 pauseIfSleepingLocked();
1952 } else {
1953 // This activity is not starting in the resumed state... which
1954 // should look like we asked it to pause+stop (but remain visible),
1955 // and it has done so and reported back the current icicle and
1956 // other state.
1957 r.state = ActivityState.STOPPED;
1958 r.stopped = true;
1959 }
1960
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001961 // Launch the new version setup screen if needed. We do this -after-
1962 // launching the initial activity (that is, home), so that it can have
1963 // a chance to initialize itself while in the background, making the
1964 // switch back to it faster and look better.
1965 startSetupActivityLocked();
1966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 return true;
1968 }
1969
1970 private final void startSpecificActivityLocked(HistoryRecord r,
1971 boolean andResume, boolean checkConfig) {
1972 // Is this activity's application already running?
1973 ProcessRecord app = getProcessRecordLocked(r.processName,
1974 r.info.applicationInfo.uid);
1975
1976 if (r.startTime == 0) {
1977 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001978 if (mInitialStartTime == 0) {
1979 mInitialStartTime = r.startTime;
1980 }
1981 } else if (mInitialStartTime == 0) {
1982 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 }
1984
1985 if (app != null && app.thread != null) {
1986 try {
1987 realStartActivityLocked(r, app, andResume, checkConfig);
1988 return;
1989 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001990 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001991 + r.intent.getComponent().flattenToShortString(), e);
1992 }
1993
1994 // If a dead object exception was thrown -- fall through to
1995 // restart the application.
1996 }
1997
1998 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001999 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 }
2001
2002 private final ProcessRecord startProcessLocked(String processName,
2003 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002004 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002005 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
2006 // We don't have to do anything more if:
2007 // (1) There is an existing application record; and
2008 // (2) The caller doesn't think it is dead, OR there is no thread
2009 // object attached to it so we know it couldn't have crashed; and
2010 // (3) There is a pid assigned to it, so it is either starting or
2011 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002012 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 + " app=" + app + " knownToBeDead=" + knownToBeDead
2014 + " thread=" + (app != null ? app.thread : null)
2015 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01002016 if (app != null && app.pid > 0) {
2017 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002018 // We already have the app running, or are waiting for it to
2019 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01002020 return app;
2021 } else {
2022 // An application record is attached to a previous process,
2023 // clean it up now.
2024 handleAppDiedLocked(app, true);
2025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002027
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028 String hostingNameStr = hostingName != null
2029 ? hostingName.flattenToShortString() : null;
2030
2031 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
2032 // If we are in the background, then check to see if this process
2033 // is bad. If so, we will just silently fail.
2034 if (mBadProcesses.get(info.processName, info.uid) != null) {
2035 return null;
2036 }
2037 } else {
2038 // When the user is explicitly starting a process, then clear its
2039 // crash count so that we won't make it bad until they see at
2040 // least one crash dialog again, and make the process good again
2041 // if it had been bad.
2042 mProcessCrashTimes.remove(info.processName, info.uid);
2043 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002044 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002045 info.processName);
2046 mBadProcesses.remove(info.processName, info.uid);
2047 if (app != null) {
2048 app.bad = false;
2049 }
2050 }
2051 }
2052
2053 if (app == null) {
2054 app = newProcessRecordLocked(null, info, processName);
2055 mProcessNames.put(processName, info.uid, app);
2056 } else {
2057 // If this is a new package in the process, add the package to the list
2058 app.addPackage(info.packageName);
2059 }
2060
2061 // If the system is not ready yet, then hold off on starting this
2062 // process until it is.
2063 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002064 && !isAllowedWhileBooting(info)
2065 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 if (!mProcessesOnHold.contains(app)) {
2067 mProcessesOnHold.add(app);
2068 }
2069 return app;
2070 }
2071
2072 startProcessLocked(app, hostingType, hostingNameStr);
2073 return (app.pid != 0) ? app : null;
2074 }
2075
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002076 boolean isAllowedWhileBooting(ApplicationInfo ai) {
2077 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
2078 }
2079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002080 private final void startProcessLocked(ProcessRecord app,
2081 String hostingType, String hostingNameStr) {
2082 if (app.pid > 0 && app.pid != MY_PID) {
2083 synchronized (mPidsSelfLocked) {
2084 mPidsSelfLocked.remove(app.pid);
2085 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
2086 }
2087 app.pid = 0;
2088 }
2089
2090 mProcessesOnHold.remove(app);
2091
2092 updateCpuStats();
2093
2094 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
2095 mProcDeaths[0] = 0;
2096
2097 try {
2098 int uid = app.info.uid;
2099 int[] gids = null;
2100 try {
2101 gids = mContext.getPackageManager().getPackageGids(
2102 app.info.packageName);
2103 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002104 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105 }
2106 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2107 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2108 && mTopComponent != null
2109 && app.processName.equals(mTopComponent.getPackageName())) {
2110 uid = 0;
2111 }
2112 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2113 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2114 uid = 0;
2115 }
2116 }
2117 int debugFlags = 0;
2118 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2119 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
2120 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002121 // Run the app in safe mode if its manifest requests so or the
2122 // system is booted in safe mode.
2123 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2124 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002125 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2128 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2129 }
2130 if ("1".equals(SystemProperties.get("debug.assert"))) {
2131 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2132 }
2133 int pid = Process.start("android.app.ActivityThread",
2134 mSimpleProcessManagement ? app.processName : null, uid, uid,
2135 gids, debugFlags, null);
2136 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2137 synchronized (bs) {
2138 if (bs.isOnBattery()) {
2139 app.batteryStats.incStartsLocked();
2140 }
2141 }
2142
Doug Zongker2bec3d42009-12-04 12:52:44 -08002143 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 app.processName, hostingType,
2145 hostingNameStr != null ? hostingNameStr : "");
2146
2147 if (app.persistent) {
2148 Watchdog.getInstance().processStarted(app, app.processName, pid);
2149 }
2150
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002151 StringBuilder buf = mStringBuilder;
2152 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153 buf.append("Start proc ");
2154 buf.append(app.processName);
2155 buf.append(" for ");
2156 buf.append(hostingType);
2157 if (hostingNameStr != null) {
2158 buf.append(" ");
2159 buf.append(hostingNameStr);
2160 }
2161 buf.append(": pid=");
2162 buf.append(pid);
2163 buf.append(" uid=");
2164 buf.append(uid);
2165 buf.append(" gids={");
2166 if (gids != null) {
2167 for (int gi=0; gi<gids.length; gi++) {
2168 if (gi != 0) buf.append(", ");
2169 buf.append(gids[gi]);
2170
2171 }
2172 }
2173 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002174 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 if (pid == 0 || pid == MY_PID) {
2176 // Processes are being emulated with threads.
2177 app.pid = MY_PID;
2178 app.removed = false;
2179 mStartingProcesses.add(app);
2180 } else if (pid > 0) {
2181 app.pid = pid;
2182 app.removed = false;
2183 synchronized (mPidsSelfLocked) {
2184 this.mPidsSelfLocked.put(pid, app);
2185 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2186 msg.obj = app;
2187 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2188 }
2189 } else {
2190 app.pid = 0;
2191 RuntimeException e = new RuntimeException(
2192 "Failure starting process " + app.processName
2193 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002194 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195 }
2196 } catch (RuntimeException e) {
2197 // XXX do better error recovery.
2198 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002199 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 }
2201 }
2202
2203 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2204 if (mPausingActivity != null) {
2205 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002206 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 + mPausingActivity, e);
2208 }
2209 HistoryRecord prev = mResumedActivity;
2210 if (prev == null) {
2211 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002212 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213 resumeTopActivityLocked(null);
2214 return;
2215 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002216 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002217 mResumedActivity = null;
2218 mPausingActivity = prev;
2219 mLastPausedActivity = prev;
2220 prev.state = ActivityState.PAUSING;
2221 prev.task.touchActiveTime();
2222
2223 updateCpuStats();
2224
2225 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002226 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002228 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002229 System.identityHashCode(prev),
2230 prev.shortComponentName);
2231 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2232 prev.configChangeFlags);
2233 updateUsageStats(prev, false);
2234 } catch (Exception e) {
2235 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002236 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237 mPausingActivity = null;
2238 mLastPausedActivity = null;
2239 }
2240 } else {
2241 mPausingActivity = null;
2242 mLastPausedActivity = null;
2243 }
2244
2245 // If we are not going to sleep, we want to ensure the device is
2246 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002247 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 mLaunchingActivity.acquire();
2249 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2250 // To be safe, don't allow the wake lock to be held for too long.
2251 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2252 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2253 }
2254 }
2255
2256
2257 if (mPausingActivity != null) {
2258 // Have the window manager pause its key dispatching until the new
2259 // activity has started. If we're pausing the activity just because
2260 // the screen is being turned off and the UI is sleeping, don't interrupt
2261 // key dispatch; the same activity will pick it up again on wakeup.
2262 if (!uiSleeping) {
2263 prev.pauseKeyDispatchingLocked();
2264 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002265 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 }
2267
2268 // Schedule a pause timeout in case the app doesn't respond.
2269 // We don't give it much time because this directly impacts the
2270 // responsiveness seen by the user.
2271 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2272 msg.obj = prev;
2273 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002274 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 } else {
2276 // This activity failed to schedule the
2277 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002278 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 resumeTopActivityLocked(null);
2280 }
2281 }
2282
2283 private final void completePauseLocked() {
2284 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002285 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002286
2287 if (prev != null) {
2288 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002289 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2291 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002292 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 if (prev.waitingVisible) {
2294 prev.waitingVisible = false;
2295 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002296 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002297 TAG, "Complete pause, no longer waiting: " + prev);
2298 }
2299 if (prev.configDestroy) {
2300 // The previous is being paused because the configuration
2301 // is changing, which means it is actually stopping...
2302 // To juggle the fact that we are also starting a new
2303 // instance right now, we need to first completely stop
2304 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002305 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002306 destroyActivityLocked(prev, true);
2307 } else {
2308 mStoppingActivities.add(prev);
2309 if (mStoppingActivities.size() > 3) {
2310 // If we already have a few activities waiting to stop,
2311 // then give up on things going idle and start clearing
2312 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002313 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314 Message msg = Message.obtain();
2315 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2316 mHandler.sendMessage(msg);
2317 }
2318 }
2319 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002320 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002321 prev = null;
2322 }
2323 mPausingActivity = null;
2324 }
2325
Dianne Hackborn55280a92009-05-07 15:53:46 -07002326 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002327 resumeTopActivityLocked(prev);
2328 } else {
2329 if (mGoingToSleep.isHeld()) {
2330 mGoingToSleep.release();
2331 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002332 if (mShuttingDown) {
2333 notifyAll();
2334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 }
2336
2337 if (prev != null) {
2338 prev.resumeKeyDispatchingLocked();
2339 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002340
2341 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2342 long diff = 0;
2343 synchronized (mProcessStatsThread) {
2344 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2345 }
2346 if (diff > 0) {
2347 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2348 synchronized (bsi) {
2349 BatteryStatsImpl.Uid.Proc ps =
2350 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2351 prev.info.packageName);
2352 if (ps != null) {
2353 ps.addForegroundTimeLocked(diff);
2354 }
2355 }
2356 }
2357 }
2358 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002359 }
2360
2361 /**
2362 * Once we know that we have asked an application to put an activity in
2363 * the resumed state (either by launching it or explicitly telling it),
2364 * this function updates the rest of our state to match that fact.
2365 */
2366 private final void completeResumeLocked(HistoryRecord next) {
2367 next.idle = false;
2368 next.results = null;
2369 next.newIntents = null;
2370
2371 // schedule an idle timeout in case the app doesn't do it for us.
2372 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2373 msg.obj = next;
2374 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2375
2376 if (false) {
2377 // The activity was never told to pause, so just keep
2378 // things going as-is. To maintain our own state,
2379 // we need to emulate it coming back and saying it is
2380 // idle.
2381 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2382 msg.obj = next;
2383 mHandler.sendMessage(msg);
2384 }
2385
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002386 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002388 next.thumbnail = null;
2389 setFocusedActivityLocked(next);
2390 next.resumeKeyDispatchingLocked();
2391 ensureActivitiesVisibleLocked(null, 0);
2392 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002393 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002394
2395 // Mark the point when the activity is resuming
2396 // TODO: To be more accurate, the mark should be before the onCreate,
2397 // not after the onResume. But for subsequent starts, onResume is fine.
2398 if (next.app != null) {
2399 synchronized (mProcessStatsThread) {
2400 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2401 }
2402 } else {
2403 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002405 }
2406
2407 /**
2408 * Make sure that all activities that need to be visible (that is, they
2409 * currently can be seen by the user) actually are.
2410 */
2411 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2412 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002413 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002414 TAG, "ensureActivitiesVisible behind " + top
2415 + " configChanges=0x" + Integer.toHexString(configChanges));
2416
2417 // If the top activity is not fullscreen, then we need to
2418 // make sure any activities under it are now visible.
2419 final int count = mHistory.size();
2420 int i = count-1;
2421 while (mHistory.get(i) != top) {
2422 i--;
2423 }
2424 HistoryRecord r;
2425 boolean behindFullscreen = false;
2426 for (; i>=0; i--) {
2427 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002428 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 TAG, "Make visible? " + r + " finishing=" + r.finishing
2430 + " state=" + r.state);
2431 if (r.finishing) {
2432 continue;
2433 }
2434
2435 final boolean doThisProcess = onlyThisProcess == null
2436 || onlyThisProcess.equals(r.processName);
2437
2438 // First: if this is not the current activity being started, make
2439 // sure it matches the current configuration.
2440 if (r != starting && doThisProcess) {
2441 ensureActivityConfigurationLocked(r, 0);
2442 }
2443
2444 if (r.app == null || r.app.thread == null) {
2445 if (onlyThisProcess == null
2446 || onlyThisProcess.equals(r.processName)) {
2447 // This activity needs to be visible, but isn't even
2448 // running... get it started, but don't resume it
2449 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002450 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002451 TAG, "Start and freeze screen for " + r);
2452 if (r != starting) {
2453 r.startFreezingScreenLocked(r.app, configChanges);
2454 }
2455 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002456 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002457 TAG, "Starting and making visible: " + r);
2458 mWindowManager.setAppVisibility(r, true);
2459 }
2460 if (r != starting) {
2461 startSpecificActivityLocked(r, false, false);
2462 }
2463 }
2464
2465 } else if (r.visible) {
2466 // If this activity is already visible, then there is nothing
2467 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002468 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002469 TAG, "Skipping: already visible at " + r);
2470 r.stopFreezingScreenLocked(false);
2471
2472 } else if (onlyThisProcess == null) {
2473 // This activity is not currently visible, but is running.
2474 // Tell it to become visible.
2475 r.visible = true;
2476 if (r.state != ActivityState.RESUMED && r != starting) {
2477 // If this activity is paused, tell it
2478 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002479 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002480 TAG, "Making visible and scheduling visibility: " + r);
2481 try {
2482 mWindowManager.setAppVisibility(r, true);
2483 r.app.thread.scheduleWindowVisibility(r, true);
2484 r.stopFreezingScreenLocked(false);
2485 } catch (Exception e) {
2486 // Just skip on any failure; we'll make it
2487 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002488 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002489 + r.intent.getComponent(), e);
2490 }
2491 }
2492 }
2493
2494 // Aggregate current change flags.
2495 configChanges |= r.configChangeFlags;
2496
2497 if (r.fullscreen) {
2498 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002499 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 TAG, "Stopping: fullscreen at " + r);
2501 behindFullscreen = true;
2502 i--;
2503 break;
2504 }
2505 }
2506
2507 // Now for any activities that aren't visible to the user, make
2508 // sure they no longer are keeping the screen frozen.
2509 while (i >= 0) {
2510 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002511 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 TAG, "Make invisible? " + r + " finishing=" + r.finishing
2513 + " state=" + r.state
2514 + " behindFullscreen=" + behindFullscreen);
2515 if (!r.finishing) {
2516 if (behindFullscreen) {
2517 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002518 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002519 TAG, "Making invisible: " + r);
2520 r.visible = false;
2521 try {
2522 mWindowManager.setAppVisibility(r, false);
2523 if ((r.state == ActivityState.STOPPING
2524 || r.state == ActivityState.STOPPED)
2525 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002526 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 TAG, "Scheduling invisibility: " + r);
2528 r.app.thread.scheduleWindowVisibility(r, false);
2529 }
2530 } catch (Exception e) {
2531 // Just skip on any failure; we'll make it
2532 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002533 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002534 + r.intent.getComponent(), e);
2535 }
2536 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002537 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002538 TAG, "Already invisible: " + r);
2539 }
2540 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002541 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 TAG, "Now behindFullscreen: " + r);
2543 behindFullscreen = true;
2544 }
2545 }
2546 i--;
2547 }
2548 }
2549
2550 /**
2551 * Version of ensureActivitiesVisible that can easily be called anywhere.
2552 */
2553 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2554 int configChanges) {
2555 HistoryRecord r = topRunningActivityLocked(null);
2556 if (r != null) {
2557 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2558 }
2559 }
2560
2561 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2562 if (resumed) {
2563 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2564 } else {
2565 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2566 }
2567 }
2568
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002569 private boolean startHomeActivityLocked() {
2570 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2571 && mTopAction == null) {
2572 // We are running in factory test mode, but unable to find
2573 // the factory test app, so just sit around displaying the
2574 // error message and don't try to start anything.
2575 return false;
2576 }
2577 Intent intent = new Intent(
2578 mTopAction,
2579 mTopData != null ? Uri.parse(mTopData) : null);
2580 intent.setComponent(mTopComponent);
2581 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2582 intent.addCategory(Intent.CATEGORY_HOME);
2583 }
2584 ActivityInfo aInfo =
2585 intent.resolveActivityInfo(mContext.getPackageManager(),
2586 STOCK_PM_FLAGS);
2587 if (aInfo != null) {
2588 intent.setComponent(new ComponentName(
2589 aInfo.applicationInfo.packageName, aInfo.name));
2590 // Don't do this if the home app is currently being
2591 // instrumented.
2592 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2593 aInfo.applicationInfo.uid);
2594 if (app == null || app.instrumentationClass == null) {
2595 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2596 startActivityLocked(null, intent, null, null, 0, aInfo,
2597 null, null, 0, 0, 0, false, false);
2598 }
2599 }
2600
2601
2602 return true;
2603 }
2604
2605 /**
2606 * Starts the "new version setup screen" if appropriate.
2607 */
2608 private void startSetupActivityLocked() {
2609 // Only do this once per boot.
2610 if (mCheckedForSetup) {
2611 return;
2612 }
2613
2614 // We will show this screen if the current one is a different
2615 // version than the last one shown, and we are not running in
2616 // low-level factory test mode.
2617 final ContentResolver resolver = mContext.getContentResolver();
2618 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2619 Settings.Secure.getInt(resolver,
2620 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2621 mCheckedForSetup = true;
2622
2623 // See if we should be showing the platform update setup UI.
2624 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2625 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2626 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2627
2628 // We don't allow third party apps to replace this.
2629 ResolveInfo ri = null;
2630 for (int i=0; ris != null && i<ris.size(); i++) {
2631 if ((ris.get(i).activityInfo.applicationInfo.flags
2632 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2633 ri = ris.get(i);
2634 break;
2635 }
2636 }
2637
2638 if (ri != null) {
2639 String vers = ri.activityInfo.metaData != null
2640 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2641 : null;
2642 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2643 vers = ri.activityInfo.applicationInfo.metaData.getString(
2644 Intent.METADATA_SETUP_VERSION);
2645 }
2646 String lastVers = Settings.Secure.getString(
2647 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2648 if (vers != null && !vers.equals(lastVers)) {
2649 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2650 intent.setComponent(new ComponentName(
2651 ri.activityInfo.packageName, ri.activityInfo.name));
2652 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2653 null, null, 0, 0, 0, false, false);
2654 }
2655 }
2656 }
2657 }
2658
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002659 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002660 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002661
2662 final int identHash = System.identityHashCode(r);
2663 updateUsageStats(r, true);
2664
2665 int i = mWatchers.beginBroadcast();
2666 while (i > 0) {
2667 i--;
2668 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2669 if (w != null) {
2670 try {
2671 w.activityResuming(identHash);
2672 } catch (RemoteException e) {
2673 }
2674 }
2675 }
2676 mWatchers.finishBroadcast();
2677 }
2678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 /**
2680 * Ensure that the top activity in the stack is resumed.
2681 *
2682 * @param prev The previously resumed activity, for when in the process
2683 * of pausing; can be null to call from elsewhere.
2684 *
2685 * @return Returns true if something is being resumed, or false if
2686 * nothing happened.
2687 */
2688 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2689 // Find the first activity that is not finishing.
2690 HistoryRecord next = topRunningActivityLocked(null);
2691
2692 // Remember how we'll process this pause/resume situation, and ensure
2693 // that the state is reset however we wind up proceeding.
2694 final boolean userLeaving = mUserLeaving;
2695 mUserLeaving = false;
2696
2697 if (next == null) {
2698 // There are no more activities! Let's just start up the
2699 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002700 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 }
2702
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002703 next.delayedResume = false;
2704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 // If the top activity is the resumed one, nothing to do.
2706 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2707 // Make sure we have executed any pending transitions, since there
2708 // should be nothing left to do at this point.
2709 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002710 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 return false;
2712 }
2713
2714 // If we are sleeping, and there is no resumed activity, and the top
2715 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002716 if ((mSleeping || mShuttingDown)
2717 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002718 // Make sure we have executed any pending transitions, since there
2719 // should be nothing left to do at this point.
2720 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002721 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 return false;
2723 }
2724
2725 // The activity may be waiting for stop, but that is no longer
2726 // appropriate for it.
2727 mStoppingActivities.remove(next);
2728 mWaitingVisibleActivities.remove(next);
2729
Joe Onorato8a9b2202010-02-26 18:56:32 -08002730 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731
2732 // If we are currently pausing an activity, then don't do anything
2733 // until that is done.
2734 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002735 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736 return false;
2737 }
2738
2739 // We need to start pausing the current activity so the top one
2740 // can be resumed...
2741 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002742 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002743 startPausingLocked(userLeaving, false);
2744 return true;
2745 }
2746
2747 if (prev != null && prev != next) {
2748 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2749 prev.waitingVisible = true;
2750 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002751 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 TAG, "Resuming top, waiting visible to hide: " + prev);
2753 } else {
2754 // The next activity is already visible, so hide the previous
2755 // activity's windows right now so we can show the new one ASAP.
2756 // We only do this if the previous is finishing, which should mean
2757 // it is on top of the one being resumed so hiding it quickly
2758 // is good. Otherwise, we want to do the normal route of allowing
2759 // the resumed activity to be shown so we can decide if the
2760 // previous should actually be hidden depending on whether the
2761 // new one is found to be full-screen or not.
2762 if (prev.finishing) {
2763 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002764 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 + prev + ", waitingVisible="
2766 + (prev != null ? prev.waitingVisible : null)
2767 + ", nowVisible=" + next.nowVisible);
2768 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002769 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002770 + prev + ", waitingVisible="
2771 + (prev != null ? prev.waitingVisible : null)
2772 + ", nowVisible=" + next.nowVisible);
2773 }
2774 }
2775 }
2776
2777 // We are starting up the next activity, so tell the window manager
2778 // that the previous one will be hidden soon. This way it can know
2779 // to ignore it when computing the desired screen orientation.
2780 if (prev != null) {
2781 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002782 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002784 if (mNoAnimActivities.contains(prev)) {
2785 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2786 } else {
2787 mWindowManager.prepareAppTransition(prev.task == next.task
2788 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2789 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 mWindowManager.setAppWillBeHidden(prev);
2792 mWindowManager.setAppVisibility(prev, false);
2793 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002794 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002796 if (mNoAnimActivities.contains(next)) {
2797 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2798 } else {
2799 mWindowManager.prepareAppTransition(prev.task == next.task
2800 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2801 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2802 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 }
2804 if (false) {
2805 mWindowManager.setAppWillBeHidden(prev);
2806 mWindowManager.setAppVisibility(prev, false);
2807 }
2808 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002809 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002810 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002811 if (mNoAnimActivities.contains(next)) {
2812 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2813 } else {
2814 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002816 }
2817
2818 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002819 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820
2821 // This activity is now becoming visible.
2822 mWindowManager.setAppVisibility(next, true);
2823
2824 HistoryRecord lastResumedActivity = mResumedActivity;
2825 ActivityState lastState = next.state;
2826
2827 updateCpuStats();
2828
2829 next.state = ActivityState.RESUMED;
2830 mResumedActivity = next;
2831 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002832 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833 updateLRUListLocked(next);
2834
2835 // Have the window manager re-evaluate the orientation of
2836 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002837 boolean updated;
2838 synchronized (this) {
2839 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2840 mConfiguration,
2841 next.mayFreezeScreenLocked(next.app) ? next : null);
2842 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002843 next.frozenBeforeDestroy = true;
2844 }
2845 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002846 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002847 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 // The configuration update wasn't able to keep the existing
2849 // instance of the activity, and instead started a new one.
2850 // We should be all done, but let's just make sure our activity
2851 // is still at the top and schedule another run if something
2852 // weird happened.
2853 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002854 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002855 "Activity config changed during resume: " + next
2856 + ", new next: " + nextNext);
2857 if (nextNext != next) {
2858 // Do over!
2859 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2860 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002861 setFocusedActivityLocked(next);
2862 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002864 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002865 return true;
2866 }
2867
2868 try {
2869 // Deliver all pending results.
2870 ArrayList a = next.results;
2871 if (a != null) {
2872 final int N = a.size();
2873 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002874 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002875 TAG, "Delivering results to " + next
2876 + ": " + a);
2877 next.app.thread.scheduleSendResult(next, a);
2878 }
2879 }
2880
2881 if (next.newIntents != null) {
2882 next.app.thread.scheduleNewIntent(next.newIntents, next);
2883 }
2884
Doug Zongker2bec3d42009-12-04 12:52:44 -08002885 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 System.identityHashCode(next),
2887 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888
2889 next.app.thread.scheduleResumeActivity(next,
2890 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 pauseIfSleepingLocked();
2893
2894 } catch (Exception e) {
2895 // Whoops, need to restart this activity!
2896 next.state = lastState;
2897 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002898 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 if (!next.hasBeenLaunched) {
2900 next.hasBeenLaunched = true;
2901 } else {
2902 if (SHOW_APP_STARTING_ICON) {
2903 mWindowManager.setAppStartingWindow(
2904 next, next.packageName, next.theme,
2905 next.nonLocalizedLabel,
2906 next.labelRes, next.icon, null, true);
2907 }
2908 }
2909 startSpecificActivityLocked(next, true, false);
2910 return true;
2911 }
2912
2913 // From this point on, if something goes wrong there is no way
2914 // to recover the activity.
2915 try {
2916 next.visible = true;
2917 completeResumeLocked(next);
2918 } catch (Exception e) {
2919 // If any exception gets thrown, toss away this
2920 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002921 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002922 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2923 "resume-exception");
2924 return true;
2925 }
2926
2927 // Didn't need to use the icicle, and it is now out of date.
2928 next.icicle = null;
2929 next.haveState = false;
2930 next.stopped = false;
2931
2932 } else {
2933 // Whoops, need to restart this activity!
2934 if (!next.hasBeenLaunched) {
2935 next.hasBeenLaunched = true;
2936 } else {
2937 if (SHOW_APP_STARTING_ICON) {
2938 mWindowManager.setAppStartingWindow(
2939 next, next.packageName, next.theme,
2940 next.nonLocalizedLabel,
2941 next.labelRes, next.icon, null, true);
2942 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002943 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 }
2945 startSpecificActivityLocked(next, true, true);
2946 }
2947
2948 return true;
2949 }
2950
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002951 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2952 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 final int NH = mHistory.size();
2954
2955 int addPos = -1;
2956
2957 if (!newTask) {
2958 // If starting in an existing task, find where that is...
2959 HistoryRecord next = null;
2960 boolean startIt = true;
2961 for (int i = NH-1; i >= 0; i--) {
2962 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2963 if (p.finishing) {
2964 continue;
2965 }
2966 if (p.task == r.task) {
2967 // Here it is! Now, if this is not yet visible to the
2968 // user, then just add it without starting; it will
2969 // get started when the user navigates back to it.
2970 addPos = i+1;
2971 if (!startIt) {
2972 mHistory.add(addPos, r);
2973 r.inHistory = true;
2974 r.task.numActivities++;
2975 mWindowManager.addAppToken(addPos, r, r.task.taskId,
2976 r.info.screenOrientation, r.fullscreen);
2977 if (VALIDATE_TOKENS) {
2978 mWindowManager.validateAppTokens(mHistory);
2979 }
2980 return;
2981 }
2982 break;
2983 }
2984 if (p.fullscreen) {
2985 startIt = false;
2986 }
2987 next = p;
2988 }
2989 }
2990
2991 // Place a new activity at top of stack, so it is next to interact
2992 // with the user.
2993 if (addPos < 0) {
2994 addPos = mHistory.size();
2995 }
2996
2997 // If we are not placing the new activity frontmost, we do not want
2998 // to deliver the onUserLeaving callback to the actual frontmost
2999 // activity
3000 if (addPos < NH) {
3001 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003002 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 }
3004
3005 // Slot the activity into the history stack and proceed
3006 mHistory.add(addPos, r);
3007 r.inHistory = true;
3008 r.frontOfTask = newTask;
3009 r.task.numActivities++;
3010 if (NH > 0) {
3011 // We want to show the starting preview window if we are
3012 // switching to a new task, or the next activity's process is
3013 // not currently running.
3014 boolean showStartingIcon = newTask;
3015 ProcessRecord proc = r.app;
3016 if (proc == null) {
3017 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
3018 }
3019 if (proc == null || proc.thread == null) {
3020 showStartingIcon = true;
3021 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003022 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003024 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3025 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
3026 mNoAnimActivities.add(r);
3027 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3028 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
3029 mNoAnimActivities.remove(r);
3030 } else {
3031 mWindowManager.prepareAppTransition(newTask
3032 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
3033 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
3034 mNoAnimActivities.remove(r);
3035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 mWindowManager.addAppToken(
3037 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
3038 boolean doShow = true;
3039 if (newTask) {
3040 // Even though this activity is starting fresh, we still need
3041 // to reset it to make sure we apply affinities to move any
3042 // existing activities from other tasks in to it.
3043 // If the caller has requested that the target task be
3044 // reset, then do so.
3045 if ((r.intent.getFlags()
3046 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3047 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003048 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 }
3050 }
3051 if (SHOW_APP_STARTING_ICON && doShow) {
3052 // Figure out if we are transitioning from another activity that is
3053 // "has the same starting icon" as the next one. This allows the
3054 // window manager to keep the previous window it had previously
3055 // created, if it still had one.
3056 HistoryRecord prev = mResumedActivity;
3057 if (prev != null) {
3058 // We don't want to reuse the previous starting preview if:
3059 // (1) The current activity is in a different task.
3060 if (prev.task != r.task) prev = null;
3061 // (2) The current activity is already displayed.
3062 else if (prev.nowVisible) prev = null;
3063 }
3064 mWindowManager.setAppStartingWindow(
3065 r, r.packageName, r.theme, r.nonLocalizedLabel,
3066 r.labelRes, r.icon, prev, showStartingIcon);
3067 }
3068 } else {
3069 // If this is the first activity, don't do any fancy animations,
3070 // because there is nothing for it to animate on top of.
3071 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3072 r.info.screenOrientation, r.fullscreen);
3073 }
3074 if (VALIDATE_TOKENS) {
3075 mWindowManager.validateAppTokens(mHistory);
3076 }
3077
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003078 if (doResume) {
3079 resumeTopActivityLocked(null);
3080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 }
3082
3083 /**
3084 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003085 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
3086 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 * an instance of that activity in the stack and, if found, finish all
3088 * activities on top of it and return the instance.
3089 *
3090 * @param newR Description of the new activity being started.
3091 * @return Returns the old activity that should be continue to be used,
3092 * or null if none was found.
3093 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003094 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003095 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003097
3098 // First find the requested task.
3099 while (i > 0) {
3100 i--;
3101 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3102 if (r.task.taskId == taskId) {
3103 i++;
3104 break;
3105 }
3106 }
3107
3108 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003109 while (i > 0) {
3110 i--;
3111 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3112 if (r.finishing) {
3113 continue;
3114 }
3115 if (r.task.taskId != taskId) {
3116 return null;
3117 }
3118 if (r.realActivity.equals(newR.realActivity)) {
3119 // Here it is! Now finish everything in front...
3120 HistoryRecord ret = r;
3121 if (doClear) {
3122 while (i < (mHistory.size()-1)) {
3123 i++;
3124 r = (HistoryRecord)mHistory.get(i);
3125 if (r.finishing) {
3126 continue;
3127 }
3128 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3129 null, "clear")) {
3130 i--;
3131 }
3132 }
3133 }
3134
3135 // Finally, if this is a normal launch mode (that is, not
3136 // expecting onNewIntent()), then we will finish the current
3137 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003138 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3139 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003141 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003143 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144 null, "clear");
3145 }
3146 return null;
3147 }
3148 }
3149
3150 return ret;
3151 }
3152 }
3153
3154 return null;
3155 }
3156
3157 /**
3158 * Find the activity in the history stack within the given task. Returns
3159 * the index within the history at which it's found, or < 0 if not found.
3160 */
3161 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3162 int i = mHistory.size();
3163 while (i > 0) {
3164 i--;
3165 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3166 if (candidate.task.taskId != task) {
3167 break;
3168 }
3169 if (candidate.realActivity.equals(r.realActivity)) {
3170 return i;
3171 }
3172 }
3173
3174 return -1;
3175 }
3176
3177 /**
3178 * Reorder the history stack so that the activity at the given index is
3179 * brought to the front.
3180 */
3181 private final HistoryRecord moveActivityToFrontLocked(int where) {
3182 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3183 int top = mHistory.size();
3184 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3185 mHistory.add(top, newTop);
3186 oldTop.frontOfTask = false;
3187 newTop.frontOfTask = true;
3188 return newTop;
3189 }
3190
3191 /**
3192 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3193 * method will be called at the proper time.
3194 */
3195 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3196 boolean sent = false;
3197 if (r.state == ActivityState.RESUMED
3198 && r.app != null && r.app.thread != null) {
3199 try {
3200 ArrayList<Intent> ar = new ArrayList<Intent>();
3201 ar.add(new Intent(intent));
3202 r.app.thread.scheduleNewIntent(ar, r);
3203 sent = true;
3204 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003205 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 }
3207 }
3208 if (!sent) {
3209 r.addNewIntentLocked(new Intent(intent));
3210 }
3211 }
3212
3213 private final void logStartActivity(int tag, HistoryRecord r,
3214 TaskRecord task) {
3215 EventLog.writeEvent(tag,
3216 System.identityHashCode(r), task.taskId,
3217 r.shortComponentName, r.intent.getAction(),
3218 r.intent.getType(), r.intent.getDataString(),
3219 r.intent.getFlags());
3220 }
3221
3222 private final int startActivityLocked(IApplicationThread caller,
3223 Intent intent, String resolvedType,
3224 Uri[] grantedUriPermissions,
3225 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3226 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003227 int callingPid, int callingUid, boolean onlyIfNeeded,
3228 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003229 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003230
3231 HistoryRecord sourceRecord = null;
3232 HistoryRecord resultRecord = null;
3233 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003234 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003235 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003236 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3237 if (index >= 0) {
3238 sourceRecord = (HistoryRecord)mHistory.get(index);
3239 if (requestCode >= 0 && !sourceRecord.finishing) {
3240 resultRecord = sourceRecord;
3241 }
3242 }
3243 }
3244
3245 int launchFlags = intent.getFlags();
3246
3247 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3248 && sourceRecord != null) {
3249 // Transfer the result target from the source activity to the new
3250 // one being started, including any failures.
3251 if (requestCode >= 0) {
3252 return START_FORWARD_AND_REQUEST_CONFLICT;
3253 }
3254 resultRecord = sourceRecord.resultTo;
3255 resultWho = sourceRecord.resultWho;
3256 requestCode = sourceRecord.requestCode;
3257 sourceRecord.resultTo = null;
3258 if (resultRecord != null) {
3259 resultRecord.removeResultsLocked(
3260 sourceRecord, resultWho, requestCode);
3261 }
3262 }
3263
3264 int err = START_SUCCESS;
3265
3266 if (intent.getComponent() == null) {
3267 // We couldn't find a class that can handle the given Intent.
3268 // That's the end of that!
3269 err = START_INTENT_NOT_RESOLVED;
3270 }
3271
3272 if (err == START_SUCCESS && aInfo == null) {
3273 // We couldn't find the specific class specified in the Intent.
3274 // Also the end of the line.
3275 err = START_CLASS_NOT_FOUND;
3276 }
3277
3278 ProcessRecord callerApp = null;
3279 if (err == START_SUCCESS && caller != null) {
3280 callerApp = getRecordForAppLocked(caller);
3281 if (callerApp != null) {
3282 callingPid = callerApp.pid;
3283 callingUid = callerApp.info.uid;
3284 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003285 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003286 + " (pid=" + callingPid + ") when starting: "
3287 + intent.toString());
3288 err = START_PERMISSION_DENIED;
3289 }
3290 }
3291
3292 if (err != START_SUCCESS) {
3293 if (resultRecord != null) {
3294 sendActivityResultLocked(-1,
3295 resultRecord, resultWho, requestCode,
3296 Activity.RESULT_CANCELED, null);
3297 }
3298 return err;
3299 }
3300
3301 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3302 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3303 if (perm != PackageManager.PERMISSION_GRANTED) {
3304 if (resultRecord != null) {
3305 sendActivityResultLocked(-1,
3306 resultRecord, resultWho, requestCode,
3307 Activity.RESULT_CANCELED, null);
3308 }
3309 String msg = "Permission Denial: starting " + intent.toString()
3310 + " from " + callerApp + " (pid=" + callingPid
3311 + ", uid=" + callingUid + ")"
3312 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003313 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 throw new SecurityException(msg);
3315 }
3316
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003317 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003318 boolean abort = false;
3319 try {
3320 // The Intent we give to the watcher has the extra data
3321 // stripped off, since it can contain private information.
3322 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003323 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 aInfo.applicationInfo.packageName);
3325 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003326 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003327 }
3328
3329 if (abort) {
3330 if (resultRecord != null) {
3331 sendActivityResultLocked(-1,
3332 resultRecord, resultWho, requestCode,
3333 Activity.RESULT_CANCELED, null);
3334 }
3335 // We pretend to the caller that it was really started, but
3336 // they will just get a cancel result.
3337 return START_SUCCESS;
3338 }
3339 }
3340
3341 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3342 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003343 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003345 if (mResumedActivity == null
3346 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3347 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3348 PendingActivityLaunch pal = new PendingActivityLaunch();
3349 pal.r = r;
3350 pal.sourceRecord = sourceRecord;
3351 pal.grantedUriPermissions = grantedUriPermissions;
3352 pal.grantedMode = grantedMode;
3353 pal.onlyIfNeeded = onlyIfNeeded;
3354 mPendingActivityLaunches.add(pal);
3355 return START_SWITCHES_CANCELED;
3356 }
3357 }
3358
3359 if (mDidAppSwitch) {
3360 // This is the second allowed switch since we stopped switches,
3361 // so now just generally allow switches. Use case: user presses
3362 // home (switches disabled, switch to home, mDidAppSwitch now true);
3363 // user taps a home icon (coming from home so allowed, we hit here
3364 // and now allow anyone to switch again).
3365 mAppSwitchesAllowedTime = 0;
3366 } else {
3367 mDidAppSwitch = true;
3368 }
3369
3370 doPendingActivityLaunchesLocked(false);
3371
3372 return startActivityUncheckedLocked(r, sourceRecord,
3373 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3374 }
3375
3376 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3377 final int N = mPendingActivityLaunches.size();
3378 if (N <= 0) {
3379 return;
3380 }
3381 for (int i=0; i<N; i++) {
3382 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3383 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3384 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3385 doResume && i == (N-1));
3386 }
3387 mPendingActivityLaunches.clear();
3388 }
3389
3390 private final int startActivityUncheckedLocked(HistoryRecord r,
3391 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3392 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3393 final Intent intent = r.intent;
3394 final int callingUid = r.launchedFromUid;
3395
3396 int launchFlags = intent.getFlags();
3397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003398 // We'll invoke onUserLeaving before onPause only if the launching
3399 // activity did not explicitly state that this is an automated launch.
3400 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003401 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003402 "startActivity() => mUserLeaving=" + mUserLeaving);
3403
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003404 // If the caller has asked not to resume at this point, we make note
3405 // of this in the record so that we can skip it when trying to find
3406 // the top running activity.
3407 if (!doResume) {
3408 r.delayedResume = true;
3409 }
3410
3411 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3412 != 0 ? r : null;
3413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003414 // If the onlyIfNeeded flag is set, then we can do this if the activity
3415 // being launched is the same as the one making the call... or, as
3416 // a special case, if we do not know the caller then we count the
3417 // current top activity as the caller.
3418 if (onlyIfNeeded) {
3419 HistoryRecord checkedCaller = sourceRecord;
3420 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003421 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003422 }
3423 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3424 // Caller is not the same as launcher, so always needed.
3425 onlyIfNeeded = false;
3426 }
3427 }
3428
3429 if (grantedUriPermissions != null && callingUid > 0) {
3430 for (int i=0; i<grantedUriPermissions.length; i++) {
3431 grantUriPermissionLocked(callingUid, r.packageName,
3432 grantedUriPermissions[i], grantedMode, r);
3433 }
3434 }
3435
3436 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3437 intent, r);
3438
3439 if (sourceRecord == null) {
3440 // This activity is not being started from another... in this
3441 // case we -always- start a new task.
3442 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003443 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 -08003444 + intent);
3445 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3446 }
3447 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3448 // The original activity who is starting us is running as a single
3449 // instance... this new activity it is starting must go on its
3450 // own task.
3451 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3452 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3453 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3454 // The activity being started is a single instance... it always
3455 // gets launched into its own task.
3456 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3457 }
3458
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003459 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 // For whatever reason this activity is being launched into a new
3461 // task... yet the caller has requested a result back. Well, that
3462 // is pretty messed up, so instead immediately send back a cancel
3463 // and let the new task continue launched as normal without a
3464 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003465 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003466 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003467 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 Activity.RESULT_CANCELED, null);
3469 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 }
3471
3472 boolean addingToTask = false;
3473 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3474 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3475 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3476 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3477 // If bring to front is requested, and no result is requested, and
3478 // we can find a task that was started with this same
3479 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003480 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 // See if there is a task to bring to the front. If this is
3482 // a SINGLE_INSTANCE activity, there can be one and only one
3483 // instance of it in the history, and it is always in its own
3484 // unique task, so we do a special search.
3485 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3486 ? findTaskLocked(intent, r.info)
3487 : findActivityLocked(intent, r.info);
3488 if (taskTop != null) {
3489 if (taskTop.task.intent == null) {
3490 // This task was started because of movement of
3491 // the activity based on affinity... now that we
3492 // are actually launching it, we can assign the
3493 // base intent.
3494 taskTop.task.setIntent(intent, r.info);
3495 }
3496 // If the target task is not in the front, then we need
3497 // to bring it to the front... except... well, with
3498 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3499 // to have the same behavior as if a new instance was
3500 // being started, which means not bringing it to the front
3501 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003502 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003503 if (curTop.task != taskTop.task) {
3504 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3505 boolean callerAtFront = sourceRecord == null
3506 || curTop.task == sourceRecord.task;
3507 if (callerAtFront) {
3508 // We really do want to push this one into the
3509 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003510 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 }
3512 }
3513 // If the caller has requested that the target task be
3514 // reset, then do so.
3515 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3516 taskTop = resetTaskIfNeededLocked(taskTop, r);
3517 }
3518 if (onlyIfNeeded) {
3519 // We don't need to start a new activity, and
3520 // the client said not to do anything if that
3521 // is the case, so this is it! And for paranoia, make
3522 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003523 if (doResume) {
3524 resumeTopActivityLocked(null);
3525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 return START_RETURN_INTENT_TO_CALLER;
3527 }
3528 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3529 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3530 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3531 // In this situation we want to remove all activities
3532 // from the task up to the one being started. In most
3533 // cases this means we are resetting the task to its
3534 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003535 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003536 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 if (top != null) {
3538 if (top.frontOfTask) {
3539 // Activity aliases may mean we use different
3540 // intents for the top activity, so make sure
3541 // the task now has the identity of the new
3542 // intent.
3543 top.task.setIntent(r.intent, r.info);
3544 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003545 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546 deliverNewIntentLocked(top, r.intent);
3547 } else {
3548 // A special case: we need to
3549 // start the activity because it is not currently
3550 // running, and the caller has asked to clear the
3551 // current task to have this activity at the top.
3552 addingToTask = true;
3553 // Now pretend like this activity is being started
3554 // by the top of its task, so it is put in the
3555 // right place.
3556 sourceRecord = taskTop;
3557 }
3558 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3559 // In this case the top activity on the task is the
3560 // same as the one being launched, so we take that
3561 // as a request to bring the task to the foreground.
3562 // If the top activity in the task is the root
3563 // activity, deliver this new intent to it if it
3564 // desires.
3565 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3566 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003567 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 if (taskTop.frontOfTask) {
3569 taskTop.task.setIntent(r.intent, r.info);
3570 }
3571 deliverNewIntentLocked(taskTop, r.intent);
3572 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3573 // In this case we are launching the root activity
3574 // of the task, but with a different intent. We
3575 // should start a new instance on top.
3576 addingToTask = true;
3577 sourceRecord = taskTop;
3578 }
3579 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3580 // In this case an activity is being launched in to an
3581 // existing task, without resetting that task. This
3582 // is typically the situation of launching an activity
3583 // from a notification or shortcut. We want to place
3584 // the new activity on top of the current task.
3585 addingToTask = true;
3586 sourceRecord = taskTop;
3587 } else if (!taskTop.task.rootWasReset) {
3588 // In this case we are launching in to an existing task
3589 // that has not yet been started from its front door.
3590 // The current task has been brought to the front.
3591 // Ideally, we'd probably like to place this new task
3592 // at the bottom of its stack, but that's a little hard
3593 // to do with the current organization of the code so
3594 // for now we'll just drop it.
3595 taskTop.task.setIntent(r.intent, r.info);
3596 }
3597 if (!addingToTask) {
3598 // We didn't do anything... but it was needed (a.k.a., client
3599 // don't use that intent!) And for paranoia, make
3600 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003601 if (doResume) {
3602 resumeTopActivityLocked(null);
3603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003604 return START_TASK_TO_FRONT;
3605 }
3606 }
3607 }
3608 }
3609
3610 //String uri = r.intent.toURI();
3611 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003612 //Slog.i(TAG, "Given intent: " + r.intent);
3613 //Slog.i(TAG, "URI is: " + uri);
3614 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615
3616 if (r.packageName != null) {
3617 // If the activity being launched is the same as the one currently
3618 // at the top, then we need to check if it should only be launched
3619 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003620 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3621 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622 if (top.realActivity.equals(r.realActivity)) {
3623 if (top.app != null && top.app.thread != null) {
3624 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3625 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3626 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003627 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 // For paranoia, make sure we have correctly
3629 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003630 if (doResume) {
3631 resumeTopActivityLocked(null);
3632 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 if (onlyIfNeeded) {
3634 // We don't need to start a new activity, and
3635 // the client said not to do anything if that
3636 // is the case, so this is it!
3637 return START_RETURN_INTENT_TO_CALLER;
3638 }
3639 deliverNewIntentLocked(top, r.intent);
3640 return START_DELIVERED_TO_TOP;
3641 }
3642 }
3643 }
3644 }
3645
3646 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003647 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003649 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 Activity.RESULT_CANCELED, null);
3651 }
3652 return START_CLASS_NOT_FOUND;
3653 }
3654
3655 boolean newTask = false;
3656
3657 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003658 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3660 // todo: should do better management of integers.
3661 mCurTask++;
3662 if (mCurTask <= 0) {
3663 mCurTask = 1;
3664 }
3665 r.task = new TaskRecord(mCurTask, r.info, intent,
3666 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003667 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 + " in new task " + r.task);
3669 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003670 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671
3672 } else if (sourceRecord != null) {
3673 if (!addingToTask &&
3674 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3675 // In this case, we are adding the activity to an existing
3676 // task, but the caller has asked to clear that task if the
3677 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003678 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003679 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003681 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 deliverNewIntentLocked(top, r.intent);
3683 // For paranoia, make sure we have correctly
3684 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003685 if (doResume) {
3686 resumeTopActivityLocked(null);
3687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 return START_DELIVERED_TO_TOP;
3689 }
3690 } else if (!addingToTask &&
3691 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3692 // In this case, we are launching an activity in our own task
3693 // that may already be running somewhere in the history, and
3694 // we want to shuffle it to the front of the stack if so.
3695 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3696 if (where >= 0) {
3697 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003698 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003699 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003700 if (doResume) {
3701 resumeTopActivityLocked(null);
3702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003703 return START_DELIVERED_TO_TOP;
3704 }
3705 }
3706 // An existing activity is starting this new activity, so we want
3707 // to keep the new one in the same task as the one that is starting
3708 // it.
3709 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003710 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003711 + " in existing task " + r.task);
3712
3713 } else {
3714 // This not being started from an existing activity, and not part
3715 // of a new task... just put it in the top task, though these days
3716 // this case should never happen.
3717 final int N = mHistory.size();
3718 HistoryRecord prev =
3719 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3720 r.task = prev != null
3721 ? prev.task
3722 : new TaskRecord(mCurTask, r.info, intent,
3723 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003724 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003725 + " in new guessed " + r.task);
3726 }
3727 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003728 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003730 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003731 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003732 return START_SUCCESS;
3733 }
3734
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003735 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3736 long thisTime, long totalTime) {
3737 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3738 WaitResult w = mWaitingActivityLaunched.get(i);
3739 w.timeout = timeout;
3740 if (r != null) {
3741 w.who = new ComponentName(r.info.packageName, r.info.name);
3742 }
3743 w.thisTime = thisTime;
3744 w.totalTime = totalTime;
3745 }
3746 notify();
3747 }
3748
3749 void reportActivityVisibleLocked(HistoryRecord r) {
3750 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3751 WaitResult w = mWaitingActivityVisible.get(i);
3752 w.timeout = false;
3753 if (r != null) {
3754 w.who = new ComponentName(r.info.packageName, r.info.name);
3755 }
3756 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3757 w.thisTime = w.totalTime;
3758 }
3759 notify();
3760 }
3761
3762 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3764 int grantedMode, IBinder resultTo,
3765 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003766 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 // Refuse possible leaked file descriptors
3768 if (intent != null && intent.hasFileDescriptors()) {
3769 throw new IllegalArgumentException("File descriptors passed in Intent");
3770 }
3771
Dianne Hackborn860755f2010-06-03 18:47:52 -07003772 boolean componentSpecified = intent.getComponent() != null;
The Android Open Source Project4df24232009-03-05 14:34:35 -08003773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774 // Don't modify the client's object!
3775 intent = new Intent(intent);
3776
3777 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 ActivityInfo aInfo;
3779 try {
3780 ResolveInfo rInfo =
3781 ActivityThread.getPackageManager().resolveIntent(
3782 intent, resolvedType,
3783 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003784 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003785 aInfo = rInfo != null ? rInfo.activityInfo : null;
3786 } catch (RemoteException e) {
3787 aInfo = null;
3788 }
3789
3790 if (aInfo != null) {
3791 // Store the found target back into the intent, because now that
3792 // we have it we never want to do this again. For example, if the
3793 // user navigates back to this point in the history, we should
3794 // always restart the exact same activity.
3795 intent.setComponent(new ComponentName(
3796 aInfo.applicationInfo.packageName, aInfo.name));
3797
3798 // Don't debug things in the system process
3799 if (debug) {
3800 if (!aInfo.processName.equals("system")) {
3801 setDebugApp(aInfo.processName, true, false);
3802 }
3803 }
3804 }
3805
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003806 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003807 int callingPid;
3808 int callingUid;
3809 if (caller == null) {
3810 callingPid = Binder.getCallingPid();
3811 callingUid = Binder.getCallingUid();
3812 } else {
3813 callingPid = callingUid = -1;
3814 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003815
3816 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003817 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3818 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003821
Dianne Hackborn860755f2010-06-03 18:47:52 -07003822 if (aInfo != null &&
3823 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
3824 // This may be a heavy-weight process! Check to see if we already
3825 // have another, different heavy-weight process running.
3826 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3827 if (mHeavyWeightProcess != null &&
3828 (mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3829 !mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3830 int realCallingPid = callingPid;
3831 int realCallingUid = callingUid;
3832 if (caller != null) {
3833 ProcessRecord callerApp = getRecordForAppLocked(caller);
3834 if (callerApp != null) {
3835 realCallingPid = callerApp.pid;
3836 realCallingUid = callerApp.info.uid;
3837 } else {
3838 Slog.w(TAG, "Unable to find app for caller " + caller
3839 + " (pid=" + realCallingPid + ") when starting: "
3840 + intent.toString());
3841 return START_PERMISSION_DENIED;
3842 }
3843 }
3844
3845 IIntentSender target = getIntentSenderLocked(
3846 IActivityManager.INTENT_SENDER_ACTIVITY, "android",
3847 realCallingUid, null, null, 0, intent,
3848 resolvedType, PendingIntent.FLAG_CANCEL_CURRENT
3849 | PendingIntent.FLAG_ONE_SHOT);
3850
3851 Intent newIntent = new Intent();
3852 if (requestCode >= 0) {
3853 // Caller is requesting a result.
3854 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3855 }
3856 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3857 new IntentSender(target));
3858 if (mHeavyWeightProcess.activities.size() > 0) {
3859 HistoryRecord hist = mHeavyWeightProcess.activities.get(0);
3860 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3861 hist.packageName);
3862 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3863 hist.task.taskId);
3864 }
3865 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3866 aInfo.packageName);
3867 newIntent.setFlags(intent.getFlags());
3868 newIntent.setClassName("android",
3869 HeavyWeightSwitcherActivity.class.getName());
3870 intent = newIntent;
3871 resolvedType = null;
3872 caller = null;
3873 callingUid = Binder.getCallingUid();
3874 callingPid = Binder.getCallingPid();
3875 componentSpecified = true;
3876 try {
3877 ResolveInfo rInfo =
3878 ActivityThread.getPackageManager().resolveIntent(
3879 intent, null,
3880 PackageManager.MATCH_DEFAULT_ONLY
3881 | STOCK_PM_FLAGS);
3882 aInfo = rInfo != null ? rInfo.activityInfo : null;
3883 } catch (RemoteException e) {
3884 aInfo = null;
3885 }
3886 }
3887 }
3888 }
3889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 int res = startActivityLocked(caller, intent, resolvedType,
3891 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003892 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003893 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003894
Dianne Hackborne2522462010-03-29 18:41:30 -07003895 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003896 // If the caller also wants to switch to a new configuration,
3897 // do so now. This allows a clean switch, as we are waiting
3898 // for the current activity to pause (so we will not destroy
3899 // it), and have not yet started the next activity.
3900 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3901 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003902 mConfigWillChange = false;
3903 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3904 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003905 updateConfigurationLocked(config, null);
3906 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003908 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003909
3910 if (outResult != null) {
3911 outResult.result = res;
3912 if (res == IActivityManager.START_SUCCESS) {
3913 mWaitingActivityLaunched.add(outResult);
3914 do {
3915 try {
3916 wait();
3917 } catch (InterruptedException e) {
3918 }
3919 } while (!outResult.timeout && outResult.who == null);
3920 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3921 HistoryRecord r = this.topRunningActivityLocked(null);
3922 if (r.nowVisible) {
3923 outResult.timeout = false;
3924 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3925 outResult.totalTime = 0;
3926 outResult.thisTime = 0;
3927 } else {
3928 outResult.thisTime = SystemClock.uptimeMillis();
3929 mWaitingActivityVisible.add(outResult);
3930 do {
3931 try {
3932 wait();
3933 } catch (InterruptedException e) {
3934 }
3935 } while (!outResult.timeout && outResult.who == null);
3936 }
3937 }
3938 }
3939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 return res;
3941 }
3942 }
3943
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003944 public final int startActivity(IApplicationThread caller,
3945 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3946 int grantedMode, IBinder resultTo,
3947 String resultWho, int requestCode, boolean onlyIfNeeded,
3948 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003949 return startActivityMayWait(caller, intent, resolvedType,
3950 grantedUriPermissions, grantedMode, resultTo, resultWho,
3951 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003952 }
3953
3954 public final WaitResult startActivityAndWait(IApplicationThread caller,
3955 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3956 int grantedMode, IBinder resultTo,
3957 String resultWho, int requestCode, boolean onlyIfNeeded,
3958 boolean debug) {
3959 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003960 startActivityMayWait(caller, intent, resolvedType,
3961 grantedUriPermissions, grantedMode, resultTo, resultWho,
3962 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003963 return res;
3964 }
3965
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003966 public final int startActivityWithConfig(IApplicationThread caller,
3967 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3968 int grantedMode, IBinder resultTo,
3969 String resultWho, int requestCode, boolean onlyIfNeeded,
3970 boolean debug, Configuration config) {
3971 return startActivityMayWait(caller, intent, resolvedType,
3972 grantedUriPermissions, grantedMode, resultTo, resultWho,
3973 requestCode, onlyIfNeeded, debug, null, config);
3974 }
3975
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003976 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003977 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07003978 IBinder resultTo, String resultWho, int requestCode,
3979 int flagsMask, int flagsValues) {
3980 // Refuse possible leaked file descriptors
3981 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
3982 throw new IllegalArgumentException("File descriptors passed in Intent");
3983 }
3984
3985 IIntentSender sender = intent.getTarget();
3986 if (!(sender instanceof PendingIntentRecord)) {
3987 throw new IllegalArgumentException("Bad PendingIntent object");
3988 }
3989
3990 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07003991
3992 synchronized (this) {
3993 // If this is coming from the currently resumed activity, it is
3994 // effectively saying that app switches are allowed at this point.
3995 if (mResumedActivity != null
3996 && mResumedActivity.info.applicationInfo.uid ==
3997 Binder.getCallingUid()) {
3998 mAppSwitchesAllowedTime = 0;
3999 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004000 }
4001
4002 return pir.sendInner(0, fillInIntent, resolvedType,
4003 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
4004 }
4005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004006 public boolean startNextMatchingActivity(IBinder callingActivity,
4007 Intent intent) {
4008 // Refuse possible leaked file descriptors
4009 if (intent != null && intent.hasFileDescriptors() == true) {
4010 throw new IllegalArgumentException("File descriptors passed in Intent");
4011 }
4012
4013 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004014 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 if (index < 0) {
4016 return false;
4017 }
4018 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4019 if (r.app == null || r.app.thread == null) {
4020 // The caller is not running... d'oh!
4021 return false;
4022 }
4023 intent = new Intent(intent);
4024 // The caller is not allowed to change the data.
4025 intent.setDataAndType(r.intent.getData(), r.intent.getType());
4026 // And we are resetting to find the next component...
4027 intent.setComponent(null);
4028
4029 ActivityInfo aInfo = null;
4030 try {
4031 List<ResolveInfo> resolves =
4032 ActivityThread.getPackageManager().queryIntentActivities(
4033 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004034 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035
4036 // Look for the original activity in the list...
4037 final int N = resolves != null ? resolves.size() : 0;
4038 for (int i=0; i<N; i++) {
4039 ResolveInfo rInfo = resolves.get(i);
4040 if (rInfo.activityInfo.packageName.equals(r.packageName)
4041 && rInfo.activityInfo.name.equals(r.info.name)) {
4042 // We found the current one... the next matching is
4043 // after it.
4044 i++;
4045 if (i<N) {
4046 aInfo = resolves.get(i).activityInfo;
4047 }
4048 break;
4049 }
4050 }
4051 } catch (RemoteException e) {
4052 }
4053
4054 if (aInfo == null) {
4055 // Nobody who is next!
4056 return false;
4057 }
4058
4059 intent.setComponent(new ComponentName(
4060 aInfo.applicationInfo.packageName, aInfo.name));
4061 intent.setFlags(intent.getFlags()&~(
4062 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
4063 Intent.FLAG_ACTIVITY_CLEAR_TOP|
4064 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
4065 Intent.FLAG_ACTIVITY_NEW_TASK));
4066
4067 // Okay now we need to start the new activity, replacing the
4068 // currently running activity. This is a little tricky because
4069 // we want to start the new one as if the current one is finished,
4070 // but not finish the current one first so that there is no flicker.
4071 // And thus...
4072 final boolean wasFinishing = r.finishing;
4073 r.finishing = true;
4074
4075 // Propagate reply information over to the new activity.
4076 final HistoryRecord resultTo = r.resultTo;
4077 final String resultWho = r.resultWho;
4078 final int requestCode = r.requestCode;
4079 r.resultTo = null;
4080 if (resultTo != null) {
4081 resultTo.removeResultsLocked(r, resultWho, requestCode);
4082 }
4083
4084 final long origId = Binder.clearCallingIdentity();
4085 // XXX we are not dealing with propagating grantedUriPermissions...
4086 // those are not yet exposed to user code, so there is no need.
4087 int res = startActivityLocked(r.app.thread, intent,
4088 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004089 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004090 Binder.restoreCallingIdentity(origId);
4091
4092 r.finishing = wasFinishing;
4093 if (res != START_SUCCESS) {
4094 return false;
4095 }
4096 return true;
4097 }
4098 }
4099
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004100 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 Intent intent, String resolvedType, IBinder resultTo,
4102 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004103
4104 // This is so super not safe, that only the system (or okay root)
4105 // can do it.
4106 final int callingUid = Binder.getCallingUid();
4107 if (callingUid != 0 && callingUid != Process.myUid()) {
4108 throw new SecurityException(
4109 "startActivityInPackage only available to the system");
4110 }
4111
The Android Open Source Project4df24232009-03-05 14:34:35 -08004112 final boolean componentSpecified = intent.getComponent() != null;
4113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004114 // Don't modify the client's object!
4115 intent = new Intent(intent);
4116
4117 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004118 ActivityInfo aInfo;
4119 try {
4120 ResolveInfo rInfo =
4121 ActivityThread.getPackageManager().resolveIntent(
4122 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004123 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004124 aInfo = rInfo != null ? rInfo.activityInfo : null;
4125 } catch (RemoteException e) {
4126 aInfo = null;
4127 }
4128
4129 if (aInfo != null) {
4130 // Store the found target back into the intent, because now that
4131 // we have it we never want to do this again. For example, if the
4132 // user navigates back to this point in the history, we should
4133 // always restart the exact same activity.
4134 intent.setComponent(new ComponentName(
4135 aInfo.applicationInfo.packageName, aInfo.name));
4136 }
4137
4138 synchronized(this) {
4139 return startActivityLocked(null, intent, resolvedType,
4140 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004141 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004142 }
4143 }
4144
Josh Bartel7f208742010-02-25 11:01:44 -06004145 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004146 // Remove any existing entries that are the same kind of task.
4147 int N = mRecentTasks.size();
4148 for (int i=0; i<N; i++) {
4149 TaskRecord tr = mRecentTasks.get(i);
4150 if ((task.affinity != null && task.affinity.equals(tr.affinity))
4151 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
4152 mRecentTasks.remove(i);
4153 i--;
4154 N--;
4155 if (task.intent == null) {
4156 // If the new recent task we are adding is not fully
4157 // specified, then replace it with the existing recent task.
4158 task = tr;
4159 }
4160 }
4161 }
4162 if (N >= MAX_RECENT_TASKS) {
4163 mRecentTasks.remove(N-1);
4164 }
4165 mRecentTasks.add(0, task);
4166 }
4167
4168 public void setRequestedOrientation(IBinder token,
4169 int requestedOrientation) {
4170 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004171 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 if (index < 0) {
4173 return;
4174 }
4175 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4176 final long origId = Binder.clearCallingIdentity();
4177 mWindowManager.setAppOrientation(r, requestedOrientation);
4178 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07004179 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004180 r.mayFreezeScreenLocked(r.app) ? r : null);
4181 if (config != null) {
4182 r.frozenBeforeDestroy = true;
4183 if (!updateConfigurationLocked(config, r)) {
4184 resumeTopActivityLocked(null);
4185 }
4186 }
4187 Binder.restoreCallingIdentity(origId);
4188 }
4189 }
4190
4191 public int getRequestedOrientation(IBinder token) {
4192 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004193 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 if (index < 0) {
4195 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4196 }
4197 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4198 return mWindowManager.getAppOrientation(r);
4199 }
4200 }
4201
4202 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004203 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004204 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4205 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4206 if (!r.finishing) {
4207 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4208 "no-history");
4209 }
4210 } else if (r.app != null && r.app.thread != null) {
4211 if (mFocusedActivity == r) {
4212 setFocusedActivityLocked(topRunningActivityLocked(null));
4213 }
4214 r.resumeKeyDispatchingLocked();
4215 try {
4216 r.stopped = false;
4217 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004218 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004219 TAG, "Stopping visible=" + r.visible + " for " + r);
4220 if (!r.visible) {
4221 mWindowManager.setAppVisibility(r, false);
4222 }
4223 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4224 } catch (Exception e) {
4225 // Maybe just ignore exceptions here... if the process
4226 // has crashed, our death notification will clean things
4227 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004228 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 // Just in case, assume it to be stopped.
4230 r.stopped = true;
4231 r.state = ActivityState.STOPPED;
4232 if (r.configDestroy) {
4233 destroyActivityLocked(r, true);
4234 }
4235 }
4236 }
4237 }
4238
4239 /**
4240 * @return Returns true if the activity is being finished, false if for
4241 * some reason it is being left as-is.
4242 */
4243 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4244 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004245 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004246 TAG, "Finishing activity: token=" + token
4247 + ", result=" + resultCode + ", data=" + resultData);
4248
Dianne Hackborn75b03852009-06-12 15:43:26 -07004249 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 if (index < 0) {
4251 return false;
4252 }
4253 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4254
4255 // Is this the last activity left?
4256 boolean lastActivity = true;
4257 for (int i=mHistory.size()-1; i>=0; i--) {
4258 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4259 if (!p.finishing && p != r) {
4260 lastActivity = false;
4261 break;
4262 }
4263 }
4264
4265 // If this is the last activity, but it is the home activity, then
4266 // just don't finish it.
4267 if (lastActivity) {
4268 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4269 return false;
4270 }
4271 }
4272
4273 finishActivityLocked(r, index, resultCode, resultData, reason);
4274 return true;
4275 }
4276
4277 /**
4278 * @return Returns true if this activity has been removed from the history
4279 * list, or false if it is still in the list and will be removed later.
4280 */
4281 private final boolean finishActivityLocked(HistoryRecord r, int index,
4282 int resultCode, Intent resultData, String reason) {
4283 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004284 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 return false;
4286 }
4287
4288 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004289 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 System.identityHashCode(r),
4291 r.task.taskId, r.shortComponentName, reason);
4292 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004293 if (index < (mHistory.size()-1)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004294 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4295 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004296 if (r.frontOfTask) {
4297 // The next activity is now the front of the task.
4298 next.frontOfTask = true;
4299 }
4300 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4301 // If the caller asked that this activity (and all above it)
4302 // be cleared when the task is reset, don't lose that information,
4303 // but propagate it up to the next activity.
4304 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004306 }
4307 }
4308
4309 r.pauseKeyDispatchingLocked();
4310 if (mFocusedActivity == r) {
4311 setFocusedActivityLocked(topRunningActivityLocked(null));
4312 }
4313
4314 // send the result
4315 HistoryRecord resultTo = r.resultTo;
4316 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004317 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004318 + " who=" + r.resultWho + " req=" + r.requestCode
4319 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 if (r.info.applicationInfo.uid > 0) {
4321 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4322 r.packageName, resultData, r);
4323 }
4324 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4325 resultData);
4326 r.resultTo = null;
4327 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004328 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004329
4330 // Make sure this HistoryRecord is not holding on to other resources,
4331 // because clients have remote IPC references to this object so we
4332 // can't assume that will go away and want to avoid circular IPC refs.
4333 r.results = null;
4334 r.pendingResults = null;
4335 r.newIntents = null;
4336 r.icicle = null;
4337
4338 if (mPendingThumbnails.size() > 0) {
4339 // There are clients waiting to receive thumbnails so, in case
4340 // this is an activity that someone is waiting for, add it
4341 // to the pending list so we can correctly update the clients.
4342 mCancelledThumbnails.add(r);
4343 }
4344
4345 if (mResumedActivity == r) {
4346 boolean endTask = index <= 0
4347 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004348 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 "Prepare close transition: finishing " + r);
4350 mWindowManager.prepareAppTransition(endTask
4351 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4352 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4353
4354 // Tell window manager to prepare for this one to be removed.
4355 mWindowManager.setAppVisibility(r, false);
4356
4357 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004358 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4359 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 startPausingLocked(false, false);
4361 }
4362
4363 } else if (r.state != ActivityState.PAUSING) {
4364 // If the activity is PAUSING, we will complete the finish once
4365 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004366 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 return finishCurrentActivityLocked(r, index,
4368 FINISH_AFTER_PAUSE) == null;
4369 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004370 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004371 }
4372
4373 return false;
4374 }
4375
4376 private static final int FINISH_IMMEDIATELY = 0;
4377 private static final int FINISH_AFTER_PAUSE = 1;
4378 private static final int FINISH_AFTER_VISIBLE = 2;
4379
4380 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4381 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004382 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 if (index < 0) {
4384 return null;
4385 }
4386
4387 return finishCurrentActivityLocked(r, index, mode);
4388 }
4389
4390 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4391 int index, int mode) {
4392 // First things first: if this activity is currently visible,
4393 // and the resumed activity is not yet visible, then hold off on
4394 // finishing until the resumed one becomes visible.
4395 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4396 if (!mStoppingActivities.contains(r)) {
4397 mStoppingActivities.add(r);
4398 if (mStoppingActivities.size() > 3) {
4399 // If we already have a few activities waiting to stop,
4400 // then give up on things going idle and start clearing
4401 // them out.
4402 Message msg = Message.obtain();
4403 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4404 mHandler.sendMessage(msg);
4405 }
4406 }
4407 r.state = ActivityState.STOPPING;
4408 updateOomAdjLocked();
4409 return r;
4410 }
4411
4412 // make sure the record is cleaned out of other places.
4413 mStoppingActivities.remove(r);
4414 mWaitingVisibleActivities.remove(r);
4415 if (mResumedActivity == r) {
4416 mResumedActivity = null;
4417 }
4418 final ActivityState prevState = r.state;
4419 r.state = ActivityState.FINISHING;
4420
4421 if (mode == FINISH_IMMEDIATELY
4422 || prevState == ActivityState.STOPPED
4423 || prevState == ActivityState.INITIALIZING) {
4424 // If this activity is already stopped, we can just finish
4425 // it right now.
4426 return destroyActivityLocked(r, true) ? null : r;
4427 } else {
4428 // Need to go through the full pause cycle to get this
4429 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004430 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 mFinishingActivities.add(r);
4432 resumeTopActivityLocked(null);
4433 }
4434 return r;
4435 }
4436
4437 /**
4438 * This is the internal entry point for handling Activity.finish().
4439 *
4440 * @param token The Binder token referencing the Activity we want to finish.
4441 * @param resultCode Result code, if any, from this Activity.
4442 * @param resultData Result data (Intent), if any, from this Activity.
4443 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004444 * @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 -08004445 */
4446 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4447 // Refuse possible leaked file descriptors
4448 if (resultData != null && resultData.hasFileDescriptors() == true) {
4449 throw new IllegalArgumentException("File descriptors passed in Intent");
4450 }
4451
4452 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004453 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004454 // Find the first activity that is not finishing.
4455 HistoryRecord next = topRunningActivityLocked(token, 0);
4456 if (next != null) {
4457 // ask watcher if this is allowed
4458 boolean resumeOK = true;
4459 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004460 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004462 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 }
4464
4465 if (!resumeOK) {
4466 return false;
4467 }
4468 }
4469 }
4470 final long origId = Binder.clearCallingIdentity();
4471 boolean res = requestFinishActivityLocked(token, resultCode,
4472 resultData, "app-request");
4473 Binder.restoreCallingIdentity(origId);
4474 return res;
4475 }
4476 }
4477
Dianne Hackborn860755f2010-06-03 18:47:52 -07004478 public final void finishHeavyWeightApp() {
4479 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4480 != PackageManager.PERMISSION_GRANTED) {
4481 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
4482 + Binder.getCallingPid()
4483 + ", uid=" + Binder.getCallingUid()
4484 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4485 Slog.w(TAG, msg);
4486 throw new SecurityException(msg);
4487 }
4488
4489 synchronized(this) {
4490 if (mHeavyWeightProcess == null) {
4491 return;
4492 }
4493
4494 ArrayList<HistoryRecord> activities = new ArrayList<HistoryRecord>(
4495 mHeavyWeightProcess.activities);
4496 for (int i=0; i<activities.size(); i++) {
4497 HistoryRecord r = activities.get(i);
4498 if (!r.finishing) {
4499 int index = indexOfTokenLocked(r);
4500 if (index >= 0) {
4501 finishActivityLocked(r, index, Activity.RESULT_CANCELED,
4502 null, "finish-heavy");
4503 }
4504 }
4505 }
4506
4507 mHeavyWeightProcess = null;
4508 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4509 }
4510 }
4511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4513 String resultWho, int requestCode, int resultCode, Intent data) {
4514
4515 if (callingUid > 0) {
4516 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4517 data, r);
4518 }
4519
Joe Onorato8a9b2202010-02-26 18:56:32 -08004520 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004521 + " : who=" + resultWho + " req=" + requestCode
4522 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004523 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4524 try {
4525 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4526 list.add(new ResultInfo(resultWho, requestCode,
4527 resultCode, data));
4528 r.app.thread.scheduleSendResult(r, list);
4529 return;
4530 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004531 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004532 }
4533 }
4534
4535 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4536 }
4537
4538 public final void finishSubActivity(IBinder token, String resultWho,
4539 int requestCode) {
4540 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004541 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004542 if (index < 0) {
4543 return;
4544 }
4545 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4546
4547 final long origId = Binder.clearCallingIdentity();
4548
4549 int i;
4550 for (i=mHistory.size()-1; i>=0; i--) {
4551 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4552 if (r.resultTo == self && r.requestCode == requestCode) {
4553 if ((r.resultWho == null && resultWho == null) ||
4554 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4555 finishActivityLocked(r, i,
4556 Activity.RESULT_CANCELED, null, "request-sub");
4557 }
4558 }
4559 }
4560
4561 Binder.restoreCallingIdentity(origId);
4562 }
4563 }
4564
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004565 public boolean willActivityBeVisible(IBinder token) {
4566 synchronized(this) {
4567 int i;
4568 for (i=mHistory.size()-1; i>=0; i--) {
4569 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4570 if (r == token) {
4571 return true;
4572 }
4573 if (r.fullscreen && !r.finishing) {
4574 return false;
4575 }
4576 }
4577 return true;
4578 }
4579 }
4580
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004581 public void overridePendingTransition(IBinder token, String packageName,
4582 int enterAnim, int exitAnim) {
4583 synchronized(this) {
4584 int index = indexOfTokenLocked(token);
4585 if (index < 0) {
4586 return;
4587 }
4588 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4589
4590 final long origId = Binder.clearCallingIdentity();
4591
4592 if (self.state == ActivityState.RESUMED
4593 || self.state == ActivityState.PAUSING) {
4594 mWindowManager.overridePendingAppTransition(packageName,
4595 enterAnim, exitAnim);
4596 }
4597
4598 Binder.restoreCallingIdentity(origId);
4599 }
4600 }
4601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 /**
4603 * Perform clean-up of service connections in an activity record.
4604 */
4605 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4606 // Throw away any services that have been bound by this activity.
4607 if (r.connections != null) {
4608 Iterator<ConnectionRecord> it = r.connections.iterator();
4609 while (it.hasNext()) {
4610 ConnectionRecord c = it.next();
4611 removeConnectionLocked(c, null, r);
4612 }
4613 r.connections = null;
4614 }
4615 }
4616
4617 /**
4618 * Perform the common clean-up of an activity record. This is called both
4619 * as part of destroyActivityLocked() (when destroying the client-side
4620 * representation) and cleaning things up as a result of its hosting
4621 * processing going away, in which case there is no remaining client-side
4622 * state to destroy so only the cleanup here is needed.
4623 */
4624 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4625 if (mResumedActivity == r) {
4626 mResumedActivity = null;
4627 }
4628 if (mFocusedActivity == r) {
4629 mFocusedActivity = null;
4630 }
4631
4632 r.configDestroy = false;
4633 r.frozenBeforeDestroy = false;
4634
4635 // Make sure this record is no longer in the pending finishes list.
4636 // This could happen, for example, if we are trimming activities
4637 // down to the max limit while they are still waiting to finish.
4638 mFinishingActivities.remove(r);
4639 mWaitingVisibleActivities.remove(r);
4640
4641 // Remove any pending results.
4642 if (r.finishing && r.pendingResults != null) {
4643 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4644 PendingIntentRecord rec = apr.get();
4645 if (rec != null) {
4646 cancelIntentSenderLocked(rec, false);
4647 }
4648 }
4649 r.pendingResults = null;
4650 }
4651
4652 if (cleanServices) {
4653 cleanUpActivityServicesLocked(r);
4654 }
4655
4656 if (mPendingThumbnails.size() > 0) {
4657 // There are clients waiting to receive thumbnails so, in case
4658 // this is an activity that someone is waiting for, add it
4659 // to the pending list so we can correctly update the clients.
4660 mCancelledThumbnails.add(r);
4661 }
4662
4663 // Get rid of any pending idle timeouts.
4664 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4665 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4666 }
4667
4668 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4669 if (r.state != ActivityState.DESTROYED) {
4670 mHistory.remove(r);
4671 r.inHistory = false;
4672 r.state = ActivityState.DESTROYED;
4673 mWindowManager.removeAppToken(r);
4674 if (VALIDATE_TOKENS) {
4675 mWindowManager.validateAppTokens(mHistory);
4676 }
4677 cleanUpActivityServicesLocked(r);
4678 removeActivityUriPermissionsLocked(r);
4679 }
4680 }
4681
4682 /**
4683 * Destroy the current CLIENT SIDE instance of an activity. This may be
4684 * called both when actually finishing an activity, or when performing
4685 * a configuration switch where we destroy the current client-side object
4686 * but then create a new client-side object for this same HistoryRecord.
4687 */
4688 private final boolean destroyActivityLocked(HistoryRecord r,
4689 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004690 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 TAG, "Removing activity: token=" + r
4692 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004693 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 System.identityHashCode(r),
4695 r.task.taskId, r.shortComponentName);
4696
4697 boolean removedFromHistory = false;
4698
4699 cleanUpActivityLocked(r, false);
4700
Dianne Hackborn03abb812010-01-04 18:43:19 -08004701 final boolean hadApp = r.app != null;
4702
4703 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004704 if (removeFromApp) {
4705 int idx = r.app.activities.indexOf(r);
4706 if (idx >= 0) {
4707 r.app.activities.remove(idx);
4708 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004709 if (mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4710 mHeavyWeightProcess = null;
4711 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004713 if (r.persistent) {
4714 decPersistentCountLocked(r.app);
4715 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004716 if (r.app.activities.size() == 0) {
4717 // No longer have activities, so update location in
4718 // LRU list.
4719 updateLruProcessLocked(r.app, true, false);
4720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 }
4722
4723 boolean skipDestroy = false;
4724
4725 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004726 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4728 r.configChangeFlags);
4729 } catch (Exception e) {
4730 // We can just ignore exceptions here... if the process
4731 // has crashed, our death notification will clean things
4732 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004733 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 if (r.finishing) {
4735 removeActivityFromHistoryLocked(r);
4736 removedFromHistory = true;
4737 skipDestroy = true;
4738 }
4739 }
4740
4741 r.app = null;
4742 r.nowVisible = false;
4743
4744 if (r.finishing && !skipDestroy) {
4745 r.state = ActivityState.DESTROYING;
4746 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4747 msg.obj = r;
4748 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4749 } else {
4750 r.state = ActivityState.DESTROYED;
4751 }
4752 } else {
4753 // remove this record from the history.
4754 if (r.finishing) {
4755 removeActivityFromHistoryLocked(r);
4756 removedFromHistory = true;
4757 } else {
4758 r.state = ActivityState.DESTROYED;
4759 }
4760 }
4761
4762 r.configChangeFlags = 0;
4763
Dianne Hackborn03abb812010-01-04 18:43:19 -08004764 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004765 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004766 }
4767
4768 return removedFromHistory;
4769 }
4770
Dianne Hackborn03abb812010-01-04 18:43:19 -08004771 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004772 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004773 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004774 TAG, "Removing app " + app + " from list " + list
4775 + " with " + i + " entries");
4776 while (i > 0) {
4777 i--;
4778 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004779 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4781 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004782 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004783 list.remove(i);
4784 }
4785 }
4786 }
4787
4788 /**
4789 * Main function for removing an existing process from the activity manager
4790 * as a result of that process going away. Clears out all connections
4791 * to the process.
4792 */
4793 private final void handleAppDiedLocked(ProcessRecord app,
4794 boolean restarting) {
4795 cleanUpApplicationRecordLocked(app, restarting, -1);
4796 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004797 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004798 }
4799
4800 // Just in case...
4801 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004802 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004803 mPausingActivity = null;
4804 }
4805 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4806 mLastPausedActivity = null;
4807 }
4808
4809 // Remove this application's activities from active lists.
4810 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4811 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4812 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4813 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4814
4815 boolean atTop = true;
4816 boolean hasVisibleActivities = false;
4817
4818 // Clean out the history list.
4819 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004820 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004821 TAG, "Removing app " + app + " from history with " + i + " entries");
4822 while (i > 0) {
4823 i--;
4824 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004825 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4827 if (r.app == app) {
4828 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004829 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 TAG, "Removing this entry! frozen=" + r.haveState
4831 + " finishing=" + r.finishing);
4832 mHistory.remove(i);
4833
4834 r.inHistory = false;
4835 mWindowManager.removeAppToken(r);
4836 if (VALIDATE_TOKENS) {
4837 mWindowManager.validateAppTokens(mHistory);
4838 }
4839 removeActivityUriPermissionsLocked(r);
4840
4841 } else {
4842 // We have the current state for this activity, so
4843 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004844 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 TAG, "Keeping entry, setting app to null");
4846 if (r.visible) {
4847 hasVisibleActivities = true;
4848 }
4849 r.app = null;
4850 r.nowVisible = false;
4851 if (!r.haveState) {
4852 r.icicle = null;
4853 }
4854 }
4855
4856 cleanUpActivityLocked(r, true);
4857 r.state = ActivityState.STOPPED;
4858 }
4859 atTop = false;
4860 }
4861
4862 app.activities.clear();
4863
4864 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004865 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 + " running instrumentation " + app.instrumentationClass);
4867 Bundle info = new Bundle();
4868 info.putString("shortMsg", "Process crashed.");
4869 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4870 }
4871
4872 if (!restarting) {
4873 if (!resumeTopActivityLocked(null)) {
4874 // If there was nothing to resume, and we are not already
4875 // restarting this process, but there is a visible activity that
4876 // is hosted by the process... then make sure all visible
4877 // activities are running, taking care of restarting this
4878 // process.
4879 if (hasVisibleActivities) {
4880 ensureActivitiesVisibleLocked(null, 0);
4881 }
4882 }
4883 }
4884 }
4885
4886 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4887 IBinder threadBinder = thread.asBinder();
4888
4889 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004890 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4891 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4893 return i;
4894 }
4895 }
4896 return -1;
4897 }
4898
4899 private final ProcessRecord getRecordForAppLocked(
4900 IApplicationThread thread) {
4901 if (thread == null) {
4902 return null;
4903 }
4904
4905 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004906 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004907 }
4908
4909 private final void appDiedLocked(ProcessRecord app, int pid,
4910 IApplicationThread thread) {
4911
4912 mProcDeaths[0]++;
4913
Magnus Edlund7bb25812010-02-24 15:45:06 +01004914 // Clean up already done if the process has been re-started.
4915 if (app.pid == pid && app.thread != null &&
4916 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07004917 if (!app.killedBackground) {
4918 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
4919 + ") has died.");
4920 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08004921 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004922 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004923 TAG, "Dying app: " + app + ", pid: " + pid
4924 + ", thread: " + thread.asBinder());
4925 boolean doLowMem = app.instrumentationClass == null;
4926 handleAppDiedLocked(app, false);
4927
4928 if (doLowMem) {
4929 // If there are no longer any background processes running,
4930 // and the app that died was not running instrumentation,
4931 // then tell everyone we are now low on memory.
4932 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004933 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4934 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004935 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4936 haveBg = true;
4937 break;
4938 }
4939 }
4940
4941 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004942 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004943 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004944 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004945 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4946 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004947 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004948 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4949 // The low memory report is overriding any current
4950 // state for a GC request. Make sure to do
4951 // visible/foreground processes first.
4952 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4953 rec.lastRequestedGc = 0;
4954 } else {
4955 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004956 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004957 rec.reportLowMemory = true;
4958 rec.lastLowMemory = now;
4959 mProcessesToGc.remove(rec);
4960 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 }
4962 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004963 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 }
4965 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004966 } else if (app.pid != pid) {
4967 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004968 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004969 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004970 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004971 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004972 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004973 + thread.asBinder());
4974 }
4975 }
4976
Dan Egnor42471dd2010-01-07 17:25:22 -08004977 /**
4978 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07004979 * @param clearTraces causes the dump file to be erased prior to the new
4980 * traces being written, if true; when false, the new traces will be
4981 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08004982 * @param pids of dalvik VM processes to dump stack traces for
4983 * @return file containing stack traces, or null if no dump file is configured
4984 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07004985 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08004986 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
4987 if (tracesPath == null || tracesPath.length() == 0) {
4988 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 }
Dan Egnor42471dd2010-01-07 17:25:22 -08004990
4991 File tracesFile = new File(tracesPath);
4992 try {
4993 File tracesDir = tracesFile.getParentFile();
4994 if (!tracesDir.exists()) tracesFile.mkdirs();
4995 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
4996
Christopher Tate6ee412d2010-05-28 12:01:56 -07004997 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08004998 tracesFile.createNewFile();
4999 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
5000 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005001 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005002 return null;
5003 }
5004
5005 // Use a FileObserver to detect when traces finish writing.
5006 // The order of traces is considered important to maintain for legibility.
5007 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
5008 public synchronized void onEvent(int event, String path) { notify(); }
5009 };
5010
5011 try {
5012 observer.startWatching();
5013 int num = pids.size();
5014 for (int i = 0; i < num; i++) {
5015 synchronized (observer) {
5016 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
5017 observer.wait(200); // Wait for write-close, give up after 200msec
5018 }
5019 }
5020 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08005021 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005022 } finally {
5023 observer.stopWatching();
5024 }
5025
5026 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005027 }
5028
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005029 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08005030 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005031 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005032
5033 synchronized (this) {
5034 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
5035 if (mShuttingDown) {
5036 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
5037 return;
5038 } else if (app.notResponding) {
5039 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
5040 return;
5041 } else if (app.crashing) {
5042 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
5043 return;
5044 }
5045
5046 // In case we come through here for the same app before completing
5047 // this one, mark as anring now so we will bail out.
5048 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08005049
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005050 // Log the ANR to the event log.
5051 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
5052 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08005053
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005054 // Dump thread traces as quickly as we can, starting with "interesting" processes.
5055 pids.add(app.pid);
5056
5057 int parentPid = app.pid;
5058 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
5059 if (parentPid != app.pid) pids.add(parentPid);
5060
5061 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08005062
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005063 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
5064 ProcessRecord r = mLruProcesses.get(i);
5065 if (r != null && r.thread != null) {
5066 int pid = r.pid;
5067 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
5068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 }
5070 }
5071
Christopher Tate6ee412d2010-05-28 12:01:56 -07005072 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08005073
5074 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005075 StringBuilder info = mStringBuilder;
5076 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08005077 info.append("ANR in ").append(app.processName);
5078 if (activity != null && activity.shortComponentName != null) {
5079 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07005080 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08005081 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005083 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005084 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005085 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005086 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005088
Dan Egnor42471dd2010-01-07 17:25:22 -08005089 String cpuInfo = null;
5090 if (MONITOR_CPU_USAGE) {
5091 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005092 synchronized (mProcessStatsThread) {
5093 cpuInfo = mProcessStats.printCurrentState();
5094 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005095 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005096 }
5097
Joe Onorato8a9b2202010-02-26 18:56:32 -08005098 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08005099 if (tracesFile == null) {
5100 // There is no trace file, so dump (only) the alleged culprit's threads to the log
5101 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
5102 }
5103
5104 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
5105
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005106 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005107 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08005108 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
5109 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005111 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
5112 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 }
5114 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005115 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116 }
5117 }
5118
Dan Egnor42471dd2010-01-07 17:25:22 -08005119 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
5120 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
5121 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005122
5123 synchronized (this) {
5124 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
5125 Process.killProcess(app.pid);
5126 return;
5127 }
5128
5129 // Set the app's notResponding state, and look up the errorReportReceiver
5130 makeAppNotRespondingLocked(app,
5131 activity != null ? activity.shortComponentName : null,
5132 annotation != null ? "ANR " + annotation : "ANR",
5133 info.toString());
5134
5135 // Bring up the infamous App Not Responding dialog
5136 Message msg = Message.obtain();
5137 HashMap map = new HashMap();
5138 msg.what = SHOW_NOT_RESPONDING_MSG;
5139 msg.obj = map;
5140 map.put("app", app);
5141 if (activity != null) {
5142 map.put("activity", activity);
5143 }
5144
5145 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08005146 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 }
5148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 private final void decPersistentCountLocked(ProcessRecord app)
5150 {
5151 app.persistentActivities--;
5152 if (app.persistentActivities > 0) {
5153 // Still more of 'em...
5154 return;
5155 }
5156 if (app.persistent) {
5157 // Ah, but the application itself is persistent. Whatever!
5158 return;
5159 }
5160
5161 // App is no longer persistent... make sure it and the ones
5162 // following it in the LRU list have the correc oom_adj.
5163 updateOomAdjLocked();
5164 }
5165
5166 public void setPersistent(IBinder token, boolean isPersistent) {
5167 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
5168 != PackageManager.PERMISSION_GRANTED) {
5169 String msg = "Permission Denial: setPersistent() from pid="
5170 + Binder.getCallingPid()
5171 + ", uid=" + Binder.getCallingUid()
5172 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005173 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005174 throw new SecurityException(msg);
5175 }
5176
5177 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005178 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005179 if (index < 0) {
5180 return;
5181 }
5182 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5183 ProcessRecord app = r.app;
5184
Joe Onorato8a9b2202010-02-26 18:56:32 -08005185 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 TAG, "Setting persistence " + isPersistent + ": " + r);
5187
5188 if (isPersistent) {
5189 if (r.persistent) {
5190 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005191 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192 return;
5193 }
5194 r.persistent = true;
5195 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005196 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 if (app.persistentActivities > 1) {
5198 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005199 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 return;
5201 }
5202 if (app.persistent) {
5203 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005204 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005205 return;
5206 }
5207
5208 // App is now persistent... make sure it and the ones
5209 // following it now have the correct oom_adj.
5210 final long origId = Binder.clearCallingIdentity();
5211 updateOomAdjLocked();
5212 Binder.restoreCallingIdentity(origId);
5213
5214 } else {
5215 if (!r.persistent) {
5216 // Okay okay, I heard you already!
5217 return;
5218 }
5219 r.persistent = false;
5220 final long origId = Binder.clearCallingIdentity();
5221 decPersistentCountLocked(app);
5222 Binder.restoreCallingIdentity(origId);
5223
5224 }
5225 }
5226 }
5227
5228 public boolean clearApplicationUserData(final String packageName,
5229 final IPackageDataObserver observer) {
5230 int uid = Binder.getCallingUid();
5231 int pid = Binder.getCallingPid();
5232 long callingId = Binder.clearCallingIdentity();
5233 try {
5234 IPackageManager pm = ActivityThread.getPackageManager();
5235 int pkgUid = -1;
5236 synchronized(this) {
5237 try {
5238 pkgUid = pm.getPackageUid(packageName);
5239 } catch (RemoteException e) {
5240 }
5241 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005242 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 return false;
5244 }
5245 if (uid == pkgUid || checkComponentPermission(
5246 android.Manifest.permission.CLEAR_APP_USER_DATA,
5247 pid, uid, -1)
5248 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005249 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005250 } else {
5251 throw new SecurityException(pid+" does not have permission:"+
5252 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5253 "for process:"+packageName);
5254 }
5255 }
5256
5257 try {
5258 //clear application user data
5259 pm.clearApplicationUserData(packageName, observer);
5260 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5261 Uri.fromParts("package", packageName, null));
5262 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005263 synchronized (this) {
5264 broadcastIntentLocked(null, null, intent,
5265 null, null, 0, null, null, null,
5266 false, false, MY_PID, Process.SYSTEM_UID);
5267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005268 } catch (RemoteException e) {
5269 }
5270 } finally {
5271 Binder.restoreCallingIdentity(callingId);
5272 }
5273 return true;
5274 }
5275
Dianne Hackborn03abb812010-01-04 18:43:19 -08005276 public void killBackgroundProcesses(final String packageName) {
5277 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5278 != PackageManager.PERMISSION_GRANTED &&
5279 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5280 != PackageManager.PERMISSION_GRANTED) {
5281 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282 + Binder.getCallingPid()
5283 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005284 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005285 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 throw new SecurityException(msg);
5287 }
5288
5289 long callingId = Binder.clearCallingIdentity();
5290 try {
5291 IPackageManager pm = ActivityThread.getPackageManager();
5292 int pkgUid = -1;
5293 synchronized(this) {
5294 try {
5295 pkgUid = pm.getPackageUid(packageName);
5296 } catch (RemoteException e) {
5297 }
5298 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005299 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005300 return;
5301 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005302 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005303 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005304 }
5305 } finally {
5306 Binder.restoreCallingIdentity(callingId);
5307 }
5308 }
5309
5310 public void forceStopPackage(final String packageName) {
5311 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5312 != PackageManager.PERMISSION_GRANTED) {
5313 String msg = "Permission Denial: forceStopPackage() from pid="
5314 + Binder.getCallingPid()
5315 + ", uid=" + Binder.getCallingUid()
5316 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005317 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005318 throw new SecurityException(msg);
5319 }
5320
5321 long callingId = Binder.clearCallingIdentity();
5322 try {
5323 IPackageManager pm = ActivityThread.getPackageManager();
5324 int pkgUid = -1;
5325 synchronized(this) {
5326 try {
5327 pkgUid = pm.getPackageUid(packageName);
5328 } catch (RemoteException e) {
5329 }
5330 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005331 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005332 return;
5333 }
5334 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 }
5336 } finally {
5337 Binder.restoreCallingIdentity(callingId);
5338 }
5339 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005340
5341 /*
5342 * The pkg name and uid have to be specified.
5343 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5344 */
5345 public void killApplicationWithUid(String pkg, int uid) {
5346 if (pkg == null) {
5347 return;
5348 }
5349 // Make sure the uid is valid.
5350 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005351 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005352 return;
5353 }
5354 int callerUid = Binder.getCallingUid();
5355 // Only the system server can kill an application
5356 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005357 // Post an aysnc message to kill the application
5358 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5359 msg.arg1 = uid;
5360 msg.arg2 = 0;
5361 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005362 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005363 } else {
5364 throw new SecurityException(callerUid + " cannot kill pkg: " +
5365 pkg);
5366 }
5367 }
5368
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005369 public void closeSystemDialogs(String reason) {
5370 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5371 if (reason != null) {
5372 intent.putExtra("reason", reason);
5373 }
5374
5375 final int uid = Binder.getCallingUid();
5376 final long origId = Binder.clearCallingIdentity();
5377 synchronized (this) {
5378 int i = mWatchers.beginBroadcast();
5379 while (i > 0) {
5380 i--;
5381 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5382 if (w != null) {
5383 try {
5384 w.closingSystemDialogs(reason);
5385 } catch (RemoteException e) {
5386 }
5387 }
5388 }
5389 mWatchers.finishBroadcast();
5390
Dianne Hackbornffa42482009-09-23 22:20:11 -07005391 mWindowManager.closeSystemDialogs(reason);
5392
5393 for (i=mHistory.size()-1; i>=0; i--) {
5394 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5395 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5396 finishActivityLocked(r, i,
5397 Activity.RESULT_CANCELED, null, "close-sys");
5398 }
5399 }
5400
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005401 broadcastIntentLocked(null, null, intent, null,
5402 null, 0, null, null, null, false, false, -1, uid);
5403 }
5404 Binder.restoreCallingIdentity(origId);
5405 }
5406
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005407 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005408 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005409 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5410 for (int i=pids.length-1; i>=0; i--) {
5411 infos[i] = new Debug.MemoryInfo();
5412 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005413 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005414 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005415 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005416
5417 public void killApplicationProcess(String processName, int uid) {
5418 if (processName == null) {
5419 return;
5420 }
5421
5422 int callerUid = Binder.getCallingUid();
5423 // Only the system server can kill an application
5424 if (callerUid == Process.SYSTEM_UID) {
5425 synchronized (this) {
5426 ProcessRecord app = getProcessRecordLocked(processName, uid);
5427 if (app != null) {
5428 try {
5429 app.thread.scheduleSuicide();
5430 } catch (RemoteException e) {
5431 // If the other end already died, then our work here is done.
5432 }
5433 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005434 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005435 + processName + " / " + uid);
5436 }
5437 }
5438 } else {
5439 throw new SecurityException(callerUid + " cannot kill app process: " +
5440 processName);
5441 }
5442 }
5443
Dianne Hackborn03abb812010-01-04 18:43:19 -08005444 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005445 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5447 Uri.fromParts("package", packageName, null));
5448 intent.putExtra(Intent.EXTRA_UID, uid);
5449 broadcastIntentLocked(null, null, intent,
5450 null, null, 0, null, null, null,
5451 false, false, MY_PID, Process.SYSTEM_UID);
5452 }
5453
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005454 private final boolean killPackageProcessesLocked(String packageName, int uid,
5455 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005456 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005457
Dianne Hackborn03abb812010-01-04 18:43:19 -08005458 // Remove all processes this package may have touched: all with the
5459 // same UID (except for the system or root user), and all whose name
5460 // matches the package name.
5461 final String procNamePrefix = packageName + ":";
5462 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5463 final int NA = apps.size();
5464 for (int ia=0; ia<NA; ia++) {
5465 ProcessRecord app = apps.valueAt(ia);
5466 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005467 if (doit) {
5468 procs.add(app);
5469 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005470 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5471 || app.processName.equals(packageName)
5472 || app.processName.startsWith(procNamePrefix)) {
5473 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005474 if (!doit) {
5475 return true;
5476 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005477 app.removed = true;
5478 procs.add(app);
5479 }
5480 }
5481 }
5482 }
5483
5484 int N = procs.size();
5485 for (int i=0; i<N; i++) {
5486 removeProcessLocked(procs.get(i), callerWillRestart);
5487 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005488 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005489 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005490
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005491 private final boolean forceStopPackageLocked(String name, int uid,
5492 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 int i, N;
5494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005495 if (uid < 0) {
5496 try {
5497 uid = ActivityThread.getPackageManager().getPackageUid(name);
5498 } catch (RemoteException e) {
5499 }
5500 }
5501
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005502 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005503 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005504
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005505 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5506 while (badApps.hasNext()) {
5507 SparseArray<Long> ba = badApps.next();
5508 if (ba.get(uid) != null) {
5509 badApps.remove();
5510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 }
5512 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005513
5514 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5515 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005516
5517 for (i=mHistory.size()-1; i>=0; i--) {
5518 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5519 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005520 if (!doit) {
5521 return true;
5522 }
5523 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005524 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005525 if (r.app != null) {
5526 r.app.removed = true;
5527 }
5528 r.app = null;
5529 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5530 }
5531 }
5532
5533 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5534 for (ServiceRecord service : mServices.values()) {
5535 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005536 if (!doit) {
5537 return true;
5538 }
5539 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005540 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005541 if (service.app != null) {
5542 service.app.removed = true;
5543 }
5544 service.app = null;
5545 services.add(service);
5546 }
5547 }
5548
5549 N = services.size();
5550 for (i=0; i<N; i++) {
5551 bringDownServiceLocked(services.get(i), true);
5552 }
5553
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005554 if (doit) {
5555 if (purgeCache) {
5556 AttributeCache ac = AttributeCache.instance();
5557 if (ac != null) {
5558 ac.removePackage(name);
5559 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005560 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005561 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005562 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005563
5564 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 }
5566
5567 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5568 final String name = app.processName;
5569 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005570 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005571 TAG, "Force removing process " + app + " (" + name
5572 + "/" + uid + ")");
5573
5574 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005575 if (mHeavyWeightProcess == app) {
5576 mHeavyWeightProcess = null;
5577 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 boolean needRestart = false;
5580 if (app.pid > 0 && app.pid != MY_PID) {
5581 int pid = app.pid;
5582 synchronized (mPidsSelfLocked) {
5583 mPidsSelfLocked.remove(pid);
5584 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5585 }
5586 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005587 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005588 Process.killProcess(pid);
5589
5590 if (app.persistent) {
5591 if (!callerWillRestart) {
5592 addAppLocked(app.info);
5593 } else {
5594 needRestart = true;
5595 }
5596 }
5597 } else {
5598 mRemovedProcesses.add(app);
5599 }
5600
5601 return needRestart;
5602 }
5603
5604 private final void processStartTimedOutLocked(ProcessRecord app) {
5605 final int pid = app.pid;
5606 boolean gone = false;
5607 synchronized (mPidsSelfLocked) {
5608 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5609 if (knownApp != null && knownApp.thread == null) {
5610 mPidsSelfLocked.remove(pid);
5611 gone = true;
5612 }
5613 }
5614
5615 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005616 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005617 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005618 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005619 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005620 if (mHeavyWeightProcess == app) {
5621 mHeavyWeightProcess = null;
5622 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5623 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005624 // Take care of any launching providers waiting for this process.
5625 checkAppInLaunchingProvidersLocked(app, true);
5626 // Take care of any services that are waiting for the process.
5627 for (int i=0; i<mPendingServices.size(); i++) {
5628 ServiceRecord sr = mPendingServices.get(i);
5629 if (app.info.uid == sr.appInfo.uid
5630 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005631 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005632 mPendingServices.remove(i);
5633 i--;
5634 bringDownServiceLocked(sr, true);
5635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005637 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005638 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005639 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005640 try {
5641 IBackupManager bm = IBackupManager.Stub.asInterface(
5642 ServiceManager.getService(Context.BACKUP_SERVICE));
5643 bm.agentDisconnected(app.info.packageName);
5644 } catch (RemoteException e) {
5645 // Can't happen; the backup manager is local
5646 }
5647 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005648 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005649 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005650 mPendingBroadcast = null;
5651 scheduleBroadcastsLocked();
5652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005653 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005654 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 }
5656 }
5657
5658 private final boolean attachApplicationLocked(IApplicationThread thread,
5659 int pid) {
5660
5661 // Find the application record that is being attached... either via
5662 // the pid if we are running in multiple processes, or just pull the
5663 // next app record if we are emulating process with anonymous threads.
5664 ProcessRecord app;
5665 if (pid != MY_PID && pid >= 0) {
5666 synchronized (mPidsSelfLocked) {
5667 app = mPidsSelfLocked.get(pid);
5668 }
5669 } else if (mStartingProcesses.size() > 0) {
5670 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005671 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 } else {
5673 app = null;
5674 }
5675
5676 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005677 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005679 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005680 if (pid > 0 && pid != MY_PID) {
5681 Process.killProcess(pid);
5682 } else {
5683 try {
5684 thread.scheduleExit();
5685 } catch (Exception e) {
5686 // Ignore exceptions.
5687 }
5688 }
5689 return false;
5690 }
5691
5692 // If this application record is still attached to a previous
5693 // process, clean it up now.
5694 if (app.thread != null) {
5695 handleAppDiedLocked(app, true);
5696 }
5697
5698 // Tell the process all about itself.
5699
Joe Onorato8a9b2202010-02-26 18:56:32 -08005700 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 TAG, "Binding process pid " + pid + " to record " + app);
5702
5703 String processName = app.processName;
5704 try {
5705 thread.asBinder().linkToDeath(new AppDeathRecipient(
5706 app, pid, thread), 0);
5707 } catch (RemoteException e) {
5708 app.resetPackageList();
5709 startProcessLocked(app, "link fail", processName);
5710 return false;
5711 }
5712
Doug Zongker2bec3d42009-12-04 12:52:44 -08005713 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714
5715 app.thread = thread;
5716 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005717 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5718 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005719 app.forcingToForeground = null;
5720 app.foregroundServices = false;
5721 app.debugging = false;
5722
5723 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5724
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005725 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5726 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005727
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005728 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005729 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005730 }
5731
Joe Onorato8a9b2202010-02-26 18:56:32 -08005732 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005733 TAG, "New app record " + app
5734 + " thread=" + thread.asBinder() + " pid=" + pid);
5735 try {
5736 int testMode = IApplicationThread.DEBUG_OFF;
5737 if (mDebugApp != null && mDebugApp.equals(processName)) {
5738 testMode = mWaitForDebugger
5739 ? IApplicationThread.DEBUG_WAIT
5740 : IApplicationThread.DEBUG_ON;
5741 app.debugging = true;
5742 if (mDebugTransient) {
5743 mDebugApp = mOrigDebugApp;
5744 mWaitForDebugger = mOrigWaitForDebugger;
5745 }
5746 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005747
Christopher Tate181fafa2009-05-14 11:12:14 -07005748 // If the app is being launched for restore or full backup, set it up specially
5749 boolean isRestrictedBackupMode = false;
5750 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5751 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5752 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5753 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005754
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005755 ensurePackageDexOpt(app.instrumentationInfo != null
5756 ? app.instrumentationInfo.packageName
5757 : app.info.packageName);
5758 if (app.instrumentationClass != null) {
5759 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005760 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005761 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005762 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005763 thread.bindApplication(processName, app.instrumentationInfo != null
5764 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 app.instrumentationClass, app.instrumentationProfileFile,
5766 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005767 isRestrictedBackupMode || !normalMode,
5768 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005769 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005770 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005771 } catch (Exception e) {
5772 // todo: Yikes! What should we do? For now we will try to
5773 // start another process, but that could easily get us in
5774 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005775 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005776
5777 app.resetPackageList();
5778 startProcessLocked(app, "bind fail", processName);
5779 return false;
5780 }
5781
5782 // Remove this record from the list of starting applications.
5783 mPersistentStartingProcesses.remove(app);
5784 mProcessesOnHold.remove(app);
5785
5786 boolean badApp = false;
5787 boolean didSomething = false;
5788
5789 // See if the top visible activity is waiting to run in this process...
5790 HistoryRecord hr = topRunningActivityLocked(null);
5791 if (hr != null) {
5792 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5793 && processName.equals(hr.processName)) {
5794 try {
5795 if (realStartActivityLocked(hr, app, true, true)) {
5796 didSomething = true;
5797 }
5798 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005799 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005800 + hr.intent.getComponent().flattenToShortString(), e);
5801 badApp = true;
5802 }
5803 } else {
5804 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5805 }
5806 }
5807
5808 // Find any services that should be running in this process...
5809 if (!badApp && mPendingServices.size() > 0) {
5810 ServiceRecord sr = null;
5811 try {
5812 for (int i=0; i<mPendingServices.size(); i++) {
5813 sr = mPendingServices.get(i);
5814 if (app.info.uid != sr.appInfo.uid
5815 || !processName.equals(sr.processName)) {
5816 continue;
5817 }
5818
5819 mPendingServices.remove(i);
5820 i--;
5821 realStartServiceLocked(sr, app);
5822 didSomething = true;
5823 }
5824 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005825 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005826 + sr.shortName, e);
5827 badApp = true;
5828 }
5829 }
5830
5831 // Check if the next broadcast receiver is in this process...
5832 BroadcastRecord br = mPendingBroadcast;
5833 if (!badApp && br != null && br.curApp == app) {
5834 try {
5835 mPendingBroadcast = null;
5836 processCurBroadcastLocked(br, app);
5837 didSomething = true;
5838 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005839 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 + br.curComponent.flattenToShortString(), e);
5841 badApp = true;
5842 logBroadcastReceiverDiscard(br);
5843 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5844 br.resultExtras, br.resultAbort, true);
5845 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005846 // We need to reset the state if we fails to start the receiver.
5847 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005848 }
5849 }
5850
Christopher Tate181fafa2009-05-14 11:12:14 -07005851 // Check whether the next backup agent is in this process...
5852 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005853 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005854 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005855 try {
5856 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5857 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005858 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005859 e.printStackTrace();
5860 }
5861 }
5862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 if (badApp) {
5864 // todo: Also need to kill application to deal with all
5865 // kinds of exceptions.
5866 handleAppDiedLocked(app, false);
5867 return false;
5868 }
5869
5870 if (!didSomething) {
5871 updateOomAdjLocked();
5872 }
5873
5874 return true;
5875 }
5876
5877 public final void attachApplication(IApplicationThread thread) {
5878 synchronized (this) {
5879 int callingPid = Binder.getCallingPid();
5880 final long origId = Binder.clearCallingIdentity();
5881 attachApplicationLocked(thread, callingPid);
5882 Binder.restoreCallingIdentity(origId);
5883 }
5884 }
5885
Dianne Hackborne88846e2009-09-30 21:34:25 -07005886 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005887 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005888 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005889 Binder.restoreCallingIdentity(origId);
5890 }
5891
5892 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5893 boolean remove) {
5894 int N = mStoppingActivities.size();
5895 if (N <= 0) return null;
5896
5897 ArrayList<HistoryRecord> stops = null;
5898
5899 final boolean nowVisible = mResumedActivity != null
5900 && mResumedActivity.nowVisible
5901 && !mResumedActivity.waitingVisible;
5902 for (int i=0; i<N; i++) {
5903 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005904 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005905 + nowVisible + " waitingVisible=" + s.waitingVisible
5906 + " finishing=" + s.finishing);
5907 if (s.waitingVisible && nowVisible) {
5908 mWaitingVisibleActivities.remove(s);
5909 s.waitingVisible = false;
5910 if (s.finishing) {
5911 // If this activity is finishing, it is sitting on top of
5912 // everyone else but we now know it is no longer needed...
5913 // so get rid of it. Otherwise, we need to go through the
5914 // normal flow and hide it once we determine that it is
5915 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005916 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005917 mWindowManager.setAppVisibility(s, false);
5918 }
5919 }
5920 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005921 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005922 if (stops == null) {
5923 stops = new ArrayList<HistoryRecord>();
5924 }
5925 stops.add(s);
5926 mStoppingActivities.remove(i);
5927 N--;
5928 i--;
5929 }
5930 }
5931
5932 return stops;
5933 }
5934
5935 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005936 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005937 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 mWindowManager.enableScreenAfterBoot();
5939 }
5940
Dianne Hackborne88846e2009-09-30 21:34:25 -07005941 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5942 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005943 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005944
5945 ArrayList<HistoryRecord> stops = null;
5946 ArrayList<HistoryRecord> finishes = null;
5947 ArrayList<HistoryRecord> thumbnails = null;
5948 int NS = 0;
5949 int NF = 0;
5950 int NT = 0;
5951 IApplicationThread sendThumbnail = null;
5952 boolean booting = false;
5953 boolean enableScreen = false;
5954
5955 synchronized (this) {
5956 if (token != null) {
5957 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5958 }
5959
5960 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005961 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 if (index >= 0) {
5963 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5964
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005965 if (fromTimeout) {
5966 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5967 }
5968
Dianne Hackborne88846e2009-09-30 21:34:25 -07005969 // This is a hack to semi-deal with a race condition
5970 // in the client where it can be constructed with a
5971 // newer configuration from when we asked it to launch.
5972 // We'll update with whatever configuration it now says
5973 // it used to launch.
5974 if (config != null) {
5975 r.configuration = config;
5976 }
5977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978 // No longer need to keep the device awake.
5979 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
5980 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
5981 mLaunchingActivity.release();
5982 }
5983
5984 // We are now idle. If someone is waiting for a thumbnail from
5985 // us, we can now deliver.
5986 r.idle = true;
5987 scheduleAppGcsLocked();
5988 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
5989 sendThumbnail = r.app.thread;
5990 r.thumbnailNeeded = false;
5991 }
5992
5993 // If this activity is fullscreen, set up to hide those under it.
5994
Joe Onorato8a9b2202010-02-26 18:56:32 -08005995 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 ensureActivitiesVisibleLocked(null, 0);
5997
Joe Onorato8a9b2202010-02-26 18:56:32 -08005998 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005999 if (!mBooted && !fromTimeout) {
6000 mBooted = true;
6001 enableScreen = true;
6002 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006003
6004 } else if (fromTimeout) {
6005 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006006 }
6007
6008 // Atomically retrieve all of the other things to do.
6009 stops = processStoppingActivitiesLocked(true);
6010 NS = stops != null ? stops.size() : 0;
6011 if ((NF=mFinishingActivities.size()) > 0) {
6012 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
6013 mFinishingActivities.clear();
6014 }
6015 if ((NT=mCancelledThumbnails.size()) > 0) {
6016 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
6017 mCancelledThumbnails.clear();
6018 }
6019
6020 booting = mBooting;
6021 mBooting = false;
6022 }
6023
6024 int i;
6025
6026 // Send thumbnail if requested.
6027 if (sendThumbnail != null) {
6028 try {
6029 sendThumbnail.requestThumbnail(token);
6030 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006031 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 sendPendingThumbnail(null, token, null, null, true);
6033 }
6034 }
6035
6036 // Stop any activities that are scheduled to do so but have been
6037 // waiting for the next one to start.
6038 for (i=0; i<NS; i++) {
6039 HistoryRecord r = (HistoryRecord)stops.get(i);
6040 synchronized (this) {
6041 if (r.finishing) {
6042 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
6043 } else {
6044 stopActivityLocked(r);
6045 }
6046 }
6047 }
6048
6049 // Finish any activities that are scheduled to do so but have been
6050 // waiting for the next one to start.
6051 for (i=0; i<NF; i++) {
6052 HistoryRecord r = (HistoryRecord)finishes.get(i);
6053 synchronized (this) {
6054 destroyActivityLocked(r, true);
6055 }
6056 }
6057
6058 // Report back to any thumbnail receivers.
6059 for (i=0; i<NT; i++) {
6060 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
6061 sendPendingThumbnail(r, null, null, null, true);
6062 }
6063
6064 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006065 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006066 }
6067
6068 trimApplications();
6069 //dump();
6070 //mWindowManager.dump();
6071
6072 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006073 enableScreenAfterBoot();
6074 }
6075 }
6076
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006077 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006078 IntentFilter pkgFilter = new IntentFilter();
6079 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
6080 pkgFilter.addDataScheme("package");
6081 mContext.registerReceiver(new BroadcastReceiver() {
6082 @Override
6083 public void onReceive(Context context, Intent intent) {
6084 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
6085 if (pkgs != null) {
6086 for (String pkg : pkgs) {
6087 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
6088 setResultCode(Activity.RESULT_OK);
6089 return;
6090 }
6091 }
6092 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006093 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006094 }, pkgFilter);
6095
6096 synchronized (this) {
6097 // Ensure that any processes we had put on hold are now started
6098 // up.
6099 final int NP = mProcessesOnHold.size();
6100 if (NP > 0) {
6101 ArrayList<ProcessRecord> procs =
6102 new ArrayList<ProcessRecord>(mProcessesOnHold);
6103 for (int ip=0; ip<NP; ip++) {
6104 this.startProcessLocked(procs.get(ip), "on-hold", null);
6105 }
6106 }
6107
6108 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6109 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006110 broadcastIntentLocked(null, null,
6111 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
6112 null, null, 0, null, null,
6113 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
6114 false, false, MY_PID, Process.SYSTEM_UID);
6115 }
6116 }
6117 }
6118
6119 final void ensureBootCompleted() {
6120 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006121 boolean enableScreen;
6122 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006123 booting = mBooting;
6124 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006125 enableScreen = !mBooted;
6126 mBooted = true;
6127 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006128
6129 if (booting) {
6130 finishBooting();
6131 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006132
6133 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006134 enableScreenAfterBoot();
6135 }
6136 }
6137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006138 public final void activityPaused(IBinder token, Bundle icicle) {
6139 // Refuse possible leaked file descriptors
6140 if (icicle != null && icicle.hasFileDescriptors()) {
6141 throw new IllegalArgumentException("File descriptors passed in Bundle");
6142 }
6143
6144 final long origId = Binder.clearCallingIdentity();
6145 activityPaused(token, icicle, false);
6146 Binder.restoreCallingIdentity(origId);
6147 }
6148
6149 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006150 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006151 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
6152 + ", timeout=" + timeout);
6153
6154 HistoryRecord r = null;
6155
6156 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006157 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006158 if (index >= 0) {
6159 r = (HistoryRecord)mHistory.get(index);
6160 if (!timeout) {
6161 r.icicle = icicle;
6162 r.haveState = true;
6163 }
6164 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
6165 if (mPausingActivity == r) {
6166 r.state = ActivityState.PAUSED;
6167 completePauseLocked();
6168 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08006169 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006170 System.identityHashCode(r), r.shortComponentName,
6171 mPausingActivity != null
6172 ? mPausingActivity.shortComponentName : "(none)");
6173 }
6174 }
6175 }
6176 }
6177
6178 public final void activityStopped(IBinder token, Bitmap thumbnail,
6179 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006180 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006181 TAG, "Activity stopped: token=" + token);
6182
6183 HistoryRecord r = null;
6184
6185 final long origId = Binder.clearCallingIdentity();
6186
6187 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006188 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006189 if (index >= 0) {
6190 r = (HistoryRecord)mHistory.get(index);
6191 r.thumbnail = thumbnail;
6192 r.description = description;
6193 r.stopped = true;
6194 r.state = ActivityState.STOPPED;
6195 if (!r.finishing) {
6196 if (r.configDestroy) {
6197 destroyActivityLocked(r, true);
6198 resumeTopActivityLocked(null);
6199 }
6200 }
6201 }
6202 }
6203
6204 if (r != null) {
6205 sendPendingThumbnail(r, null, null, null, false);
6206 }
6207
6208 trimApplications();
6209
6210 Binder.restoreCallingIdentity(origId);
6211 }
6212
6213 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006214 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 synchronized (this) {
6216 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
6217
Dianne Hackborn75b03852009-06-12 15:43:26 -07006218 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 if (index >= 0) {
6220 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6221 if (r.state == ActivityState.DESTROYING) {
6222 final long origId = Binder.clearCallingIdentity();
6223 removeActivityFromHistoryLocked(r);
6224 Binder.restoreCallingIdentity(origId);
6225 }
6226 }
6227 }
6228 }
6229
6230 public String getCallingPackage(IBinder token) {
6231 synchronized (this) {
6232 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07006233 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006234 }
6235 }
6236
6237 public ComponentName getCallingActivity(IBinder token) {
6238 synchronized (this) {
6239 HistoryRecord r = getCallingRecordLocked(token);
6240 return r != null ? r.intent.getComponent() : null;
6241 }
6242 }
6243
6244 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006245 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006246 if (index >= 0) {
6247 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6248 if (r != null) {
6249 return r.resultTo;
6250 }
6251 }
6252 return null;
6253 }
6254
6255 public ComponentName getActivityClassForToken(IBinder token) {
6256 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006257 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006258 if (index >= 0) {
6259 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6260 return r.intent.getComponent();
6261 }
6262 return null;
6263 }
6264 }
6265
6266 public String getPackageForToken(IBinder token) {
6267 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006268 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006269 if (index >= 0) {
6270 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6271 return r.packageName;
6272 }
6273 return null;
6274 }
6275 }
6276
6277 public IIntentSender getIntentSender(int type,
6278 String packageName, IBinder token, String resultWho,
6279 int requestCode, Intent intent, String resolvedType, int flags) {
6280 // Refuse possible leaked file descriptors
6281 if (intent != null && intent.hasFileDescriptors() == true) {
6282 throw new IllegalArgumentException("File descriptors passed in Intent");
6283 }
6284
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006285 if (type == INTENT_SENDER_BROADCAST) {
6286 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6287 throw new IllegalArgumentException(
6288 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6289 }
6290 }
6291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006292 synchronized(this) {
6293 int callingUid = Binder.getCallingUid();
6294 try {
6295 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6296 Process.supportsProcesses()) {
6297 int uid = ActivityThread.getPackageManager()
6298 .getPackageUid(packageName);
6299 if (uid != Binder.getCallingUid()) {
6300 String msg = "Permission Denial: getIntentSender() from pid="
6301 + Binder.getCallingPid()
6302 + ", uid=" + Binder.getCallingUid()
6303 + ", (need uid=" + uid + ")"
6304 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006305 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006306 throw new SecurityException(msg);
6307 }
6308 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006309
6310 return getIntentSenderLocked(type, packageName, callingUid,
6311 token, resultWho, requestCode, intent, resolvedType, flags);
6312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006313 } catch (RemoteException e) {
6314 throw new SecurityException(e);
6315 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006316 }
6317 }
6318
6319 IIntentSender getIntentSenderLocked(int type,
6320 String packageName, int callingUid, IBinder token, String resultWho,
6321 int requestCode, Intent intent, String resolvedType, int flags) {
6322 HistoryRecord activity = null;
6323 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6324 int index = indexOfTokenLocked(token);
6325 if (index < 0) {
6326 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006328 activity = (HistoryRecord)mHistory.get(index);
6329 if (activity.finishing) {
6330 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006332 }
6333
6334 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6335 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6336 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6337 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6338 |PendingIntent.FLAG_UPDATE_CURRENT);
6339
6340 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6341 type, packageName, activity, resultWho,
6342 requestCode, intent, resolvedType, flags);
6343 WeakReference<PendingIntentRecord> ref;
6344 ref = mIntentSenderRecords.get(key);
6345 PendingIntentRecord rec = ref != null ? ref.get() : null;
6346 if (rec != null) {
6347 if (!cancelCurrent) {
6348 if (updateCurrent) {
6349 rec.key.requestIntent.replaceExtras(intent);
6350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 return rec;
6352 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006353 rec.canceled = true;
6354 mIntentSenderRecords.remove(key);
6355 }
6356 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006357 return rec;
6358 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006359 rec = new PendingIntentRecord(this, key, callingUid);
6360 mIntentSenderRecords.put(key, rec.ref);
6361 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6362 if (activity.pendingResults == null) {
6363 activity.pendingResults
6364 = new HashSet<WeakReference<PendingIntentRecord>>();
6365 }
6366 activity.pendingResults.add(rec.ref);
6367 }
6368 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006369 }
6370
6371 public void cancelIntentSender(IIntentSender sender) {
6372 if (!(sender instanceof PendingIntentRecord)) {
6373 return;
6374 }
6375 synchronized(this) {
6376 PendingIntentRecord rec = (PendingIntentRecord)sender;
6377 try {
6378 int uid = ActivityThread.getPackageManager()
6379 .getPackageUid(rec.key.packageName);
6380 if (uid != Binder.getCallingUid()) {
6381 String msg = "Permission Denial: cancelIntentSender() from pid="
6382 + Binder.getCallingPid()
6383 + ", uid=" + Binder.getCallingUid()
6384 + " is not allowed to cancel packges "
6385 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006386 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006387 throw new SecurityException(msg);
6388 }
6389 } catch (RemoteException e) {
6390 throw new SecurityException(e);
6391 }
6392 cancelIntentSenderLocked(rec, true);
6393 }
6394 }
6395
6396 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6397 rec.canceled = true;
6398 mIntentSenderRecords.remove(rec.key);
6399 if (cleanActivity && rec.key.activity != null) {
6400 rec.key.activity.pendingResults.remove(rec.ref);
6401 }
6402 }
6403
6404 public String getPackageForIntentSender(IIntentSender pendingResult) {
6405 if (!(pendingResult instanceof PendingIntentRecord)) {
6406 return null;
6407 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006408 try {
6409 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6410 return res.key.packageName;
6411 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006412 }
6413 return null;
6414 }
6415
6416 public void setProcessLimit(int max) {
6417 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6418 "setProcessLimit()");
6419 mProcessLimit = max;
6420 }
6421
6422 public int getProcessLimit() {
6423 return mProcessLimit;
6424 }
6425
6426 void foregroundTokenDied(ForegroundToken token) {
6427 synchronized (ActivityManagerService.this) {
6428 synchronized (mPidsSelfLocked) {
6429 ForegroundToken cur
6430 = mForegroundProcesses.get(token.pid);
6431 if (cur != token) {
6432 return;
6433 }
6434 mForegroundProcesses.remove(token.pid);
6435 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6436 if (pr == null) {
6437 return;
6438 }
6439 pr.forcingToForeground = null;
6440 pr.foregroundServices = false;
6441 }
6442 updateOomAdjLocked();
6443 }
6444 }
6445
6446 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6447 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6448 "setProcessForeground()");
6449 synchronized(this) {
6450 boolean changed = false;
6451
6452 synchronized (mPidsSelfLocked) {
6453 ProcessRecord pr = mPidsSelfLocked.get(pid);
6454 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006455 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006456 return;
6457 }
6458 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6459 if (oldToken != null) {
6460 oldToken.token.unlinkToDeath(oldToken, 0);
6461 mForegroundProcesses.remove(pid);
6462 pr.forcingToForeground = null;
6463 changed = true;
6464 }
6465 if (isForeground && token != null) {
6466 ForegroundToken newToken = new ForegroundToken() {
6467 public void binderDied() {
6468 foregroundTokenDied(this);
6469 }
6470 };
6471 newToken.pid = pid;
6472 newToken.token = token;
6473 try {
6474 token.linkToDeath(newToken, 0);
6475 mForegroundProcesses.put(pid, newToken);
6476 pr.forcingToForeground = token;
6477 changed = true;
6478 } catch (RemoteException e) {
6479 // If the process died while doing this, we will later
6480 // do the cleanup with the process death link.
6481 }
6482 }
6483 }
6484
6485 if (changed) {
6486 updateOomAdjLocked();
6487 }
6488 }
6489 }
6490
6491 // =========================================================
6492 // PERMISSIONS
6493 // =========================================================
6494
6495 static class PermissionController extends IPermissionController.Stub {
6496 ActivityManagerService mActivityManagerService;
6497 PermissionController(ActivityManagerService activityManagerService) {
6498 mActivityManagerService = activityManagerService;
6499 }
6500
6501 public boolean checkPermission(String permission, int pid, int uid) {
6502 return mActivityManagerService.checkPermission(permission, pid,
6503 uid) == PackageManager.PERMISSION_GRANTED;
6504 }
6505 }
6506
6507 /**
6508 * This can be called with or without the global lock held.
6509 */
6510 int checkComponentPermission(String permission, int pid, int uid,
6511 int reqUid) {
6512 // We might be performing an operation on behalf of an indirect binder
6513 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6514 // client identity accordingly before proceeding.
6515 Identity tlsIdentity = sCallerIdentity.get();
6516 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006517 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006518 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6519 uid = tlsIdentity.uid;
6520 pid = tlsIdentity.pid;
6521 }
6522
6523 // Root, system server and our own process get to do everything.
6524 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6525 !Process.supportsProcesses()) {
6526 return PackageManager.PERMISSION_GRANTED;
6527 }
6528 // If the target requires a specific UID, always fail for others.
6529 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006530 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006531 return PackageManager.PERMISSION_DENIED;
6532 }
6533 if (permission == null) {
6534 return PackageManager.PERMISSION_GRANTED;
6535 }
6536 try {
6537 return ActivityThread.getPackageManager()
6538 .checkUidPermission(permission, uid);
6539 } catch (RemoteException e) {
6540 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006541 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006542 }
6543 return PackageManager.PERMISSION_DENIED;
6544 }
6545
6546 /**
6547 * As the only public entry point for permissions checking, this method
6548 * can enforce the semantic that requesting a check on a null global
6549 * permission is automatically denied. (Internally a null permission
6550 * string is used when calling {@link #checkComponentPermission} in cases
6551 * when only uid-based security is needed.)
6552 *
6553 * This can be called with or without the global lock held.
6554 */
6555 public int checkPermission(String permission, int pid, int uid) {
6556 if (permission == null) {
6557 return PackageManager.PERMISSION_DENIED;
6558 }
6559 return checkComponentPermission(permission, pid, uid, -1);
6560 }
6561
6562 /**
6563 * Binder IPC calls go through the public entry point.
6564 * This can be called with or without the global lock held.
6565 */
6566 int checkCallingPermission(String permission) {
6567 return checkPermission(permission,
6568 Binder.getCallingPid(),
6569 Binder.getCallingUid());
6570 }
6571
6572 /**
6573 * This can be called with or without the global lock held.
6574 */
6575 void enforceCallingPermission(String permission, String func) {
6576 if (checkCallingPermission(permission)
6577 == PackageManager.PERMISSION_GRANTED) {
6578 return;
6579 }
6580
6581 String msg = "Permission Denial: " + func + " from pid="
6582 + Binder.getCallingPid()
6583 + ", uid=" + Binder.getCallingUid()
6584 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006585 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006586 throw new SecurityException(msg);
6587 }
6588
6589 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6590 ProviderInfo pi, int uid, int modeFlags) {
6591 try {
6592 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6593 if ((pi.readPermission != null) &&
6594 (pm.checkUidPermission(pi.readPermission, uid)
6595 != PackageManager.PERMISSION_GRANTED)) {
6596 return false;
6597 }
6598 }
6599 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6600 if ((pi.writePermission != null) &&
6601 (pm.checkUidPermission(pi.writePermission, uid)
6602 != PackageManager.PERMISSION_GRANTED)) {
6603 return false;
6604 }
6605 }
6606 return true;
6607 } catch (RemoteException e) {
6608 return false;
6609 }
6610 }
6611
6612 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6613 int modeFlags) {
6614 // Root gets to do everything.
6615 if (uid == 0 || !Process.supportsProcesses()) {
6616 return true;
6617 }
6618 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6619 if (perms == null) return false;
6620 UriPermission perm = perms.get(uri);
6621 if (perm == null) return false;
6622 return (modeFlags&perm.modeFlags) == modeFlags;
6623 }
6624
6625 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6626 // Another redirected-binder-call permissions check as in
6627 // {@link checkComponentPermission}.
6628 Identity tlsIdentity = sCallerIdentity.get();
6629 if (tlsIdentity != null) {
6630 uid = tlsIdentity.uid;
6631 pid = tlsIdentity.pid;
6632 }
6633
6634 // Our own process gets to do everything.
6635 if (pid == MY_PID) {
6636 return PackageManager.PERMISSION_GRANTED;
6637 }
6638 synchronized(this) {
6639 return checkUriPermissionLocked(uri, uid, modeFlags)
6640 ? PackageManager.PERMISSION_GRANTED
6641 : PackageManager.PERMISSION_DENIED;
6642 }
6643 }
6644
6645 private void grantUriPermissionLocked(int callingUid,
6646 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6647 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6648 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6649 if (modeFlags == 0) {
6650 return;
6651 }
6652
Joe Onorato8a9b2202010-02-26 18:56:32 -08006653 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006654 "Requested grant " + targetPkg + " permission to " + uri);
6655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006656 final IPackageManager pm = ActivityThread.getPackageManager();
6657
6658 // If this is not a content: uri, we can't do anything with it.
6659 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006660 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006661 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 return;
6663 }
6664
6665 String name = uri.getAuthority();
6666 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006667 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006668 if (cpr != null) {
6669 pi = cpr.info;
6670 } else {
6671 try {
6672 pi = pm.resolveContentProvider(name,
6673 PackageManager.GET_URI_PERMISSION_PATTERNS);
6674 } catch (RemoteException ex) {
6675 }
6676 }
6677 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006678 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006679 return;
6680 }
6681
6682 int targetUid;
6683 try {
6684 targetUid = pm.getPackageUid(targetPkg);
6685 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006686 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006687 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006688 return;
6689 }
6690 } catch (RemoteException ex) {
6691 return;
6692 }
6693
6694 // First... does the target actually need this permission?
6695 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6696 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006697 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006698 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 return;
6700 }
6701
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006702 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006703 if (!pi.grantUriPermissions) {
6704 throw new SecurityException("Provider " + pi.packageName
6705 + "/" + pi.name
6706 + " does not allow granting of Uri permissions (uri "
6707 + uri + ")");
6708 }
6709 if (pi.uriPermissionPatterns != null) {
6710 final int N = pi.uriPermissionPatterns.length;
6711 boolean allowed = false;
6712 for (int i=0; i<N; i++) {
6713 if (pi.uriPermissionPatterns[i] != null
6714 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6715 allowed = true;
6716 break;
6717 }
6718 }
6719 if (!allowed) {
6720 throw new SecurityException("Provider " + pi.packageName
6721 + "/" + pi.name
6722 + " does not allow granting of permission to path of Uri "
6723 + uri);
6724 }
6725 }
6726
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006727 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006728 // this uri?
6729 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6730 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6731 throw new SecurityException("Uid " + callingUid
6732 + " does not have permission to uri " + uri);
6733 }
6734 }
6735
6736 // Okay! So here we are: the caller has the assumed permission
6737 // to the uri, and the target doesn't. Let's now give this to
6738 // the target.
6739
Joe Onorato8a9b2202010-02-26 18:56:32 -08006740 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006741 "Granting " + targetPkg + " permission to " + uri);
6742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006743 HashMap<Uri, UriPermission> targetUris
6744 = mGrantedUriPermissions.get(targetUid);
6745 if (targetUris == null) {
6746 targetUris = new HashMap<Uri, UriPermission>();
6747 mGrantedUriPermissions.put(targetUid, targetUris);
6748 }
6749
6750 UriPermission perm = targetUris.get(uri);
6751 if (perm == null) {
6752 perm = new UriPermission(targetUid, uri);
6753 targetUris.put(uri, perm);
6754
6755 }
6756 perm.modeFlags |= modeFlags;
6757 if (activity == null) {
6758 perm.globalModeFlags |= modeFlags;
6759 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6760 perm.readActivities.add(activity);
6761 if (activity.readUriPermissions == null) {
6762 activity.readUriPermissions = new HashSet<UriPermission>();
6763 }
6764 activity.readUriPermissions.add(perm);
6765 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6766 perm.writeActivities.add(activity);
6767 if (activity.writeUriPermissions == null) {
6768 activity.writeUriPermissions = new HashSet<UriPermission>();
6769 }
6770 activity.writeUriPermissions.add(perm);
6771 }
6772 }
6773
6774 private void grantUriPermissionFromIntentLocked(int callingUid,
6775 String targetPkg, Intent intent, HistoryRecord activity) {
6776 if (intent == null) {
6777 return;
6778 }
6779 Uri data = intent.getData();
6780 if (data == null) {
6781 return;
6782 }
6783 grantUriPermissionLocked(callingUid, targetPkg, data,
6784 intent.getFlags(), activity);
6785 }
6786
6787 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6788 Uri uri, int modeFlags) {
6789 synchronized(this) {
6790 final ProcessRecord r = getRecordForAppLocked(caller);
6791 if (r == null) {
6792 throw new SecurityException("Unable to find app for caller "
6793 + caller
6794 + " when granting permission to uri " + uri);
6795 }
6796 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006797 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006798 return;
6799 }
6800 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006801 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006802 return;
6803 }
6804
6805 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6806 null);
6807 }
6808 }
6809
6810 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6811 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6812 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6813 HashMap<Uri, UriPermission> perms
6814 = mGrantedUriPermissions.get(perm.uid);
6815 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006816 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006817 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006818 perms.remove(perm.uri);
6819 if (perms.size() == 0) {
6820 mGrantedUriPermissions.remove(perm.uid);
6821 }
6822 }
6823 }
6824 }
6825
6826 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6827 if (activity.readUriPermissions != null) {
6828 for (UriPermission perm : activity.readUriPermissions) {
6829 perm.readActivities.remove(activity);
6830 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6831 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6832 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6833 removeUriPermissionIfNeededLocked(perm);
6834 }
6835 }
6836 }
6837 if (activity.writeUriPermissions != null) {
6838 for (UriPermission perm : activity.writeUriPermissions) {
6839 perm.writeActivities.remove(activity);
6840 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6841 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6842 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6843 removeUriPermissionIfNeededLocked(perm);
6844 }
6845 }
6846 }
6847 }
6848
6849 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6850 int modeFlags) {
6851 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6852 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6853 if (modeFlags == 0) {
6854 return;
6855 }
6856
Joe Onorato8a9b2202010-02-26 18:56:32 -08006857 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006858 "Revoking all granted permissions to " + uri);
6859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006860 final IPackageManager pm = ActivityThread.getPackageManager();
6861
6862 final String authority = uri.getAuthority();
6863 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006864 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006865 if (cpr != null) {
6866 pi = cpr.info;
6867 } else {
6868 try {
6869 pi = pm.resolveContentProvider(authority,
6870 PackageManager.GET_URI_PERMISSION_PATTERNS);
6871 } catch (RemoteException ex) {
6872 }
6873 }
6874 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006875 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006876 return;
6877 }
6878
6879 // Does the caller have this permission on the URI?
6880 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6881 // Right now, if you are not the original owner of the permission,
6882 // you are not allowed to revoke it.
6883 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6884 throw new SecurityException("Uid " + callingUid
6885 + " does not have permission to uri " + uri);
6886 //}
6887 }
6888
6889 // Go through all of the permissions and remove any that match.
6890 final List<String> SEGMENTS = uri.getPathSegments();
6891 if (SEGMENTS != null) {
6892 final int NS = SEGMENTS.size();
6893 int N = mGrantedUriPermissions.size();
6894 for (int i=0; i<N; i++) {
6895 HashMap<Uri, UriPermission> perms
6896 = mGrantedUriPermissions.valueAt(i);
6897 Iterator<UriPermission> it = perms.values().iterator();
6898 toploop:
6899 while (it.hasNext()) {
6900 UriPermission perm = it.next();
6901 Uri targetUri = perm.uri;
6902 if (!authority.equals(targetUri.getAuthority())) {
6903 continue;
6904 }
6905 List<String> targetSegments = targetUri.getPathSegments();
6906 if (targetSegments == null) {
6907 continue;
6908 }
6909 if (targetSegments.size() < NS) {
6910 continue;
6911 }
6912 for (int j=0; j<NS; j++) {
6913 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6914 continue toploop;
6915 }
6916 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006917 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006918 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006919 perm.clearModes(modeFlags);
6920 if (perm.modeFlags == 0) {
6921 it.remove();
6922 }
6923 }
6924 if (perms.size() == 0) {
6925 mGrantedUriPermissions.remove(
6926 mGrantedUriPermissions.keyAt(i));
6927 N--;
6928 i--;
6929 }
6930 }
6931 }
6932 }
6933
6934 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6935 int modeFlags) {
6936 synchronized(this) {
6937 final ProcessRecord r = getRecordForAppLocked(caller);
6938 if (r == null) {
6939 throw new SecurityException("Unable to find app for caller "
6940 + caller
6941 + " when revoking permission to uri " + uri);
6942 }
6943 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006944 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006945 return;
6946 }
6947
6948 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6949 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6950 if (modeFlags == 0) {
6951 return;
6952 }
6953
6954 final IPackageManager pm = ActivityThread.getPackageManager();
6955
6956 final String authority = uri.getAuthority();
6957 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006958 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006959 if (cpr != null) {
6960 pi = cpr.info;
6961 } else {
6962 try {
6963 pi = pm.resolveContentProvider(authority,
6964 PackageManager.GET_URI_PERMISSION_PATTERNS);
6965 } catch (RemoteException ex) {
6966 }
6967 }
6968 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006969 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006970 return;
6971 }
6972
6973 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
6974 }
6975 }
6976
6977 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
6978 synchronized (this) {
6979 ProcessRecord app =
6980 who != null ? getRecordForAppLocked(who) : null;
6981 if (app == null) return;
6982
6983 Message msg = Message.obtain();
6984 msg.what = WAIT_FOR_DEBUGGER_MSG;
6985 msg.obj = app;
6986 msg.arg1 = waiting ? 1 : 0;
6987 mHandler.sendMessage(msg);
6988 }
6989 }
6990
6991 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
6992 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08006993 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006994 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08006995 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006996 }
6997
6998 // =========================================================
6999 // TASK MANAGEMENT
7000 // =========================================================
7001
7002 public List getTasks(int maxNum, int flags,
7003 IThumbnailReceiver receiver) {
7004 ArrayList list = new ArrayList();
7005
7006 PendingThumbnailsRecord pending = null;
7007 IApplicationThread topThumbnail = null;
7008 HistoryRecord topRecord = null;
7009
7010 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007011 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007012 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
7013 + ", receiver=" + receiver);
7014
7015 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
7016 != PackageManager.PERMISSION_GRANTED) {
7017 if (receiver != null) {
7018 // If the caller wants to wait for pending thumbnails,
7019 // it ain't gonna get them.
7020 try {
7021 receiver.finished();
7022 } catch (RemoteException ex) {
7023 }
7024 }
7025 String msg = "Permission Denial: getTasks() from pid="
7026 + Binder.getCallingPid()
7027 + ", uid=" + Binder.getCallingUid()
7028 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007029 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007030 throw new SecurityException(msg);
7031 }
7032
7033 int pos = mHistory.size()-1;
7034 HistoryRecord next =
7035 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
7036 HistoryRecord top = null;
7037 CharSequence topDescription = null;
7038 TaskRecord curTask = null;
7039 int numActivities = 0;
7040 int numRunning = 0;
7041 while (pos >= 0 && maxNum > 0) {
7042 final HistoryRecord r = next;
7043 pos--;
7044 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
7045
7046 // Initialize state for next task if needed.
7047 if (top == null ||
7048 (top.state == ActivityState.INITIALIZING
7049 && top.task == r.task)) {
7050 top = r;
7051 topDescription = r.description;
7052 curTask = r.task;
7053 numActivities = numRunning = 0;
7054 }
7055
7056 // Add 'r' into the current task.
7057 numActivities++;
7058 if (r.app != null && r.app.thread != null) {
7059 numRunning++;
7060 }
7061 if (topDescription == null) {
7062 topDescription = r.description;
7063 }
7064
Joe Onorato8a9b2202010-02-26 18:56:32 -08007065 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007066 TAG, r.intent.getComponent().flattenToShortString()
7067 + ": task=" + r.task);
7068
7069 // If the next one is a different task, generate a new
7070 // TaskInfo entry for what we have.
7071 if (next == null || next.task != curTask) {
7072 ActivityManager.RunningTaskInfo ci
7073 = new ActivityManager.RunningTaskInfo();
7074 ci.id = curTask.taskId;
7075 ci.baseActivity = r.intent.getComponent();
7076 ci.topActivity = top.intent.getComponent();
7077 ci.thumbnail = top.thumbnail;
7078 ci.description = topDescription;
7079 ci.numActivities = numActivities;
7080 ci.numRunning = numRunning;
7081 //System.out.println(
7082 // "#" + maxNum + ": " + " descr=" + ci.description);
7083 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007084 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007085 TAG, "State=" + top.state + "Idle=" + top.idle
7086 + " app=" + top.app
7087 + " thr=" + (top.app != null ? top.app.thread : null));
7088 if (top.state == ActivityState.RESUMED
7089 || top.state == ActivityState.PAUSING) {
7090 if (top.idle && top.app != null
7091 && top.app.thread != null) {
7092 topRecord = top;
7093 topThumbnail = top.app.thread;
7094 } else {
7095 top.thumbnailNeeded = true;
7096 }
7097 }
7098 if (pending == null) {
7099 pending = new PendingThumbnailsRecord(receiver);
7100 }
7101 pending.pendingRecords.add(top);
7102 }
7103 list.add(ci);
7104 maxNum--;
7105 top = null;
7106 }
7107 }
7108
7109 if (pending != null) {
7110 mPendingThumbnails.add(pending);
7111 }
7112 }
7113
Joe Onorato8a9b2202010-02-26 18:56:32 -08007114 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007115
7116 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007117 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007118 try {
7119 topThumbnail.requestThumbnail(topRecord);
7120 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007121 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007122 sendPendingThumbnail(null, topRecord, null, null, true);
7123 }
7124 }
7125
7126 if (pending == null && receiver != null) {
7127 // In this case all thumbnails were available and the client
7128 // is being asked to be told when the remaining ones come in...
7129 // which is unusually, since the top-most currently running
7130 // activity should never have a canned thumbnail! Oh well.
7131 try {
7132 receiver.finished();
7133 } catch (RemoteException ex) {
7134 }
7135 }
7136
7137 return list;
7138 }
7139
7140 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
7141 int flags) {
7142 synchronized (this) {
7143 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
7144 "getRecentTasks()");
7145
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007146 IPackageManager pm = ActivityThread.getPackageManager();
7147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007148 final int N = mRecentTasks.size();
7149 ArrayList<ActivityManager.RecentTaskInfo> res
7150 = new ArrayList<ActivityManager.RecentTaskInfo>(
7151 maxNum < N ? maxNum : N);
7152 for (int i=0; i<N && maxNum > 0; i++) {
7153 TaskRecord tr = mRecentTasks.get(i);
7154 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
7155 || (tr.intent == null)
7156 || ((tr.intent.getFlags()
7157 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
7158 ActivityManager.RecentTaskInfo rti
7159 = new ActivityManager.RecentTaskInfo();
7160 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
7161 rti.baseIntent = new Intent(
7162 tr.intent != null ? tr.intent : tr.affinityIntent);
7163 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007164
7165 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
7166 // Check whether this activity is currently available.
7167 try {
7168 if (rti.origActivity != null) {
7169 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
7170 continue;
7171 }
7172 } else if (rti.baseIntent != null) {
7173 if (pm.queryIntentActivities(rti.baseIntent,
7174 null, 0) == null) {
7175 continue;
7176 }
7177 }
7178 } catch (RemoteException e) {
7179 // Will never happen.
7180 }
7181 }
7182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007183 res.add(rti);
7184 maxNum--;
7185 }
7186 }
7187 return res;
7188 }
7189 }
7190
7191 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
7192 int j;
7193 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
7194 TaskRecord jt = startTask;
7195
7196 // First look backwards
7197 for (j=startIndex-1; j>=0; j--) {
7198 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7199 if (r.task != jt) {
7200 jt = r.task;
7201 if (affinity.equals(jt.affinity)) {
7202 return j;
7203 }
7204 }
7205 }
7206
7207 // Now look forwards
7208 final int N = mHistory.size();
7209 jt = startTask;
7210 for (j=startIndex+1; j<N; j++) {
7211 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7212 if (r.task != jt) {
7213 if (affinity.equals(jt.affinity)) {
7214 return j;
7215 }
7216 jt = r.task;
7217 }
7218 }
7219
7220 // Might it be at the top?
7221 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
7222 return N-1;
7223 }
7224
7225 return -1;
7226 }
7227
7228 /**
7229 * Perform a reset of the given task, if needed as part of launching it.
7230 * Returns the new HistoryRecord at the top of the task.
7231 */
7232 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
7233 HistoryRecord newActivity) {
7234 boolean forceReset = (newActivity.info.flags
7235 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
7236 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
7237 if ((newActivity.info.flags
7238 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
7239 forceReset = true;
7240 }
7241 }
7242
7243 final TaskRecord task = taskTop.task;
7244
7245 // We are going to move through the history list so that we can look
7246 // at each activity 'target' with 'below' either the interesting
7247 // activity immediately below it in the stack or null.
7248 HistoryRecord target = null;
7249 int targetI = 0;
7250 int taskTopI = -1;
7251 int replyChainEnd = -1;
7252 int lastReparentPos = -1;
7253 for (int i=mHistory.size()-1; i>=-1; i--) {
7254 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
7255
7256 if (below != null && below.finishing) {
7257 continue;
7258 }
7259 if (target == null) {
7260 target = below;
7261 targetI = i;
7262 // If we were in the middle of a reply chain before this
7263 // task, it doesn't appear like the root of the chain wants
7264 // anything interesting, so drop it.
7265 replyChainEnd = -1;
7266 continue;
7267 }
7268
7269 final int flags = target.info.flags;
7270
7271 final boolean finishOnTaskLaunch =
7272 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7273 final boolean allowTaskReparenting =
7274 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7275
7276 if (target.task == task) {
7277 // We are inside of the task being reset... we'll either
7278 // finish this activity, push it out for another task,
7279 // or leave it as-is. We only do this
7280 // for activities that are not the root of the task (since
7281 // if we finish the root, we may no longer have the task!).
7282 if (taskTopI < 0) {
7283 taskTopI = targetI;
7284 }
7285 if (below != null && below.task == task) {
7286 final boolean clearWhenTaskReset =
7287 (target.intent.getFlags()
7288 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007289 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007290 // If this activity is sending a reply to a previous
7291 // activity, we can't do anything with it now until
7292 // we reach the start of the reply chain.
7293 // XXX note that we are assuming the result is always
7294 // to the previous activity, which is almost always
7295 // the case but we really shouldn't count on.
7296 if (replyChainEnd < 0) {
7297 replyChainEnd = targetI;
7298 }
Ed Heyl73798232009-03-24 21:32:21 -07007299 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007300 && target.taskAffinity != null
7301 && !target.taskAffinity.equals(task.affinity)) {
7302 // If this activity has an affinity for another
7303 // task, then we need to move it out of here. We will
7304 // move it as far out of the way as possible, to the
7305 // bottom of the activity stack. This also keeps it
7306 // correctly ordered with any activities we previously
7307 // moved.
7308 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7309 if (target.taskAffinity != null
7310 && target.taskAffinity.equals(p.task.affinity)) {
7311 // If the activity currently at the bottom has the
7312 // same task affinity as the one we are moving,
7313 // then merge it into the same task.
7314 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007315 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 + " out to bottom task " + p.task);
7317 } else {
7318 mCurTask++;
7319 if (mCurTask <= 0) {
7320 mCurTask = 1;
7321 }
7322 target.task = new TaskRecord(mCurTask, target.info, null,
7323 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7324 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007325 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 + " out to new task " + target.task);
7327 }
7328 mWindowManager.setAppGroupId(target, task.taskId);
7329 if (replyChainEnd < 0) {
7330 replyChainEnd = targetI;
7331 }
7332 int dstPos = 0;
7333 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7334 p = (HistoryRecord)mHistory.get(srcPos);
7335 if (p.finishing) {
7336 continue;
7337 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007338 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007339 + " out to target's task " + target.task);
7340 task.numActivities--;
7341 p.task = target.task;
7342 target.task.numActivities++;
7343 mHistory.remove(srcPos);
7344 mHistory.add(dstPos, p);
7345 mWindowManager.moveAppToken(dstPos, p);
7346 mWindowManager.setAppGroupId(p, p.task.taskId);
7347 dstPos++;
7348 if (VALIDATE_TOKENS) {
7349 mWindowManager.validateAppTokens(mHistory);
7350 }
7351 i++;
7352 }
7353 if (taskTop == p) {
7354 taskTop = below;
7355 }
7356 if (taskTopI == replyChainEnd) {
7357 taskTopI = -1;
7358 }
7359 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007360 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007361 } else if (forceReset || finishOnTaskLaunch
7362 || clearWhenTaskReset) {
7363 // If the activity should just be removed -- either
7364 // because it asks for it, or the task should be
7365 // cleared -- then finish it and anything that is
7366 // part of its reply chain.
7367 if (clearWhenTaskReset) {
7368 // In this case, we want to finish this activity
7369 // and everything above it, so be sneaky and pretend
7370 // like these are all in the reply chain.
7371 replyChainEnd = targetI+1;
7372 while (replyChainEnd < mHistory.size() &&
7373 ((HistoryRecord)mHistory.get(
7374 replyChainEnd)).task == task) {
7375 replyChainEnd++;
7376 }
7377 replyChainEnd--;
7378 } else if (replyChainEnd < 0) {
7379 replyChainEnd = targetI;
7380 }
7381 HistoryRecord p = null;
7382 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7383 p = (HistoryRecord)mHistory.get(srcPos);
7384 if (p.finishing) {
7385 continue;
7386 }
7387 if (finishActivityLocked(p, srcPos,
7388 Activity.RESULT_CANCELED, null, "reset")) {
7389 replyChainEnd--;
7390 srcPos--;
7391 }
7392 }
7393 if (taskTop == p) {
7394 taskTop = below;
7395 }
7396 if (taskTopI == replyChainEnd) {
7397 taskTopI = -1;
7398 }
7399 replyChainEnd = -1;
7400 } else {
7401 // If we were in the middle of a chain, well the
7402 // activity that started it all doesn't want anything
7403 // special, so leave it all as-is.
7404 replyChainEnd = -1;
7405 }
7406 } else {
7407 // Reached the bottom of the task -- any reply chain
7408 // should be left as-is.
7409 replyChainEnd = -1;
7410 }
7411
7412 } else if (target.resultTo != null) {
7413 // If this activity is sending a reply to a previous
7414 // activity, we can't do anything with it now until
7415 // we reach the start of the reply chain.
7416 // XXX note that we are assuming the result is always
7417 // to the previous activity, which is almost always
7418 // the case but we really shouldn't count on.
7419 if (replyChainEnd < 0) {
7420 replyChainEnd = targetI;
7421 }
7422
7423 } else if (taskTopI >= 0 && allowTaskReparenting
7424 && task.affinity != null
7425 && task.affinity.equals(target.taskAffinity)) {
7426 // We are inside of another task... if this activity has
7427 // an affinity for our task, then either remove it if we are
7428 // clearing or move it over to our task. Note that
7429 // we currently punt on the case where we are resetting a
7430 // task that is not at the top but who has activities above
7431 // with an affinity to it... this is really not a normal
7432 // case, and we will need to later pull that task to the front
7433 // and usually at that point we will do the reset and pick
7434 // up those remaining activities. (This only happens if
7435 // someone starts an activity in a new task from an activity
7436 // in a task that is not currently on top.)
7437 if (forceReset || finishOnTaskLaunch) {
7438 if (replyChainEnd < 0) {
7439 replyChainEnd = targetI;
7440 }
7441 HistoryRecord p = null;
7442 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7443 p = (HistoryRecord)mHistory.get(srcPos);
7444 if (p.finishing) {
7445 continue;
7446 }
7447 if (finishActivityLocked(p, srcPos,
7448 Activity.RESULT_CANCELED, null, "reset")) {
7449 taskTopI--;
7450 lastReparentPos--;
7451 replyChainEnd--;
7452 srcPos--;
7453 }
7454 }
7455 replyChainEnd = -1;
7456 } else {
7457 if (replyChainEnd < 0) {
7458 replyChainEnd = targetI;
7459 }
7460 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7461 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7462 if (p.finishing) {
7463 continue;
7464 }
7465 if (lastReparentPos < 0) {
7466 lastReparentPos = taskTopI;
7467 taskTop = p;
7468 } else {
7469 lastReparentPos--;
7470 }
7471 mHistory.remove(srcPos);
7472 p.task.numActivities--;
7473 p.task = task;
7474 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007475 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007476 + " in to resetting task " + task);
7477 task.numActivities++;
7478 mWindowManager.moveAppToken(lastReparentPos, p);
7479 mWindowManager.setAppGroupId(p, p.task.taskId);
7480 if (VALIDATE_TOKENS) {
7481 mWindowManager.validateAppTokens(mHistory);
7482 }
7483 }
7484 replyChainEnd = -1;
7485
7486 // Now we've moved it in to place... but what if this is
7487 // a singleTop activity and we have put it on top of another
7488 // instance of the same activity? Then we drop the instance
7489 // below so it remains singleTop.
7490 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7491 for (int j=lastReparentPos-1; j>=0; j--) {
7492 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7493 if (p.finishing) {
7494 continue;
7495 }
7496 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7497 if (finishActivityLocked(p, j,
7498 Activity.RESULT_CANCELED, null, "replace")) {
7499 taskTopI--;
7500 lastReparentPos--;
7501 }
7502 }
7503 }
7504 }
7505 }
7506 }
7507
7508 target = below;
7509 targetI = i;
7510 }
7511
7512 return taskTop;
7513 }
7514
7515 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007516 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517 */
7518 public void moveTaskToFront(int task) {
7519 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7520 "moveTaskToFront()");
7521
7522 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007523 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7524 Binder.getCallingUid(), "Task to front")) {
7525 return;
7526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007527 final long origId = Binder.clearCallingIdentity();
7528 try {
7529 int N = mRecentTasks.size();
7530 for (int i=0; i<N; i++) {
7531 TaskRecord tr = mRecentTasks.get(i);
7532 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007533 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534 return;
7535 }
7536 }
7537 for (int i=mHistory.size()-1; i>=0; i--) {
7538 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7539 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007540 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007541 return;
7542 }
7543 }
7544 } finally {
7545 Binder.restoreCallingIdentity(origId);
7546 }
7547 }
7548 }
7549
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007550 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007551 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007552
7553 final int task = tr.taskId;
7554 int top = mHistory.size()-1;
7555
7556 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7557 // nothing to do!
7558 return;
7559 }
7560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007561 ArrayList moved = new ArrayList();
7562
7563 // Applying the affinities may have removed entries from the history,
7564 // so get the size again.
7565 top = mHistory.size()-1;
7566 int pos = top;
7567
7568 // Shift all activities with this task up to the top
7569 // of the stack, keeping them in the same internal order.
7570 while (pos >= 0) {
7571 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007572 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7574 boolean first = true;
7575 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007576 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007577 mHistory.remove(pos);
7578 mHistory.add(top, r);
7579 moved.add(0, r);
7580 top--;
7581 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007582 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 first = false;
7584 }
7585 }
7586 pos--;
7587 }
7588
Joe Onorato8a9b2202010-02-26 18:56:32 -08007589 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007590 "Prepare to front transition: task=" + tr);
7591 if (reason != null &&
7592 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7593 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7594 HistoryRecord r = topRunningActivityLocked(null);
7595 if (r != null) {
7596 mNoAnimActivities.add(r);
7597 }
7598 } else {
7599 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7600 }
7601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007602 mWindowManager.moveAppTokensToTop(moved);
7603 if (VALIDATE_TOKENS) {
7604 mWindowManager.validateAppTokens(mHistory);
7605 }
7606
Josh Bartel7f208742010-02-25 11:01:44 -06007607 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007608 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007609 }
7610
Josh Bartel7f208742010-02-25 11:01:44 -06007611 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007612 resumeTopActivityLocked(null);
7613 }
7614
7615 public void moveTaskToBack(int task) {
7616 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7617 "moveTaskToBack()");
7618
7619 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007620 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7621 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7622 Binder.getCallingUid(), "Task to back")) {
7623 return;
7624 }
7625 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007627 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007628 Binder.restoreCallingIdentity(origId);
7629 }
7630 }
7631
7632 /**
7633 * Moves an activity, and all of the other activities within the same task, to the bottom
7634 * of the history stack. The activity's order within the task is unchanged.
7635 *
7636 * @param token A reference to the activity we wish to move
7637 * @param nonRoot If false then this only works if the activity is the root
7638 * of a task; if true it will work for any activity in a task.
7639 * @return Returns true if the move completed, false if not.
7640 */
7641 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7642 synchronized(this) {
7643 final long origId = Binder.clearCallingIdentity();
7644 int taskId = getTaskForActivityLocked(token, !nonRoot);
7645 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007646 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007647 }
7648 Binder.restoreCallingIdentity(origId);
7649 }
7650 return false;
7651 }
7652
7653 /**
7654 * Worker method for rearranging history stack. Implements the function of moving all
7655 * activities for a specific task (gathering them if disjoint) into a single group at the
7656 * bottom of the stack.
7657 *
7658 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7659 * to premeptively cancel the move.
7660 *
7661 * @param task The taskId to collect and move to the bottom.
7662 * @return Returns true if the move completed, false if not.
7663 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007664 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007665 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666
7667 // If we have a watcher, preflight the move before committing to it. First check
7668 // for *other* available tasks, but if none are available, then try again allowing the
7669 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007670 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007671 HistoryRecord next = topRunningActivityLocked(null, task);
7672 if (next == null) {
7673 next = topRunningActivityLocked(null, 0);
7674 }
7675 if (next != null) {
7676 // ask watcher if this is allowed
7677 boolean moveOK = true;
7678 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007679 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007680 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007681 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007682 }
7683 if (!moveOK) {
7684 return false;
7685 }
7686 }
7687 }
7688
7689 ArrayList moved = new ArrayList();
7690
Joe Onorato8a9b2202010-02-26 18:56:32 -08007691 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007693
7694 final int N = mHistory.size();
7695 int bottom = 0;
7696 int pos = 0;
7697
7698 // Shift all activities with this task down to the bottom
7699 // of the stack, keeping them in the same internal order.
7700 while (pos < N) {
7701 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007702 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007703 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7704 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007705 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 mHistory.remove(pos);
7707 mHistory.add(bottom, r);
7708 moved.add(r);
7709 bottom++;
7710 }
7711 pos++;
7712 }
7713
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007714 if (reason != null &&
7715 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7716 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7717 HistoryRecord r = topRunningActivityLocked(null);
7718 if (r != null) {
7719 mNoAnimActivities.add(r);
7720 }
7721 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007722 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007724 mWindowManager.moveAppTokensToBottom(moved);
7725 if (VALIDATE_TOKENS) {
7726 mWindowManager.validateAppTokens(mHistory);
7727 }
7728
Josh Bartel7f208742010-02-25 11:01:44 -06007729 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 return true;
7731 }
7732
7733 public void moveTaskBackwards(int task) {
7734 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7735 "moveTaskBackwards()");
7736
7737 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007738 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7739 Binder.getCallingUid(), "Task backwards")) {
7740 return;
7741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742 final long origId = Binder.clearCallingIdentity();
7743 moveTaskBackwardsLocked(task);
7744 Binder.restoreCallingIdentity(origId);
7745 }
7746 }
7747
7748 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007749 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 }
7751
7752 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7753 synchronized(this) {
7754 return getTaskForActivityLocked(token, onlyRoot);
7755 }
7756 }
7757
7758 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7759 final int N = mHistory.size();
7760 TaskRecord lastTask = null;
7761 for (int i=0; i<N; i++) {
7762 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7763 if (r == token) {
7764 if (!onlyRoot || lastTask != r.task) {
7765 return r.task.taskId;
7766 }
7767 return -1;
7768 }
7769 lastTask = r.task;
7770 }
7771
7772 return -1;
7773 }
7774
7775 /**
7776 * Returns the top activity in any existing task matching the given
7777 * Intent. Returns null if no such task is found.
7778 */
7779 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7780 ComponentName cls = intent.getComponent();
7781 if (info.targetActivity != null) {
7782 cls = new ComponentName(info.packageName, info.targetActivity);
7783 }
7784
7785 TaskRecord cp = null;
7786
7787 final int N = mHistory.size();
7788 for (int i=(N-1); i>=0; i--) {
7789 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7790 if (!r.finishing && r.task != cp
7791 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7792 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007793 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 // + "/aff=" + r.task.affinity + " to new cls="
7795 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7796 if (r.task.affinity != null) {
7797 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007798 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 return r;
7800 }
7801 } else if (r.task.intent != null
7802 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007803 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007805 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007806 return r;
7807 } else if (r.task.affinityIntent != null
7808 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007809 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007811 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007812 return r;
7813 }
7814 }
7815 }
7816
7817 return null;
7818 }
7819
7820 /**
7821 * Returns the first activity (starting from the top of the stack) that
7822 * is the same as the given activity. Returns null if no such activity
7823 * is found.
7824 */
7825 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7826 ComponentName cls = intent.getComponent();
7827 if (info.targetActivity != null) {
7828 cls = new ComponentName(info.packageName, info.targetActivity);
7829 }
7830
7831 final int N = mHistory.size();
7832 for (int i=(N-1); i>=0; i--) {
7833 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7834 if (!r.finishing) {
7835 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007836 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007837 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007838 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007839 return r;
7840 }
7841 }
7842 }
7843
7844 return null;
7845 }
7846
7847 public void finishOtherInstances(IBinder token, ComponentName className) {
7848 synchronized(this) {
7849 final long origId = Binder.clearCallingIdentity();
7850
7851 int N = mHistory.size();
7852 TaskRecord lastTask = null;
7853 for (int i=0; i<N; i++) {
7854 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7855 if (r.realActivity.equals(className)
7856 && r != token && lastTask != r.task) {
7857 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7858 null, "others")) {
7859 i--;
7860 N--;
7861 }
7862 }
7863 lastTask = r.task;
7864 }
7865
7866 Binder.restoreCallingIdentity(origId);
7867 }
7868 }
7869
7870 // =========================================================
7871 // THUMBNAILS
7872 // =========================================================
7873
7874 public void reportThumbnail(IBinder token,
7875 Bitmap thumbnail, CharSequence description) {
7876 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7877 final long origId = Binder.clearCallingIdentity();
7878 sendPendingThumbnail(null, token, thumbnail, description, true);
7879 Binder.restoreCallingIdentity(origId);
7880 }
7881
7882 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7883 Bitmap thumbnail, CharSequence description, boolean always) {
7884 TaskRecord task = null;
7885 ArrayList receivers = null;
7886
7887 //System.out.println("Send pending thumbnail: " + r);
7888
7889 synchronized(this) {
7890 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007891 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 if (index < 0) {
7893 return;
7894 }
7895 r = (HistoryRecord)mHistory.get(index);
7896 }
7897 if (thumbnail == null) {
7898 thumbnail = r.thumbnail;
7899 description = r.description;
7900 }
7901 if (thumbnail == null && !always) {
7902 // If there is no thumbnail, and this entry is not actually
7903 // going away, then abort for now and pick up the next
7904 // thumbnail we get.
7905 return;
7906 }
7907 task = r.task;
7908
7909 int N = mPendingThumbnails.size();
7910 int i=0;
7911 while (i<N) {
7912 PendingThumbnailsRecord pr =
7913 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7914 //System.out.println("Looking in " + pr.pendingRecords);
7915 if (pr.pendingRecords.remove(r)) {
7916 if (receivers == null) {
7917 receivers = new ArrayList();
7918 }
7919 receivers.add(pr);
7920 if (pr.pendingRecords.size() == 0) {
7921 pr.finished = true;
7922 mPendingThumbnails.remove(i);
7923 N--;
7924 continue;
7925 }
7926 }
7927 i++;
7928 }
7929 }
7930
7931 if (receivers != null) {
7932 final int N = receivers.size();
7933 for (int i=0; i<N; i++) {
7934 try {
7935 PendingThumbnailsRecord pr =
7936 (PendingThumbnailsRecord)receivers.get(i);
7937 pr.receiver.newThumbnail(
7938 task != null ? task.taskId : -1, thumbnail, description);
7939 if (pr.finished) {
7940 pr.receiver.finished();
7941 }
7942 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007943 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007944 }
7945 }
7946 }
7947 }
7948
7949 // =========================================================
7950 // CONTENT PROVIDERS
7951 // =========================================================
7952
7953 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7954 List providers = null;
7955 try {
7956 providers = ActivityThread.getPackageManager().
7957 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007958 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007959 } catch (RemoteException ex) {
7960 }
7961 if (providers != null) {
7962 final int N = providers.size();
7963 for (int i=0; i<N; i++) {
7964 ProviderInfo cpi =
7965 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007966 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967 if (cpr == null) {
7968 cpr = new ContentProviderRecord(cpi, app.info);
7969 mProvidersByClass.put(cpi.name, cpr);
7970 }
7971 app.pubProviders.put(cpi.name, cpr);
7972 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007973 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007974 }
7975 }
7976 return providers;
7977 }
7978
7979 private final String checkContentProviderPermissionLocked(
7980 ProviderInfo cpi, ProcessRecord r, int mode) {
7981 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
7982 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
7983 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
7984 cpi.exported ? -1 : cpi.applicationInfo.uid)
7985 == PackageManager.PERMISSION_GRANTED
7986 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
7987 return null;
7988 }
7989 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
7990 cpi.exported ? -1 : cpi.applicationInfo.uid)
7991 == PackageManager.PERMISSION_GRANTED) {
7992 return null;
7993 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07007994
7995 PathPermission[] pps = cpi.pathPermissions;
7996 if (pps != null) {
7997 int i = pps.length;
7998 while (i > 0) {
7999 i--;
8000 PathPermission pp = pps[i];
8001 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
8002 cpi.exported ? -1 : cpi.applicationInfo.uid)
8003 == PackageManager.PERMISSION_GRANTED
8004 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8005 return null;
8006 }
8007 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
8008 cpi.exported ? -1 : cpi.applicationInfo.uid)
8009 == PackageManager.PERMISSION_GRANTED) {
8010 return null;
8011 }
8012 }
8013 }
8014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015 String msg = "Permission Denial: opening provider " + cpi.name
8016 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
8017 + ", uid=" + callingUid + ") requires "
8018 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008019 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008020 return msg;
8021 }
8022
8023 private final ContentProviderHolder getContentProviderImpl(
8024 IApplicationThread caller, String name) {
8025 ContentProviderRecord cpr;
8026 ProviderInfo cpi = null;
8027
8028 synchronized(this) {
8029 ProcessRecord r = null;
8030 if (caller != null) {
8031 r = getRecordForAppLocked(caller);
8032 if (r == null) {
8033 throw new SecurityException(
8034 "Unable to find app for caller " + caller
8035 + " (pid=" + Binder.getCallingPid()
8036 + ") when getting content provider " + name);
8037 }
8038 }
8039
8040 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07008041 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008042 if (cpr != null) {
8043 cpi = cpr.info;
8044 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8045 return new ContentProviderHolder(cpi,
8046 cpi.readPermission != null
8047 ? cpi.readPermission : cpi.writePermission);
8048 }
8049
8050 if (r != null && cpr.canRunHere(r)) {
8051 // This provider has been published or is in the process
8052 // of being published... but it is also allowed to run
8053 // in the caller's process, so don't make a connection
8054 // and just let the caller instantiate its own instance.
8055 if (cpr.provider != null) {
8056 // don't give caller the provider object, it needs
8057 // to make its own.
8058 cpr = new ContentProviderRecord(cpr);
8059 }
8060 return cpr;
8061 }
8062
8063 final long origId = Binder.clearCallingIdentity();
8064
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008065 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 // return it right away.
8067 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008068 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008069 "Adding provider requested by "
8070 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008071 + cpr.info.processName);
8072 Integer cnt = r.conProviders.get(cpr);
8073 if (cnt == null) {
8074 r.conProviders.put(cpr, new Integer(1));
8075 } else {
8076 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008078 cpr.clients.add(r);
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07008079 if (cpr.app != null && r.setAdj >= VISIBLE_APP_ADJ) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07008080 // If this is a visible app accessing the provider,
8081 // make sure to count it as being accessed and thus
8082 // back up on the LRU list. This is good because
8083 // content providers are often expensive to start.
8084 updateLruProcessLocked(cpr.app, false, true);
8085 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07008086 } else {
8087 cpr.externals++;
8088 }
8089
8090 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008091 updateOomAdjLocked(cpr.app);
8092 }
8093
8094 Binder.restoreCallingIdentity(origId);
8095
8096 } else {
8097 try {
8098 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008099 resolveContentProvider(name,
8100 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008101 } catch (RemoteException ex) {
8102 }
8103 if (cpi == null) {
8104 return null;
8105 }
8106
8107 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8108 return new ContentProviderHolder(cpi,
8109 cpi.readPermission != null
8110 ? cpi.readPermission : cpi.writePermission);
8111 }
8112
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008113 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
8114 && !cpi.processName.equals("system")) {
8115 // If this content provider does not run in the system
8116 // process, and the system is not yet ready to run other
8117 // processes, then fail fast instead of hanging.
8118 throw new IllegalArgumentException(
8119 "Attempt to launch content provider before system ready");
8120 }
8121
Dianne Hackborn860755f2010-06-03 18:47:52 -07008122 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 final boolean firstClass = cpr == null;
8124 if (firstClass) {
8125 try {
8126 ApplicationInfo ai =
8127 ActivityThread.getPackageManager().
8128 getApplicationInfo(
8129 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008130 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008131 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008132 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008133 + cpi.name);
8134 return null;
8135 }
8136 cpr = new ContentProviderRecord(cpi, ai);
8137 } catch (RemoteException ex) {
8138 // pm is in same process, this will never happen.
8139 }
8140 }
8141
8142 if (r != null && cpr.canRunHere(r)) {
8143 // If this is a multiprocess provider, then just return its
8144 // info and allow the caller to instantiate it. Only do
8145 // this if the provider is the same user as the caller's
8146 // process, or can run as root (so can be in any process).
8147 return cpr;
8148 }
8149
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008150 if (DEBUG_PROVIDER) {
8151 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08008152 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008153 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008154 }
8155
8156 // This is single process, and our app is now connecting to it.
8157 // See if we are already in the process of launching this
8158 // provider.
8159 final int N = mLaunchingProviders.size();
8160 int i;
8161 for (i=0; i<N; i++) {
8162 if (mLaunchingProviders.get(i) == cpr) {
8163 break;
8164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165 }
8166
8167 // If the provider is not already being launched, then get it
8168 // started.
8169 if (i >= N) {
8170 final long origId = Binder.clearCallingIdentity();
8171 ProcessRecord proc = startProcessLocked(cpi.processName,
8172 cpr.appInfo, false, 0, "content provider",
8173 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008174 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008176 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008177 + cpi.applicationInfo.packageName + "/"
8178 + cpi.applicationInfo.uid + " for provider "
8179 + name + ": process is bad");
8180 return null;
8181 }
8182 cpr.launchingApp = proc;
8183 mLaunchingProviders.add(cpr);
8184 Binder.restoreCallingIdentity(origId);
8185 }
8186
8187 // Make sure the provider is published (the same provider class
8188 // may be published under multiple names).
8189 if (firstClass) {
8190 mProvidersByClass.put(cpi.name, cpr);
8191 }
8192 mProvidersByName.put(name, cpr);
8193
8194 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008195 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008196 "Adding provider requested by "
8197 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008198 + cpr.info.processName);
8199 Integer cnt = r.conProviders.get(cpr);
8200 if (cnt == null) {
8201 r.conProviders.put(cpr, new Integer(1));
8202 } else {
8203 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008205 cpr.clients.add(r);
8206 } else {
8207 cpr.externals++;
8208 }
8209 }
8210 }
8211
8212 // Wait for the provider to be published...
8213 synchronized (cpr) {
8214 while (cpr.provider == null) {
8215 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008216 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 + cpi.applicationInfo.packageName + "/"
8218 + cpi.applicationInfo.uid + " for provider "
8219 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008220 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008221 cpi.applicationInfo.packageName,
8222 cpi.applicationInfo.uid, name);
8223 return null;
8224 }
8225 try {
8226 cpr.wait();
8227 } catch (InterruptedException ex) {
8228 }
8229 }
8230 }
8231 return cpr;
8232 }
8233
8234 public final ContentProviderHolder getContentProvider(
8235 IApplicationThread caller, String name) {
8236 if (caller == null) {
8237 String msg = "null IApplicationThread when getting content provider "
8238 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008239 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008240 throw new SecurityException(msg);
8241 }
8242
8243 return getContentProviderImpl(caller, name);
8244 }
8245
8246 private ContentProviderHolder getContentProviderExternal(String name) {
8247 return getContentProviderImpl(null, name);
8248 }
8249
8250 /**
8251 * Drop a content provider from a ProcessRecord's bookkeeping
8252 * @param cpr
8253 */
8254 public void removeContentProvider(IApplicationThread caller, String name) {
8255 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008256 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008257 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008258 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008259 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008260 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008261 return;
8262 }
8263 final ProcessRecord r = getRecordForAppLocked(caller);
8264 if (r == null) {
8265 throw new SecurityException(
8266 "Unable to find app for caller " + caller +
8267 " when removing content provider " + name);
8268 }
8269 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008270 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008271 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008272 + r.info.processName + " from process "
8273 + localCpr.appInfo.processName);
8274 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008275 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008276 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008277 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008278 return;
8279 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008280 Integer cnt = r.conProviders.get(localCpr);
8281 if (cnt == null || cnt.intValue() <= 1) {
8282 localCpr.clients.remove(r);
8283 r.conProviders.remove(localCpr);
8284 } else {
8285 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008287 }
8288 updateOomAdjLocked();
8289 }
8290 }
8291
8292 private void removeContentProviderExternal(String name) {
8293 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008294 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008295 if(cpr == null) {
8296 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008297 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008298 return;
8299 }
8300
8301 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008302 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008303 localCpr.externals--;
8304 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008305 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008306 }
8307 updateOomAdjLocked();
8308 }
8309 }
8310
8311 public final void publishContentProviders(IApplicationThread caller,
8312 List<ContentProviderHolder> providers) {
8313 if (providers == null) {
8314 return;
8315 }
8316
8317 synchronized(this) {
8318 final ProcessRecord r = getRecordForAppLocked(caller);
8319 if (r == null) {
8320 throw new SecurityException(
8321 "Unable to find app for caller " + caller
8322 + " (pid=" + Binder.getCallingPid()
8323 + ") when publishing content providers");
8324 }
8325
8326 final long origId = Binder.clearCallingIdentity();
8327
8328 final int N = providers.size();
8329 for (int i=0; i<N; i++) {
8330 ContentProviderHolder src = providers.get(i);
8331 if (src == null || src.info == null || src.provider == null) {
8332 continue;
8333 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07008334 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 if (dst != null) {
8336 mProvidersByClass.put(dst.info.name, dst);
8337 String names[] = dst.info.authority.split(";");
8338 for (int j = 0; j < names.length; j++) {
8339 mProvidersByName.put(names[j], dst);
8340 }
8341
8342 int NL = mLaunchingProviders.size();
8343 int j;
8344 for (j=0; j<NL; j++) {
8345 if (mLaunchingProviders.get(j) == dst) {
8346 mLaunchingProviders.remove(j);
8347 j--;
8348 NL--;
8349 }
8350 }
8351 synchronized (dst) {
8352 dst.provider = src.provider;
8353 dst.app = r;
8354 dst.notifyAll();
8355 }
8356 updateOomAdjLocked(r);
8357 }
8358 }
8359
8360 Binder.restoreCallingIdentity(origId);
8361 }
8362 }
8363
8364 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008365 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008366 synchronized (mSelf) {
8367 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8368 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008369 if (providers != null) {
8370 for (int i=providers.size()-1; i>=0; i--) {
8371 ProviderInfo pi = (ProviderInfo)providers.get(i);
8372 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8373 Slog.w(TAG, "Not installing system proc provider " + pi.name
8374 + ": not system .apk");
8375 providers.remove(i);
8376 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008377 }
8378 }
8379 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008380 if (providers != null) {
8381 mSystemThread.installSystemProviders(providers);
8382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008383 }
8384
8385 // =========================================================
8386 // GLOBAL MANAGEMENT
8387 // =========================================================
8388
8389 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8390 ApplicationInfo info, String customProcess) {
8391 String proc = customProcess != null ? customProcess : info.processName;
8392 BatteryStatsImpl.Uid.Proc ps = null;
8393 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8394 synchronized (stats) {
8395 ps = stats.getProcessStatsLocked(info.uid, proc);
8396 }
8397 return new ProcessRecord(ps, thread, info, proc);
8398 }
8399
8400 final ProcessRecord addAppLocked(ApplicationInfo info) {
8401 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8402
8403 if (app == null) {
8404 app = newProcessRecordLocked(null, info, null);
8405 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008406 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008407 }
8408
8409 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8410 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8411 app.persistent = true;
8412 app.maxAdj = CORE_SERVER_ADJ;
8413 }
8414 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8415 mPersistentStartingProcesses.add(app);
8416 startProcessLocked(app, "added application", app.processName);
8417 }
8418
8419 return app;
8420 }
8421
8422 public void unhandledBack() {
8423 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8424 "unhandledBack()");
8425
8426 synchronized(this) {
8427 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008428 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008429 TAG, "Performing unhandledBack(): stack size = " + count);
8430 if (count > 1) {
8431 final long origId = Binder.clearCallingIdentity();
8432 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8433 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8434 Binder.restoreCallingIdentity(origId);
8435 }
8436 }
8437 }
8438
8439 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8440 String name = uri.getAuthority();
8441 ContentProviderHolder cph = getContentProviderExternal(name);
8442 ParcelFileDescriptor pfd = null;
8443 if (cph != null) {
8444 // We record the binder invoker's uid in thread-local storage before
8445 // going to the content provider to open the file. Later, in the code
8446 // that handles all permissions checks, we look for this uid and use
8447 // that rather than the Activity Manager's own uid. The effect is that
8448 // we do the check against the caller's permissions even though it looks
8449 // to the content provider like the Activity Manager itself is making
8450 // the request.
8451 sCallerIdentity.set(new Identity(
8452 Binder.getCallingPid(), Binder.getCallingUid()));
8453 try {
8454 pfd = cph.provider.openFile(uri, "r");
8455 } catch (FileNotFoundException e) {
8456 // do nothing; pfd will be returned null
8457 } finally {
8458 // Ensure that whatever happens, we clean up the identity state
8459 sCallerIdentity.remove();
8460 }
8461
8462 // We've got the fd now, so we're done with the provider.
8463 removeContentProviderExternal(name);
8464 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008465 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008466 }
8467 return pfd;
8468 }
8469
8470 public void goingToSleep() {
8471 synchronized(this) {
8472 mSleeping = true;
8473 mWindowManager.setEventDispatching(false);
8474
8475 if (mResumedActivity != null) {
8476 pauseIfSleepingLocked();
8477 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008478 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008479 }
8480 }
8481 }
8482
Dianne Hackborn55280a92009-05-07 15:53:46 -07008483 public boolean shutdown(int timeout) {
8484 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8485 != PackageManager.PERMISSION_GRANTED) {
8486 throw new SecurityException("Requires permission "
8487 + android.Manifest.permission.SHUTDOWN);
8488 }
8489
8490 boolean timedout = false;
8491
8492 synchronized(this) {
8493 mShuttingDown = true;
8494 mWindowManager.setEventDispatching(false);
8495
8496 if (mResumedActivity != null) {
8497 pauseIfSleepingLocked();
8498 final long endTime = System.currentTimeMillis() + timeout;
8499 while (mResumedActivity != null || mPausingActivity != null) {
8500 long delay = endTime - System.currentTimeMillis();
8501 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008502 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008503 timedout = true;
8504 break;
8505 }
8506 try {
8507 this.wait();
8508 } catch (InterruptedException e) {
8509 }
8510 }
8511 }
8512 }
8513
8514 mUsageStatsService.shutdown();
8515 mBatteryStatsService.shutdown();
8516
8517 return timedout;
8518 }
8519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008521 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 if (!mGoingToSleep.isHeld()) {
8523 mGoingToSleep.acquire();
8524 if (mLaunchingActivity.isHeld()) {
8525 mLaunchingActivity.release();
8526 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8527 }
8528 }
8529
8530 // If we are not currently pausing an activity, get the current
8531 // one to pause. If we are pausing one, we will just let that stuff
8532 // run and release the wake lock when all done.
8533 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008534 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8535 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008536 startPausingLocked(false, true);
8537 }
8538 }
8539 }
8540
8541 public void wakingUp() {
8542 synchronized(this) {
8543 if (mGoingToSleep.isHeld()) {
8544 mGoingToSleep.release();
8545 }
8546 mWindowManager.setEventDispatching(true);
8547 mSleeping = false;
8548 resumeTopActivityLocked(null);
8549 }
8550 }
8551
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008552 public void stopAppSwitches() {
8553 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8554 != PackageManager.PERMISSION_GRANTED) {
8555 throw new SecurityException("Requires permission "
8556 + android.Manifest.permission.STOP_APP_SWITCHES);
8557 }
8558
8559 synchronized(this) {
8560 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8561 + APP_SWITCH_DELAY_TIME;
8562 mDidAppSwitch = false;
8563 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8564 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8565 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8566 }
8567 }
8568
8569 public void resumeAppSwitches() {
8570 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8571 != PackageManager.PERMISSION_GRANTED) {
8572 throw new SecurityException("Requires permission "
8573 + android.Manifest.permission.STOP_APP_SWITCHES);
8574 }
8575
8576 synchronized(this) {
8577 // Note that we don't execute any pending app switches... we will
8578 // let those wait until either the timeout, or the next start
8579 // activity request.
8580 mAppSwitchesAllowedTime = 0;
8581 }
8582 }
8583
8584 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8585 String name) {
8586 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8587 return true;
8588 }
8589
8590 final int perm = checkComponentPermission(
8591 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8592 callingUid, -1);
8593 if (perm == PackageManager.PERMISSION_GRANTED) {
8594 return true;
8595 }
8596
Joe Onorato8a9b2202010-02-26 18:56:32 -08008597 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008598 return false;
8599 }
8600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008601 public void setDebugApp(String packageName, boolean waitForDebugger,
8602 boolean persistent) {
8603 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8604 "setDebugApp()");
8605
8606 // Note that this is not really thread safe if there are multiple
8607 // callers into it at the same time, but that's not a situation we
8608 // care about.
8609 if (persistent) {
8610 final ContentResolver resolver = mContext.getContentResolver();
8611 Settings.System.putString(
8612 resolver, Settings.System.DEBUG_APP,
8613 packageName);
8614 Settings.System.putInt(
8615 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8616 waitForDebugger ? 1 : 0);
8617 }
8618
8619 synchronized (this) {
8620 if (!persistent) {
8621 mOrigDebugApp = mDebugApp;
8622 mOrigWaitForDebugger = mWaitForDebugger;
8623 }
8624 mDebugApp = packageName;
8625 mWaitForDebugger = waitForDebugger;
8626 mDebugTransient = !persistent;
8627 if (packageName != null) {
8628 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008629 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008630 Binder.restoreCallingIdentity(origId);
8631 }
8632 }
8633 }
8634
8635 public void setAlwaysFinish(boolean enabled) {
8636 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8637 "setAlwaysFinish()");
8638
8639 Settings.System.putInt(
8640 mContext.getContentResolver(),
8641 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8642
8643 synchronized (this) {
8644 mAlwaysFinishActivities = enabled;
8645 }
8646 }
8647
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008648 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008650 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008651 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008652 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653 }
8654 }
8655
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008656 public boolean isUserAMonkey() {
8657 // For now the fact that there is a controller implies
8658 // we have a monkey.
8659 synchronized (this) {
8660 return mController != null;
8661 }
8662 }
8663
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008664 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008665 synchronized (this) {
8666 mWatchers.register(watcher);
8667 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008668 }
8669
8670 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008671 synchronized (this) {
8672 mWatchers.unregister(watcher);
8673 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008674 }
8675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008676 public final void enterSafeMode() {
8677 synchronized(this) {
8678 // It only makes sense to do this before the system is ready
8679 // and started launching other packages.
8680 if (!mSystemReady) {
8681 try {
8682 ActivityThread.getPackageManager().enterSafeMode();
8683 } catch (RemoteException e) {
8684 }
8685
8686 View v = LayoutInflater.from(mContext).inflate(
8687 com.android.internal.R.layout.safe_mode, null);
8688 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8689 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8690 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8691 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8692 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8693 lp.format = v.getBackground().getOpacity();
8694 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8695 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8696 ((WindowManager)mContext.getSystemService(
8697 Context.WINDOW_SERVICE)).addView(v, lp);
8698 }
8699 }
8700 }
8701
8702 public void noteWakeupAlarm(IIntentSender sender) {
8703 if (!(sender instanceof PendingIntentRecord)) {
8704 return;
8705 }
8706 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8707 synchronized (stats) {
8708 if (mBatteryStatsService.isOnBattery()) {
8709 mBatteryStatsService.enforceCallingPermission();
8710 PendingIntentRecord rec = (PendingIntentRecord)sender;
8711 int MY_UID = Binder.getCallingUid();
8712 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8713 BatteryStatsImpl.Uid.Pkg pkg =
8714 stats.getPackageStatsLocked(uid, rec.key.packageName);
8715 pkg.incWakeupsLocked();
8716 }
8717 }
8718 }
8719
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008720 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008721 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008722 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008723 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008724 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008725 // XXX Note: don't acquire main activity lock here, because the window
8726 // manager calls in with its locks held.
8727
8728 boolean killed = false;
8729 synchronized (mPidsSelfLocked) {
8730 int[] types = new int[pids.length];
8731 int worstType = 0;
8732 for (int i=0; i<pids.length; i++) {
8733 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8734 if (proc != null) {
8735 int type = proc.setAdj;
8736 types[i] = type;
8737 if (type > worstType) {
8738 worstType = type;
8739 }
8740 }
8741 }
8742
8743 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8744 // then constrain it so we will kill all hidden procs.
8745 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8746 worstType = HIDDEN_APP_MIN_ADJ;
8747 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008748 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749 for (int i=0; i<pids.length; i++) {
8750 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8751 if (proc == null) {
8752 continue;
8753 }
8754 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008755 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008756 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008757 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8758 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008760 proc.killedBackground = true;
8761 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008762 }
8763 }
8764 }
8765 return killed;
8766 }
8767
8768 public void reportPss(IApplicationThread caller, int pss) {
8769 Watchdog.PssRequestor req;
8770 String name;
8771 ProcessRecord callerApp;
8772 synchronized (this) {
8773 if (caller == null) {
8774 return;
8775 }
8776 callerApp = getRecordForAppLocked(caller);
8777 if (callerApp == null) {
8778 return;
8779 }
8780 callerApp.lastPss = pss;
8781 req = callerApp;
8782 name = callerApp.processName;
8783 }
8784 Watchdog.getInstance().reportPss(req, name, pss);
8785 if (!callerApp.persistent) {
8786 removeRequestedPss(callerApp);
8787 }
8788 }
8789
8790 public void requestPss(Runnable completeCallback) {
8791 ArrayList<ProcessRecord> procs;
8792 synchronized (this) {
8793 mRequestPssCallback = completeCallback;
8794 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008795 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8796 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008797 if (!proc.persistent) {
8798 mRequestPssList.add(proc);
8799 }
8800 }
8801 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8802 }
8803
8804 int oldPri = Process.getThreadPriority(Process.myTid());
8805 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8806 for (int i=procs.size()-1; i>=0; i--) {
8807 ProcessRecord proc = procs.get(i);
8808 proc.lastPss = 0;
8809 proc.requestPss();
8810 }
8811 Process.setThreadPriority(oldPri);
8812 }
8813
8814 void removeRequestedPss(ProcessRecord proc) {
8815 Runnable callback = null;
8816 synchronized (this) {
8817 if (mRequestPssList.remove(proc)) {
8818 if (mRequestPssList.size() == 0) {
8819 callback = mRequestPssCallback;
8820 mRequestPssCallback = null;
8821 }
8822 }
8823 }
8824
8825 if (callback != null) {
8826 callback.run();
8827 }
8828 }
8829
8830 public void collectPss(Watchdog.PssStats stats) {
8831 stats.mEmptyPss = 0;
8832 stats.mEmptyCount = 0;
8833 stats.mBackgroundPss = 0;
8834 stats.mBackgroundCount = 0;
8835 stats.mServicePss = 0;
8836 stats.mServiceCount = 0;
8837 stats.mVisiblePss = 0;
8838 stats.mVisibleCount = 0;
8839 stats.mForegroundPss = 0;
8840 stats.mForegroundCount = 0;
8841 stats.mNoPssCount = 0;
8842 synchronized (this) {
8843 int i;
8844 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8845 ? mProcDeaths.length : stats.mProcDeaths.length;
8846 int aggr = 0;
8847 for (i=0; i<NPD; i++) {
8848 aggr += mProcDeaths[i];
8849 stats.mProcDeaths[i] = aggr;
8850 }
8851 while (i<stats.mProcDeaths.length) {
8852 stats.mProcDeaths[i] = 0;
8853 i++;
8854 }
8855
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008856 for (i=mLruProcesses.size()-1; i>=0; i--) {
8857 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008858 if (proc.persistent) {
8859 continue;
8860 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008861 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008862 if (proc.lastPss == 0) {
8863 stats.mNoPssCount++;
8864 continue;
8865 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008866 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8867 if (proc.empty) {
8868 stats.mEmptyPss += proc.lastPss;
8869 stats.mEmptyCount++;
8870 } else {
8871 stats.mBackgroundPss += proc.lastPss;
8872 stats.mBackgroundCount++;
8873 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008874 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8875 stats.mVisiblePss += proc.lastPss;
8876 stats.mVisibleCount++;
8877 } else {
8878 stats.mForegroundPss += proc.lastPss;
8879 stats.mForegroundCount++;
8880 }
8881 }
8882 }
8883 }
8884
8885 public final void startRunning(String pkg, String cls, String action,
8886 String data) {
8887 synchronized(this) {
8888 if (mStartRunning) {
8889 return;
8890 }
8891 mStartRunning = true;
8892 mTopComponent = pkg != null && cls != null
8893 ? new ComponentName(pkg, cls) : null;
8894 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8895 mTopData = data;
8896 if (!mSystemReady) {
8897 return;
8898 }
8899 }
8900
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008901 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008902 }
8903
8904 private void retrieveSettings() {
8905 final ContentResolver resolver = mContext.getContentResolver();
8906 String debugApp = Settings.System.getString(
8907 resolver, Settings.System.DEBUG_APP);
8908 boolean waitForDebugger = Settings.System.getInt(
8909 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8910 boolean alwaysFinishActivities = Settings.System.getInt(
8911 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8912
8913 Configuration configuration = new Configuration();
8914 Settings.System.getConfiguration(resolver, configuration);
8915
8916 synchronized (this) {
8917 mDebugApp = mOrigDebugApp = debugApp;
8918 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8919 mAlwaysFinishActivities = alwaysFinishActivities;
8920 // This happens before any activities are started, so we can
8921 // change mConfiguration in-place.
8922 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008923 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008924 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008925 }
8926 }
8927
8928 public boolean testIsSystemReady() {
8929 // no need to synchronize(this) just to read & return the value
8930 return mSystemReady;
8931 }
8932
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008933 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008934 // In the simulator, startRunning will never have been called, which
8935 // normally sets a few crucial variables. Do it here instead.
8936 if (!Process.supportsProcesses()) {
8937 mStartRunning = true;
8938 mTopAction = Intent.ACTION_MAIN;
8939 }
8940
8941 synchronized(this) {
8942 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008943 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008944 return;
8945 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008946
8947 // Check to see if there are any update receivers to run.
8948 if (!mDidUpdate) {
8949 if (mWaitingUpdate) {
8950 return;
8951 }
8952 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8953 List<ResolveInfo> ris = null;
8954 try {
8955 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8956 intent, null, 0);
8957 } catch (RemoteException e) {
8958 }
8959 if (ris != null) {
8960 for (int i=ris.size()-1; i>=0; i--) {
8961 if ((ris.get(i).activityInfo.applicationInfo.flags
8962 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8963 ris.remove(i);
8964 }
8965 }
8966 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8967 for (int i=0; i<ris.size(); i++) {
8968 ActivityInfo ai = ris.get(i).activityInfo;
8969 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8970 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008971 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008972 finisher = new IIntentReceiver.Stub() {
8973 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07008974 String data, Bundle extras, boolean ordered,
8975 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008976 throws RemoteException {
8977 synchronized (ActivityManagerService.this) {
8978 mDidUpdate = true;
8979 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008980 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008981 }
8982 };
8983 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008984 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008985 broadcastIntentLocked(null, null, intent, null, finisher,
8986 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08008987 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008988 mWaitingUpdate = true;
8989 }
8990 }
8991 }
8992 if (mWaitingUpdate) {
8993 return;
8994 }
8995 mDidUpdate = true;
8996 }
8997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 mSystemReady = true;
8999 if (!mStartRunning) {
9000 return;
9001 }
9002 }
9003
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009004 ArrayList<ProcessRecord> procsToKill = null;
9005 synchronized(mPidsSelfLocked) {
9006 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
9007 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
9008 if (!isAllowedWhileBooting(proc.info)){
9009 if (procsToKill == null) {
9010 procsToKill = new ArrayList<ProcessRecord>();
9011 }
9012 procsToKill.add(proc);
9013 }
9014 }
9015 }
9016
9017 if (procsToKill != null) {
9018 synchronized(this) {
9019 for (int i=procsToKill.size()-1; i>=0; i--) {
9020 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009021 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009022 removeProcessLocked(proc, true);
9023 }
9024 }
9025 }
9026
Joe Onorato8a9b2202010-02-26 18:56:32 -08009027 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009028 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009029 SystemClock.uptimeMillis());
9030
9031 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009032 // Make sure we have no pre-ready processes sitting around.
9033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009034 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
9035 ResolveInfo ri = mContext.getPackageManager()
9036 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07009037 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009038 CharSequence errorMsg = null;
9039 if (ri != null) {
9040 ActivityInfo ai = ri.activityInfo;
9041 ApplicationInfo app = ai.applicationInfo;
9042 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
9043 mTopAction = Intent.ACTION_FACTORY_TEST;
9044 mTopData = null;
9045 mTopComponent = new ComponentName(app.packageName,
9046 ai.name);
9047 } else {
9048 errorMsg = mContext.getResources().getText(
9049 com.android.internal.R.string.factorytest_not_system);
9050 }
9051 } else {
9052 errorMsg = mContext.getResources().getText(
9053 com.android.internal.R.string.factorytest_no_action);
9054 }
9055 if (errorMsg != null) {
9056 mTopAction = null;
9057 mTopData = null;
9058 mTopComponent = null;
9059 Message msg = Message.obtain();
9060 msg.what = SHOW_FACTORY_ERROR_MSG;
9061 msg.getData().putCharSequence("msg", errorMsg);
9062 mHandler.sendMessage(msg);
9063 }
9064 }
9065 }
9066
9067 retrieveSettings();
9068
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009069 if (goingCallback != null) goingCallback.run();
9070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009071 synchronized (this) {
9072 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
9073 try {
9074 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009075 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009076 if (apps != null) {
9077 int N = apps.size();
9078 int i;
9079 for (i=0; i<N; i++) {
9080 ApplicationInfo info
9081 = (ApplicationInfo)apps.get(i);
9082 if (info != null &&
9083 !info.packageName.equals("android")) {
9084 addAppLocked(info);
9085 }
9086 }
9087 }
9088 } catch (RemoteException ex) {
9089 // pm is in same process, this will never happen.
9090 }
9091 }
9092
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009093 // Start up initial activity.
9094 mBooting = true;
9095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009096 try {
9097 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
9098 Message msg = Message.obtain();
9099 msg.what = SHOW_UID_ERROR_MSG;
9100 mHandler.sendMessage(msg);
9101 }
9102 } catch (RemoteException e) {
9103 }
9104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009105 resumeTopActivityLocked(null);
9106 }
9107 }
9108
Dan Egnorb7f03672009-12-09 16:22:32 -08009109 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009110 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009111 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009112 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009113 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009114 startAppProblemLocked(app);
9115 app.stopFreezingAllLocked();
9116 return handleAppCrashLocked(app);
9117 }
9118
Dan Egnorb7f03672009-12-09 16:22:32 -08009119 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009120 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009121 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009122 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009123 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
9124 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 startAppProblemLocked(app);
9126 app.stopFreezingAllLocked();
9127 }
9128
9129 /**
9130 * Generate a process error record, suitable for attachment to a ProcessRecord.
9131 *
9132 * @param app The ProcessRecord in which the error occurred.
9133 * @param condition Crashing, Application Not Responding, etc. Values are defined in
9134 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08009135 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009136 * @param shortMsg Short message describing the crash.
9137 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08009138 * @param stackTrace Full crash stack trace, may be null.
9139 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009140 * @return Returns a fully-formed AppErrorStateInfo record.
9141 */
9142 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009143 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009144 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08009145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009146 report.condition = condition;
9147 report.processName = app.processName;
9148 report.pid = app.pid;
9149 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08009150 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009151 report.shortMsg = shortMsg;
9152 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08009153 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009154
9155 return report;
9156 }
9157
Dan Egnor42471dd2010-01-07 17:25:22 -08009158 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009159 synchronized (this) {
9160 app.crashing = false;
9161 app.crashingReport = null;
9162 app.notResponding = false;
9163 app.notRespondingReport = null;
9164 if (app.anrDialog == fromDialog) {
9165 app.anrDialog = null;
9166 }
9167 if (app.waitDialog == fromDialog) {
9168 app.waitDialog = null;
9169 }
9170 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009171 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07009172 Slog.i(ActivityManagerService.TAG, "Killing "
9173 + app.processName + " (pid=" + app.pid + "): user's request");
9174 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
9175 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009176 Process.killProcess(app.pid);
9177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009178 }
9179 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009180
Dan Egnorb7f03672009-12-09 16:22:32 -08009181 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 long now = SystemClock.uptimeMillis();
9183
9184 Long crashTime = mProcessCrashTimes.get(app.info.processName,
9185 app.info.uid);
9186 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
9187 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08009188 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009190 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009191 app.info.processName, app.info.uid);
9192 killServicesLocked(app, false);
9193 for (int i=mHistory.size()-1; i>=0; i--) {
9194 HistoryRecord r = (HistoryRecord)mHistory.get(i);
9195 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009196 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009197 + r.intent.getComponent().flattenToShortString());
9198 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
9199 }
9200 }
9201 if (!app.persistent) {
9202 // We don't want to start this process again until the user
9203 // explicitly does so... but for persistent process, we really
9204 // need to keep it running. If a persistent process is actually
9205 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08009206 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009207 app.info.processName);
9208 mBadProcesses.put(app.info.processName, app.info.uid, now);
9209 app.bad = true;
9210 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
9211 app.removed = true;
9212 removeProcessLocked(app, false);
9213 return false;
9214 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009215 } else {
9216 HistoryRecord r = topRunningActivityLocked(null);
9217 if (r.app == app) {
9218 // If the top running activity is from this crashing
9219 // process, then terminate it to avoid getting in a loop.
9220 Slog.w(TAG, " Force finishing activity "
9221 + r.intent.getComponent().flattenToShortString());
9222 int index = indexOfTokenLocked(r);
9223 finishActivityLocked(r, index,
9224 Activity.RESULT_CANCELED, null, "crashed");
9225 // Also terminate an activities below it that aren't yet
9226 // stopped, to avoid a situation where one will get
9227 // re-start our crashing activity once it gets resumed again.
9228 index--;
9229 if (index >= 0) {
9230 r = (HistoryRecord)mHistory.get(index);
9231 if (r.state == ActivityState.RESUMED
9232 || r.state == ActivityState.PAUSING
9233 || r.state == ActivityState.PAUSED) {
9234 if (!r.isHomeActivity) {
9235 Slog.w(TAG, " Force finishing activity "
9236 + r.intent.getComponent().flattenToShortString());
9237 finishActivityLocked(r, index,
9238 Activity.RESULT_CANCELED, null, "crashed");
9239 }
9240 }
9241 }
9242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009243 }
9244
9245 // Bump up the crash count of any services currently running in the proc.
9246 if (app.services.size() != 0) {
9247 // Any services running in the application need to be placed
9248 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009249 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009251 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009252 sr.crashCount++;
9253 }
9254 }
9255
9256 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9257 return true;
9258 }
9259
9260 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009261 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9262 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009263 skipCurrentReceiverLocked(app);
9264 }
9265
9266 void skipCurrentReceiverLocked(ProcessRecord app) {
9267 boolean reschedule = false;
9268 BroadcastRecord r = app.curReceiver;
9269 if (r != null) {
9270 // The current broadcast is waiting for this app's receiver
9271 // to be finished. Looks like that's not going to happen, so
9272 // let the broadcast continue.
9273 logBroadcastReceiverDiscard(r);
9274 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9275 r.resultExtras, r.resultAbort, true);
9276 reschedule = true;
9277 }
9278 r = mPendingBroadcast;
9279 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009280 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009281 "skip & discard pending app " + r);
9282 logBroadcastReceiverDiscard(r);
9283 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9284 r.resultExtras, r.resultAbort, true);
9285 reschedule = true;
9286 }
9287 if (reschedule) {
9288 scheduleBroadcastsLocked();
9289 }
9290 }
9291
Dan Egnor60d87622009-12-16 16:32:58 -08009292 /**
9293 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9294 * The application process will exit immediately after this call returns.
9295 * @param app object of the crashing app, null for the system server
9296 * @param crashInfo describing the exception
9297 */
9298 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9299 ProcessRecord r = findAppProcess(app);
9300
9301 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9302 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009303 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009304 crashInfo.exceptionClassName,
9305 crashInfo.exceptionMessage,
9306 crashInfo.throwFileName,
9307 crashInfo.throwLineNumber);
9308
Dan Egnor42471dd2010-01-07 17:25:22 -08009309 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009310
9311 crashApplication(r, crashInfo);
9312 }
9313
9314 /**
9315 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9316 * @param app object of the crashing app, null for the system server
9317 * @param tag reported by the caller
9318 * @param crashInfo describing the context of the error
9319 * @return true if the process should exit immediately (WTF is fatal)
9320 */
9321 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009322 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009323 ProcessRecord r = findAppProcess(app);
9324
9325 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9326 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009327 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009328 tag, crashInfo.exceptionMessage);
9329
Dan Egnor42471dd2010-01-07 17:25:22 -08009330 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009331
Doug Zongker43866e02010-01-07 12:09:54 -08009332 if (Settings.Secure.getInt(mContext.getContentResolver(),
9333 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009334 crashApplication(r, crashInfo);
9335 return true;
9336 } else {
9337 return false;
9338 }
9339 }
9340
9341 /**
9342 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9343 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9344 */
9345 private ProcessRecord findAppProcess(IBinder app) {
9346 if (app == null) {
9347 return null;
9348 }
9349
9350 synchronized (this) {
9351 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9352 final int NA = apps.size();
9353 for (int ia=0; ia<NA; ia++) {
9354 ProcessRecord p = apps.valueAt(ia);
9355 if (p.thread != null && p.thread.asBinder() == app) {
9356 return p;
9357 }
9358 }
9359 }
9360
Joe Onorato8a9b2202010-02-26 18:56:32 -08009361 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009362 return null;
9363 }
9364 }
9365
9366 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009367 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009368 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009369 * @param process which caused the error, null means the system server
9370 * @param activity which triggered the error, null if unknown
9371 * @param parent activity related to the error, null if unknown
9372 * @param subject line related to the error, null if absent
9373 * @param report in long form describing the error, null if absent
9374 * @param logFile to include in the report, null if none
9375 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009376 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009377 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009378 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9379 final String report, final File logFile,
9380 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009381 // NOTE -- this must never acquire the ActivityManagerService lock,
9382 // otherwise the watchdog may be prevented from resetting the system.
9383
Dan Egnora455d192010-03-12 08:52:28 -08009384 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009385 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009386 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009387 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009388 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009389 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009390 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009391 }
9392
Dan Egnora455d192010-03-12 08:52:28 -08009393 final String dropboxTag = prefix + eventType;
9394 final DropBoxManager dbox = (DropBoxManager)
9395 mContext.getSystemService(Context.DROPBOX_SERVICE);
9396
9397 // Exit early if the dropbox isn't configured to accept this report type.
9398 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9399
9400 final StringBuilder sb = new StringBuilder(1024);
9401 if (process == null || process.pid == MY_PID) {
9402 sb.append("Process: system_server\n");
9403 } else {
9404 sb.append("Process: ").append(process.processName).append("\n");
9405 }
9406 if (process != null) {
9407 int flags = process.info.flags;
9408 IPackageManager pm = ActivityThread.getPackageManager();
9409 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9410 for (String pkg : process.pkgList) {
9411 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009412 try {
Dan Egnora455d192010-03-12 08:52:28 -08009413 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9414 if (pi != null) {
9415 sb.append(" v").append(pi.versionCode);
9416 if (pi.versionName != null) {
9417 sb.append(" (").append(pi.versionName).append(")");
9418 }
9419 }
9420 } catch (RemoteException e) {
9421 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009422 }
Dan Egnora455d192010-03-12 08:52:28 -08009423 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009424 }
Dan Egnora455d192010-03-12 08:52:28 -08009425 }
9426 if (activity != null) {
9427 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9428 }
9429 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9430 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9431 }
9432 if (parent != null && parent != activity) {
9433 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9434 }
9435 if (subject != null) {
9436 sb.append("Subject: ").append(subject).append("\n");
9437 }
9438 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9439 sb.append("\n");
9440
9441 // Do the rest in a worker thread to avoid blocking the caller on I/O
9442 // (After this point, we shouldn't access AMS internal data structures.)
9443 Thread worker = new Thread("Error dump: " + dropboxTag) {
9444 @Override
9445 public void run() {
9446 if (report != null) {
9447 sb.append(report);
9448 }
9449 if (logFile != null) {
9450 try {
9451 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9452 } catch (IOException e) {
9453 Slog.e(TAG, "Error reading " + logFile, e);
9454 }
9455 }
9456 if (crashInfo != null && crashInfo.stackTrace != null) {
9457 sb.append(crashInfo.stackTrace);
9458 }
9459
9460 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9461 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9462 if (lines > 0) {
9463 sb.append("\n");
9464
9465 // Merge several logcat streams, and take the last N lines
9466 InputStreamReader input = null;
9467 try {
9468 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9469 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9470 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9471
9472 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9473 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9474 input = new InputStreamReader(logcat.getInputStream());
9475
9476 int num;
9477 char[] buf = new char[8192];
9478 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9479 } catch (IOException e) {
9480 Slog.e(TAG, "Error running logcat", e);
9481 } finally {
9482 if (input != null) try { input.close(); } catch (IOException e) {}
9483 }
9484 }
9485
9486 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009487 }
Dan Egnora455d192010-03-12 08:52:28 -08009488 };
9489
9490 if (process == null || process.pid == MY_PID) {
9491 worker.run(); // We may be about to die -- need to run this synchronously
9492 } else {
9493 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009494 }
9495 }
9496
9497 /**
9498 * Bring up the "unexpected error" dialog box for a crashing app.
9499 * Deal with edge cases (intercepts from instrumented applications,
9500 * ActivityController, error intent receivers, that sort of thing).
9501 * @param r the application crashing
9502 * @param crashInfo describing the failure
9503 */
9504 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009505 long timeMillis = System.currentTimeMillis();
9506 String shortMsg = crashInfo.exceptionClassName;
9507 String longMsg = crashInfo.exceptionMessage;
9508 String stackTrace = crashInfo.stackTrace;
9509 if (shortMsg != null && longMsg != null) {
9510 longMsg = shortMsg + ": " + longMsg;
9511 } else if (shortMsg != null) {
9512 longMsg = shortMsg;
9513 }
9514
Dan Egnor60d87622009-12-16 16:32:58 -08009515 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009516 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009517 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009518 try {
9519 String name = r != null ? r.processName : null;
9520 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009521 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009522 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009523 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009524 + " at watcher's request");
9525 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009526 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009527 }
9528 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009529 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009530 }
9531 }
9532
9533 final long origId = Binder.clearCallingIdentity();
9534
9535 // If this process is running instrumentation, finish it.
9536 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009537 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009538 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009539 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9540 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009541 Bundle info = new Bundle();
9542 info.putString("shortMsg", shortMsg);
9543 info.putString("longMsg", longMsg);
9544 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9545 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009546 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009547 }
9548
Dan Egnor60d87622009-12-16 16:32:58 -08009549 // If we can't identify the process or it's already exceeded its crash quota,
9550 // quit right away without showing a crash dialog.
9551 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009552 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009553 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009554 }
9555
9556 Message msg = Message.obtain();
9557 msg.what = SHOW_ERROR_MSG;
9558 HashMap data = new HashMap();
9559 data.put("result", result);
9560 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009561 msg.obj = data;
9562 mHandler.sendMessage(msg);
9563
9564 Binder.restoreCallingIdentity(origId);
9565 }
9566
9567 int res = result.get();
9568
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009569 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009570 synchronized (this) {
9571 if (r != null) {
9572 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9573 SystemClock.uptimeMillis());
9574 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009575 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009576 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009577 }
9578 }
9579
9580 if (appErrorIntent != null) {
9581 try {
9582 mContext.startActivity(appErrorIntent);
9583 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009584 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009587 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009588
9589 Intent createAppErrorIntentLocked(ProcessRecord r,
9590 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9591 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009592 if (report == null) {
9593 return null;
9594 }
9595 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9596 result.setComponent(r.errorReportReceiver);
9597 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9598 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9599 return result;
9600 }
9601
Dan Egnorb7f03672009-12-09 16:22:32 -08009602 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9603 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009604 if (r.errorReportReceiver == null) {
9605 return null;
9606 }
9607
9608 if (!r.crashing && !r.notResponding) {
9609 return null;
9610 }
9611
Dan Egnorb7f03672009-12-09 16:22:32 -08009612 ApplicationErrorReport report = new ApplicationErrorReport();
9613 report.packageName = r.info.packageName;
9614 report.installerPackageName = r.errorReportReceiver.getPackageName();
9615 report.processName = r.processName;
9616 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009617 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009618
Dan Egnorb7f03672009-12-09 16:22:32 -08009619 if (r.crashing) {
9620 report.type = ApplicationErrorReport.TYPE_CRASH;
9621 report.crashInfo = crashInfo;
9622 } else if (r.notResponding) {
9623 report.type = ApplicationErrorReport.TYPE_ANR;
9624 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009625
Dan Egnorb7f03672009-12-09 16:22:32 -08009626 report.anrInfo.activity = r.notRespondingReport.tag;
9627 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9628 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009629 }
9630
Dan Egnorb7f03672009-12-09 16:22:32 -08009631 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009632 }
9633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009634 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9635 // assume our apps are happy - lazy create the list
9636 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9637
9638 synchronized (this) {
9639
9640 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009641 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9642 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9644 // This one's in trouble, so we'll generate a report for it
9645 // crashes are higher priority (in case there's a crash *and* an anr)
9646 ActivityManager.ProcessErrorStateInfo report = null;
9647 if (app.crashing) {
9648 report = app.crashingReport;
9649 } else if (app.notResponding) {
9650 report = app.notRespondingReport;
9651 }
9652
9653 if (report != null) {
9654 if (errList == null) {
9655 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9656 }
9657 errList.add(report);
9658 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009659 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009660 " crashing = " + app.crashing +
9661 " notResponding = " + app.notResponding);
9662 }
9663 }
9664 }
9665 }
9666
9667 return errList;
9668 }
9669
9670 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9671 // Lazy instantiation of list
9672 List<ActivityManager.RunningAppProcessInfo> runList = null;
9673 synchronized (this) {
9674 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009675 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9676 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009677 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9678 // Generate process state info for running application
9679 ActivityManager.RunningAppProcessInfo currApp =
9680 new ActivityManager.RunningAppProcessInfo(app.processName,
9681 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009682 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009684 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009685 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9686 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9687 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009688 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9689 } else if (adj >= HOME_APP_ADJ) {
9690 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9691 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692 } else if (adj >= SECONDARY_SERVER_ADJ) {
9693 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9694 } else if (adj >= VISIBLE_APP_ADJ) {
9695 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009696 } else if (app == mHeavyWeightProcess) {
9697 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698 } else {
9699 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9700 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009701 currApp.importanceReasonCode = app.adjTypeCode;
9702 if (app.adjSource instanceof ProcessRecord) {
9703 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9704 } else if (app.adjSource instanceof HistoryRecord) {
9705 HistoryRecord r = (HistoryRecord)app.adjSource;
9706 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9707 }
9708 if (app.adjTarget instanceof ComponentName) {
9709 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9710 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009711 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009712 // + " lru=" + currApp.lru);
9713 if (runList == null) {
9714 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9715 }
9716 runList.add(currApp);
9717 }
9718 }
9719 }
9720 return runList;
9721 }
9722
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009723 public List<ApplicationInfo> getRunningExternalApplications() {
9724 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9725 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9726 if (runningApps != null && runningApps.size() > 0) {
9727 Set<String> extList = new HashSet<String>();
9728 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9729 if (app.pkgList != null) {
9730 for (String pkg : app.pkgList) {
9731 extList.add(pkg);
9732 }
9733 }
9734 }
9735 IPackageManager pm = ActivityThread.getPackageManager();
9736 for (String pkg : extList) {
9737 try {
9738 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9739 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9740 retList.add(info);
9741 }
9742 } catch (RemoteException e) {
9743 }
9744 }
9745 }
9746 return retList;
9747 }
9748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009749 @Override
9750 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009751 if (checkCallingPermission(android.Manifest.permission.DUMP)
9752 != PackageManager.PERMISSION_GRANTED) {
9753 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9754 + Binder.getCallingPid()
9755 + ", uid=" + Binder.getCallingUid()
9756 + " without permission "
9757 + android.Manifest.permission.DUMP);
9758 return;
9759 }
9760
9761 boolean dumpAll = false;
9762
9763 int opti = 0;
9764 while (opti < args.length) {
9765 String opt = args[opti];
9766 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9767 break;
9768 }
9769 opti++;
9770 if ("-a".equals(opt)) {
9771 dumpAll = true;
9772 } else if ("-h".equals(opt)) {
9773 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009774 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009775 pw.println(" cmd may be one of:");
9776 pw.println(" activities: activity stack state");
9777 pw.println(" broadcasts: broadcast state");
9778 pw.println(" intents: pending intent state");
9779 pw.println(" processes: process state");
9780 pw.println(" providers: content provider state");
9781 pw.println(" services: service state");
9782 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009783 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009784 } else {
9785 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009786 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009787 }
9788
9789 // Is the caller requesting to dump a particular piece of data?
9790 if (opti < args.length) {
9791 String cmd = args[opti];
9792 opti++;
9793 if ("activities".equals(cmd) || "a".equals(cmd)) {
9794 synchronized (this) {
9795 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009796 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009797 return;
9798 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9799 synchronized (this) {
9800 dumpBroadcastsLocked(fd, pw, args, opti, true);
9801 }
9802 return;
9803 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9804 synchronized (this) {
9805 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9806 }
9807 return;
9808 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9809 synchronized (this) {
9810 dumpProcessesLocked(fd, pw, args, opti, true);
9811 }
9812 return;
9813 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9814 synchronized (this) {
9815 dumpProvidersLocked(fd, pw, args, opti, true);
9816 }
9817 return;
9818 } else if ("service".equals(cmd)) {
9819 dumpService(fd, pw, args, opti, true);
9820 return;
9821 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9822 synchronized (this) {
9823 dumpServicesLocked(fd, pw, args, opti, true);
9824 }
9825 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009826 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009827 }
9828
9829 // No piece of data specified, dump everything.
9830 synchronized (this) {
9831 boolean needSep;
9832 if (dumpAll) {
9833 pw.println("Providers in Current Activity Manager State:");
9834 }
9835 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9836 if (needSep) {
9837 pw.println(" ");
9838 }
9839 if (dumpAll) {
9840 pw.println("-------------------------------------------------------------------------------");
9841 pw.println("Broadcasts in Current Activity Manager State:");
9842 }
9843 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9844 if (needSep) {
9845 pw.println(" ");
9846 }
9847 if (dumpAll) {
9848 pw.println("-------------------------------------------------------------------------------");
9849 pw.println("Services in Current Activity Manager State:");
9850 }
9851 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9852 if (needSep) {
9853 pw.println(" ");
9854 }
9855 if (dumpAll) {
9856 pw.println("-------------------------------------------------------------------------------");
9857 pw.println("PendingIntents in Current Activity Manager State:");
9858 }
9859 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9860 if (needSep) {
9861 pw.println(" ");
9862 }
9863 if (dumpAll) {
9864 pw.println("-------------------------------------------------------------------------------");
9865 pw.println("Activities in Current Activity Manager State:");
9866 }
9867 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9868 if (needSep) {
9869 pw.println(" ");
9870 }
9871 if (dumpAll) {
9872 pw.println("-------------------------------------------------------------------------------");
9873 pw.println("Processes in Current Activity Manager State:");
9874 }
9875 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9876 }
9877 }
9878
9879 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9880 int opti, boolean dumpAll, boolean needHeader) {
9881 if (needHeader) {
9882 pw.println(" Activity stack:");
9883 }
9884 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9885 pw.println(" ");
9886 pw.println(" Running activities (most recent first):");
9887 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9888 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009889 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009890 pw.println(" Activities waiting for another to become visible:");
9891 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9892 }
9893 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009894 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009895 pw.println(" Activities waiting to stop:");
9896 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9897 }
9898 if (mFinishingActivities.size() > 0) {
9899 pw.println(" ");
9900 pw.println(" Activities waiting to finish:");
9901 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009904 pw.println(" ");
9905 pw.println(" mPausingActivity: " + mPausingActivity);
9906 pw.println(" mResumedActivity: " + mResumedActivity);
9907 pw.println(" mFocusedActivity: " + mFocusedActivity);
9908 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009909
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009910 if (dumpAll && mRecentTasks.size() > 0) {
9911 pw.println(" ");
9912 pw.println("Recent tasks in Current Activity Manager State:");
9913
9914 final int N = mRecentTasks.size();
9915 for (int i=0; i<N; i++) {
9916 TaskRecord tr = mRecentTasks.get(i);
9917 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9918 pw.println(tr);
9919 mRecentTasks.get(i).dump(pw, " ");
9920 }
9921 }
9922
9923 pw.println(" ");
9924 pw.println(" mCurTask: " + mCurTask);
9925
9926 return true;
9927 }
9928
9929 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9930 int opti, boolean dumpAll) {
9931 boolean needSep = false;
9932 int numPers = 0;
9933
9934 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009935 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9936 final int NA = procs.size();
9937 for (int ia=0; ia<NA; ia++) {
9938 if (!needSep) {
9939 pw.println(" All known processes:");
9940 needSep = true;
9941 }
9942 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009943 pw.print(r.persistent ? " *PERS*" : " *APP*");
9944 pw.print(" UID "); pw.print(procs.keyAt(ia));
9945 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009946 r.dump(pw, " ");
9947 if (r.persistent) {
9948 numPers++;
9949 }
9950 }
9951 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009952 }
9953
9954 if (mLruProcesses.size() > 0) {
9955 if (needSep) pw.println(" ");
9956 needSep = true;
9957 pw.println(" Running processes (most recent first):");
9958 dumpProcessList(pw, this, mLruProcesses, " ",
9959 "App ", "PERS", true);
9960 needSep = true;
9961 }
9962
9963 synchronized (mPidsSelfLocked) {
9964 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965 if (needSep) pw.println(" ");
9966 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009967 pw.println(" PID mappings:");
9968 for (int i=0; i<mPidsSelfLocked.size(); i++) {
9969 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
9970 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971 }
9972 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009973 }
9974
9975 if (mForegroundProcesses.size() > 0) {
9976 if (needSep) pw.println(" ");
9977 needSep = true;
9978 pw.println(" Foreground Processes:");
9979 for (int i=0; i<mForegroundProcesses.size(); i++) {
9980 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
9981 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009982 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009983 }
9984
9985 if (mPersistentStartingProcesses.size() > 0) {
9986 if (needSep) pw.println(" ");
9987 needSep = true;
9988 pw.println(" Persisent processes that are starting:");
9989 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
9990 "Starting Norm", "Restarting PERS", false);
9991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009993 if (mStartingProcesses.size() > 0) {
9994 if (needSep) pw.println(" ");
9995 needSep = true;
9996 pw.println(" Processes that are starting:");
9997 dumpProcessList(pw, this, mStartingProcesses, " ",
9998 "Starting Norm", "Starting PERS", false);
9999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010001 if (mRemovedProcesses.size() > 0) {
10002 if (needSep) pw.println(" ");
10003 needSep = true;
10004 pw.println(" Processes that are being removed:");
10005 dumpProcessList(pw, this, mRemovedProcesses, " ",
10006 "Removed Norm", "Removed PERS", false);
10007 }
10008
10009 if (mProcessesOnHold.size() > 0) {
10010 if (needSep) pw.println(" ");
10011 needSep = true;
10012 pw.println(" Processes that are on old until the system is ready:");
10013 dumpProcessList(pw, this, mProcessesOnHold, " ",
10014 "OnHold Norm", "OnHold PERS", false);
10015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010016
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010017 if (mProcessesToGc.size() > 0) {
10018 if (needSep) pw.println(" ");
10019 needSep = true;
10020 pw.println(" Processes that are waiting to GC:");
10021 long now = SystemClock.uptimeMillis();
10022 for (int i=0; i<mProcessesToGc.size(); i++) {
10023 ProcessRecord proc = mProcessesToGc.get(i);
10024 pw.print(" Process "); pw.println(proc);
10025 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
10026 pw.print(", last gced=");
10027 pw.print(now-proc.lastRequestedGc);
10028 pw.print(" ms ago, last lowMem=");
10029 pw.print(now-proc.lastLowMemory);
10030 pw.println(" ms ago");
10031
10032 }
10033 }
10034
10035 if (mProcessCrashTimes.getMap().size() > 0) {
10036 if (needSep) pw.println(" ");
10037 needSep = true;
10038 pw.println(" Time since processes crashed:");
10039 long now = SystemClock.uptimeMillis();
10040 for (Map.Entry<String, SparseArray<Long>> procs
10041 : mProcessCrashTimes.getMap().entrySet()) {
10042 SparseArray<Long> uids = procs.getValue();
10043 final int N = uids.size();
10044 for (int i=0; i<N; i++) {
10045 pw.print(" Process "); pw.print(procs.getKey());
10046 pw.print(" uid "); pw.print(uids.keyAt(i));
10047 pw.print(": last crashed ");
10048 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010049 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010050 }
10051 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010054 if (mBadProcesses.getMap().size() > 0) {
10055 if (needSep) pw.println(" ");
10056 needSep = true;
10057 pw.println(" Bad processes:");
10058 for (Map.Entry<String, SparseArray<Long>> procs
10059 : mBadProcesses.getMap().entrySet()) {
10060 SparseArray<Long> uids = procs.getValue();
10061 final int N = uids.size();
10062 for (int i=0; i<N; i++) {
10063 pw.print(" Bad process "); pw.print(procs.getKey());
10064 pw.print(" uid "); pw.print(uids.keyAt(i));
10065 pw.print(": crashed at time ");
10066 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010067 }
10068 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010070
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010071 pw.println(" ");
10072 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010073 if (mHeavyWeightProcess != null) {
10074 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
10075 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010076 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -070010077 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010078 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
10079 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
10080 || mOrigWaitForDebugger) {
10081 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
10082 + " mDebugTransient=" + mDebugTransient
10083 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
10084 }
10085 if (mAlwaysFinishActivities || mController != null) {
10086 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
10087 + " mController=" + mController);
10088 }
10089 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010090 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010091 pw.println(" mStartRunning=" + mStartRunning
10092 + " mSystemReady=" + mSystemReady
10093 + " mBooting=" + mBooting
10094 + " mBooted=" + mBooted
10095 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010096 pw.println(" mGoingToSleep=" + mGoingToSleep);
10097 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -070010098 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010100
10101 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010102 }
10103
10104 /**
10105 * There are three ways to call this:
10106 * - no service specified: dump all the services
10107 * - a flattened component name that matched an existing service was specified as the
10108 * first arg: dump that one service
10109 * - the first arg isn't the flattened component name of an existing service:
10110 * dump all services whose component contains the first arg as a substring
10111 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010112 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
10113 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 String[] newArgs;
10115 String componentNameString;
10116 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -080010117 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010118 componentNameString = null;
10119 newArgs = EMPTY_STRING_ARRAY;
10120 r = null;
10121 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010122 componentNameString = args[opti];
10123 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010124 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
10125 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010126 newArgs = new String[args.length - opti];
10127 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010128 }
10129
10130 if (r != null) {
10131 dumpService(fd, pw, r, newArgs);
10132 } else {
10133 for (ServiceRecord r1 : mServices.values()) {
10134 if (componentNameString == null
10135 || r1.name.flattenToString().contains(componentNameString)) {
10136 dumpService(fd, pw, r1, newArgs);
10137 }
10138 }
10139 }
10140 }
10141
10142 /**
10143 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
10144 * there is a thread associated with the service.
10145 */
10146 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
10147 pw.println(" Service " + r.name.flattenToString());
10148 if (r.app != null && r.app.thread != null) {
10149 try {
10150 // flush anything that is already in the PrintWriter since the thread is going
10151 // to write to the file descriptor directly
10152 pw.flush();
10153 r.app.thread.dumpService(fd, r, args);
10154 pw.print("\n");
10155 } catch (RemoteException e) {
10156 pw.println("got a RemoteException while dumping the service");
10157 }
10158 }
10159 }
10160
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010161 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10162 int opti, boolean dumpAll) {
10163 boolean needSep = false;
10164
10165 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010166 if (mRegisteredReceivers.size() > 0) {
10167 pw.println(" ");
10168 pw.println(" Registered Receivers:");
10169 Iterator it = mRegisteredReceivers.values().iterator();
10170 while (it.hasNext()) {
10171 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010172 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010173 r.dump(pw, " ");
10174 }
10175 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010177 pw.println(" ");
10178 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010179 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010180 needSep = true;
10181 }
10182
10183 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
10184 || mPendingBroadcast != null) {
10185 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010186 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010187 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010188 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010189 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10190 pw.println(" Broadcast #" + i + ":");
10191 mParallelBroadcasts.get(i).dump(pw, " ");
10192 }
10193 if (mOrderedBroadcasts.size() > 0) {
10194 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010195 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010196 }
10197 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10198 pw.println(" Serialized Broadcast #" + i + ":");
10199 mOrderedBroadcasts.get(i).dump(pw, " ");
10200 }
10201 pw.println(" ");
10202 pw.println(" Pending broadcast:");
10203 if (mPendingBroadcast != null) {
10204 mPendingBroadcast.dump(pw, " ");
10205 } else {
10206 pw.println(" (null)");
10207 }
10208 needSep = true;
10209 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010210
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010211 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010212 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -080010213 pw.println(" Historical broadcasts:");
10214 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
10215 BroadcastRecord r = mBroadcastHistory[i];
10216 if (r == null) {
10217 break;
10218 }
10219 pw.println(" Historical Broadcast #" + i + ":");
10220 r.dump(pw, " ");
10221 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010222 needSep = true;
10223 }
10224
10225 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010226 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010227 pw.println(" Sticky broadcasts:");
10228 StringBuilder sb = new StringBuilder(128);
10229 for (Map.Entry<String, ArrayList<Intent>> ent
10230 : mStickyBroadcasts.entrySet()) {
10231 pw.print(" * Sticky action "); pw.print(ent.getKey());
10232 pw.println(":");
10233 ArrayList<Intent> intents = ent.getValue();
10234 final int N = intents.size();
10235 for (int i=0; i<N; i++) {
10236 sb.setLength(0);
10237 sb.append(" Intent: ");
10238 intents.get(i).toShortString(sb, true, false);
10239 pw.println(sb.toString());
10240 Bundle bundle = intents.get(i).getExtras();
10241 if (bundle != null) {
10242 pw.print(" ");
10243 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010244 }
10245 }
10246 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010247 needSep = true;
10248 }
10249
10250 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010252 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010253 pw.println(" mHandler:");
10254 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010255 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010256 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010257
10258 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010259 }
10260
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010261 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10262 int opti, boolean dumpAll) {
10263 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010264
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010265 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 if (mServices.size() > 0) {
10267 pw.println(" Active services:");
10268 Iterator<ServiceRecord> it = mServices.values().iterator();
10269 while (it.hasNext()) {
10270 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010271 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010272 r.dump(pw, " ");
10273 }
10274 needSep = true;
10275 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010277
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010278 if (mPendingServices.size() > 0) {
10279 if (needSep) pw.println(" ");
10280 pw.println(" Pending services:");
10281 for (int i=0; i<mPendingServices.size(); i++) {
10282 ServiceRecord r = mPendingServices.get(i);
10283 pw.print(" * Pending "); pw.println(r);
10284 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010285 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010286 needSep = true;
10287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010288
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010289 if (mRestartingServices.size() > 0) {
10290 if (needSep) pw.println(" ");
10291 pw.println(" Restarting services:");
10292 for (int i=0; i<mRestartingServices.size(); i++) {
10293 ServiceRecord r = mRestartingServices.get(i);
10294 pw.print(" * Restarting "); pw.println(r);
10295 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010296 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010297 needSep = true;
10298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010300 if (mStoppingServices.size() > 0) {
10301 if (needSep) pw.println(" ");
10302 pw.println(" Stopping services:");
10303 for (int i=0; i<mStoppingServices.size(); i++) {
10304 ServiceRecord r = mStoppingServices.get(i);
10305 pw.print(" * Stopping "); pw.println(r);
10306 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010307 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010308 needSep = true;
10309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010310
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010311 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010312 if (mServiceConnections.size() > 0) {
10313 if (needSep) pw.println(" ");
10314 pw.println(" Connection bindings to services:");
10315 Iterator<ConnectionRecord> it
10316 = mServiceConnections.values().iterator();
10317 while (it.hasNext()) {
10318 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010319 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010320 r.dump(pw, " ");
10321 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010322 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010323 }
10324 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010325
10326 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327 }
10328
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010329 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10330 int opti, boolean dumpAll) {
10331 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010333 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010334 if (mProvidersByClass.size() > 0) {
10335 if (needSep) pw.println(" ");
10336 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010337 Iterator<Map.Entry<String, ContentProviderRecord>> it
10338 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010339 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010340 Map.Entry<String, ContentProviderRecord> e = it.next();
10341 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010342 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010343 r.dump(pw, " ");
10344 }
10345 needSep = true;
10346 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010347
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010348 if (mProvidersByName.size() > 0) {
10349 pw.println(" ");
10350 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010351 Iterator<Map.Entry<String, ContentProviderRecord>> it
10352 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010353 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010354 Map.Entry<String, ContentProviderRecord> e = it.next();
10355 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010356 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10357 pw.println(r);
10358 }
10359 needSep = true;
10360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010361 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010362
10363 if (mLaunchingProviders.size() > 0) {
10364 if (needSep) pw.println(" ");
10365 pw.println(" Launching content providers:");
10366 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10367 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10368 pw.println(mLaunchingProviders.get(i));
10369 }
10370 needSep = true;
10371 }
10372
10373 if (mGrantedUriPermissions.size() > 0) {
10374 pw.println();
10375 pw.println("Granted Uri Permissions:");
10376 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10377 int uid = mGrantedUriPermissions.keyAt(i);
10378 HashMap<Uri, UriPermission> perms
10379 = mGrantedUriPermissions.valueAt(i);
10380 pw.print(" * UID "); pw.print(uid);
10381 pw.println(" holds:");
10382 for (UriPermission perm : perms.values()) {
10383 pw.print(" "); pw.println(perm);
10384 perm.dump(pw, " ");
10385 }
10386 }
10387 needSep = true;
10388 }
10389
10390 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010391 }
10392
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010393 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10394 int opti, boolean dumpAll) {
10395 boolean needSep = false;
10396
10397 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010398 if (this.mIntentSenderRecords.size() > 0) {
10399 Iterator<WeakReference<PendingIntentRecord>> it
10400 = mIntentSenderRecords.values().iterator();
10401 while (it.hasNext()) {
10402 WeakReference<PendingIntentRecord> ref = it.next();
10403 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010404 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010405 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010406 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010407 rec.dump(pw, " ");
10408 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010409 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010410 }
10411 }
10412 }
10413 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010414
10415 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010416 }
10417
10418 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010419 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010420 TaskRecord lastTask = null;
10421 for (int i=list.size()-1; i>=0; i--) {
10422 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010423 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010424 if (lastTask != r.task) {
10425 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010426 pw.print(prefix);
10427 pw.print(full ? "* " : " ");
10428 pw.println(lastTask);
10429 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010430 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010432 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010433 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10434 pw.print(" #"); pw.print(i); pw.print(": ");
10435 pw.println(r);
10436 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010437 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010439 }
10440 }
10441
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010442 private static String buildOomTag(String prefix, String space, int val, int base) {
10443 if (val == base) {
10444 if (space == null) return prefix;
10445 return prefix + " ";
10446 }
10447 return prefix + "+" + Integer.toString(val-base);
10448 }
10449
10450 private static final int dumpProcessList(PrintWriter pw,
10451 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010452 String prefix, String normalLabel, String persistentLabel,
10453 boolean inclOomAdj) {
10454 int numPers = 0;
10455 for (int i=list.size()-1; i>=0; i--) {
10456 ProcessRecord r = (ProcessRecord)list.get(i);
10457 if (false) {
10458 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10459 + " #" + i + ":");
10460 r.dump(pw, prefix + " ");
10461 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010462 String oomAdj;
10463 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010464 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010465 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010466 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10467 } else if (r.setAdj >= HOME_APP_ADJ) {
10468 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10469 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10470 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10471 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10472 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10473 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10474 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10475 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10476 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010477 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010478 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010479 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010480 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010481 } else {
10482 oomAdj = Integer.toString(r.setAdj);
10483 }
10484 String schedGroup;
10485 switch (r.setSchedGroup) {
10486 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10487 schedGroup = "B";
10488 break;
10489 case Process.THREAD_GROUP_DEFAULT:
10490 schedGroup = "F";
10491 break;
10492 default:
10493 schedGroup = Integer.toString(r.setSchedGroup);
10494 break;
10495 }
10496 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010497 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010498 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010499 if (r.adjSource != null || r.adjTarget != null) {
10500 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010501 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010502 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010503 } else {
10504 pw.println(String.format("%s%s #%2d: %s",
10505 prefix, (r.persistent ? persistentLabel : normalLabel),
10506 i, r.toString()));
10507 }
10508 if (r.persistent) {
10509 numPers++;
10510 }
10511 }
10512 return numPers;
10513 }
10514
Dianne Hackborn472ad872010-04-07 17:31:48 -070010515 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010516 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010517 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010518 long uptime = SystemClock.uptimeMillis();
10519 long realtime = SystemClock.elapsedRealtime();
10520
10521 if (isCheckinRequest) {
10522 // short checkin version
10523 pw.println(uptime + "," + realtime);
10524 pw.flush();
10525 } else {
10526 pw.println("Applications Memory Usage (kB):");
10527 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10528 }
10529 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10530 ProcessRecord r = (ProcessRecord)list.get(i);
10531 if (r.thread != null) {
10532 if (!isCheckinRequest) {
10533 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10534 pw.flush();
10535 }
10536 try {
10537 r.thread.asBinder().dump(fd, args);
10538 } catch (RemoteException e) {
10539 if (!isCheckinRequest) {
10540 pw.println("Got RemoteException!");
10541 pw.flush();
10542 }
10543 }
10544 }
10545 }
10546 }
10547
10548 /**
10549 * Searches array of arguments for the specified string
10550 * @param args array of argument strings
10551 * @param value value to search for
10552 * @return true if the value is contained in the array
10553 */
10554 private static boolean scanArgs(String[] args, String value) {
10555 if (args != null) {
10556 for (String arg : args) {
10557 if (value.equals(arg)) {
10558 return true;
10559 }
10560 }
10561 }
10562 return false;
10563 }
10564
Dianne Hackborn75b03852009-06-12 15:43:26 -070010565 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010566 int count = mHistory.size();
10567
10568 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010569 int index = -1;
10570 for (int i=count-1; i>=0; i--) {
10571 Object o = mHistory.get(i);
10572 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010573 index = i;
10574 break;
10575 }
10576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010577
10578 return index;
10579 }
10580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 private final void killServicesLocked(ProcessRecord app,
10582 boolean allowRestart) {
10583 // Report disconnected services.
10584 if (false) {
10585 // XXX we are letting the client link to the service for
10586 // death notifications.
10587 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010588 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010589 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010590 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010591 if (r.connections.size() > 0) {
10592 Iterator<ConnectionRecord> jt
10593 = r.connections.values().iterator();
10594 while (jt.hasNext()) {
10595 ConnectionRecord c = jt.next();
10596 if (c.binding.client != app) {
10597 try {
10598 //c.conn.connected(r.className, null);
10599 } catch (Exception e) {
10600 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010601 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010602 + r.shortName
10603 + " from app " + app.processName, e);
10604 }
10605 }
10606 }
10607 }
10608 }
10609 }
10610 }
10611
10612 // Clean up any connections this application has to other services.
10613 if (app.connections.size() > 0) {
10614 Iterator<ConnectionRecord> it = app.connections.iterator();
10615 while (it.hasNext()) {
10616 ConnectionRecord r = it.next();
10617 removeConnectionLocked(r, app, null);
10618 }
10619 }
10620 app.connections.clear();
10621
10622 if (app.services.size() != 0) {
10623 // Any services running in the application need to be placed
10624 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010625 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010626 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010627 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010628 synchronized (sr.stats.getBatteryStats()) {
10629 sr.stats.stopLaunchedLocked();
10630 }
10631 sr.app = null;
10632 sr.executeNesting = 0;
10633 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010634
10635 boolean hasClients = sr.bindings.size() > 0;
10636 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010637 Iterator<IntentBindRecord> bindings
10638 = sr.bindings.values().iterator();
10639 while (bindings.hasNext()) {
10640 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010641 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010642 + ": shouldUnbind=" + b.hasBound);
10643 b.binder = null;
10644 b.requested = b.received = b.hasBound = false;
10645 }
10646 }
10647
10648 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010649 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010650 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010651 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 sr.crashCount, sr.shortName, app.pid);
10653 bringDownServiceLocked(sr, true);
10654 } else if (!allowRestart) {
10655 bringDownServiceLocked(sr, true);
10656 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010657 boolean canceled = scheduleServiceRestartLocked(sr, true);
10658
10659 // Should the service remain running? Note that in the
10660 // extreme case of so many attempts to deliver a command
10661 // that it failed, that we also will stop it here.
10662 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10663 if (sr.pendingStarts.size() == 0) {
10664 sr.startRequested = false;
10665 if (!hasClients) {
10666 // Whoops, no reason to restart!
10667 bringDownServiceLocked(sr, true);
10668 }
10669 }
10670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010671 }
10672 }
10673
10674 if (!allowRestart) {
10675 app.services.clear();
10676 }
10677 }
10678
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010679 // Make sure we have no more records on the stopping list.
10680 int i = mStoppingServices.size();
10681 while (i > 0) {
10682 i--;
10683 ServiceRecord sr = mStoppingServices.get(i);
10684 if (sr.app == app) {
10685 mStoppingServices.remove(i);
10686 }
10687 }
10688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010689 app.executingServices.clear();
10690 }
10691
10692 private final void removeDyingProviderLocked(ProcessRecord proc,
10693 ContentProviderRecord cpr) {
10694 synchronized (cpr) {
10695 cpr.launchingApp = null;
10696 cpr.notifyAll();
10697 }
10698
10699 mProvidersByClass.remove(cpr.info.name);
10700 String names[] = cpr.info.authority.split(";");
10701 for (int j = 0; j < names.length; j++) {
10702 mProvidersByName.remove(names[j]);
10703 }
10704
10705 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10706 while (cit.hasNext()) {
10707 ProcessRecord capp = cit.next();
10708 if (!capp.persistent && capp.thread != null
10709 && capp.pid != 0
10710 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010711 Slog.i(TAG, "Kill " + capp.processName
10712 + " (pid " + capp.pid + "): provider " + cpr.info.name
10713 + " in dying process " + proc.processName);
10714 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10715 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010716 Process.killProcess(capp.pid);
10717 }
10718 }
10719
10720 mLaunchingProviders.remove(cpr);
10721 }
10722
10723 /**
10724 * Main code for cleaning up a process when it has gone away. This is
10725 * called both as a result of the process dying, or directly when stopping
10726 * a process when running in single process mode.
10727 */
10728 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10729 boolean restarting, int index) {
10730 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010731 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010732 }
10733
Dianne Hackborn36124872009-10-08 16:22:03 -070010734 mProcessesToGc.remove(app);
10735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010736 // Dismiss any open dialogs.
10737 if (app.crashDialog != null) {
10738 app.crashDialog.dismiss();
10739 app.crashDialog = null;
10740 }
10741 if (app.anrDialog != null) {
10742 app.anrDialog.dismiss();
10743 app.anrDialog = null;
10744 }
10745 if (app.waitDialog != null) {
10746 app.waitDialog.dismiss();
10747 app.waitDialog = null;
10748 }
10749
10750 app.crashing = false;
10751 app.notResponding = false;
10752
10753 app.resetPackageList();
10754 app.thread = null;
10755 app.forcingToForeground = null;
10756 app.foregroundServices = false;
10757
10758 killServicesLocked(app, true);
10759
10760 boolean restart = false;
10761
10762 int NL = mLaunchingProviders.size();
10763
10764 // Remove published content providers.
10765 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010766 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010767 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010768 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 cpr.provider = null;
10770 cpr.app = null;
10771
10772 // See if someone is waiting for this provider... in which
10773 // case we don't remove it, but just let it restart.
10774 int i = 0;
10775 if (!app.bad) {
10776 for (; i<NL; i++) {
10777 if (mLaunchingProviders.get(i) == cpr) {
10778 restart = true;
10779 break;
10780 }
10781 }
10782 } else {
10783 i = NL;
10784 }
10785
10786 if (i >= NL) {
10787 removeDyingProviderLocked(app, cpr);
10788 NL = mLaunchingProviders.size();
10789 }
10790 }
10791 app.pubProviders.clear();
10792 }
10793
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010794 // Take care of any launching providers waiting for this process.
10795 if (checkAppInLaunchingProvidersLocked(app, false)) {
10796 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 // Unregister from connected content providers.
10800 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010801 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010802 while (it.hasNext()) {
10803 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10804 cpr.clients.remove(app);
10805 }
10806 app.conProviders.clear();
10807 }
10808
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010809 // At this point there may be remaining entries in mLaunchingProviders
10810 // where we were the only one waiting, so they are no longer of use.
10811 // Look for these and clean up if found.
10812 // XXX Commented out for now. Trying to figure out a way to reproduce
10813 // the actual situation to identify what is actually going on.
10814 if (false) {
10815 for (int i=0; i<NL; i++) {
10816 ContentProviderRecord cpr = (ContentProviderRecord)
10817 mLaunchingProviders.get(i);
10818 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10819 synchronized (cpr) {
10820 cpr.launchingApp = null;
10821 cpr.notifyAll();
10822 }
10823 }
10824 }
10825 }
10826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 skipCurrentReceiverLocked(app);
10828
10829 // Unregister any receivers.
10830 if (app.receivers.size() > 0) {
10831 Iterator<ReceiverList> it = app.receivers.iterator();
10832 while (it.hasNext()) {
10833 removeReceiverLocked(it.next());
10834 }
10835 app.receivers.clear();
10836 }
10837
Christopher Tate181fafa2009-05-14 11:12:14 -070010838 // If the app is undergoing backup, tell the backup manager about it
10839 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010840 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010841 try {
10842 IBackupManager bm = IBackupManager.Stub.asInterface(
10843 ServiceManager.getService(Context.BACKUP_SERVICE));
10844 bm.agentDisconnected(app.info.packageName);
10845 } catch (RemoteException e) {
10846 // can't happen; backup manager is local
10847 }
10848 }
10849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010850 // If the caller is restarting this app, then leave it in its
10851 // current lists and let the caller take care of it.
10852 if (restarting) {
10853 return;
10854 }
10855
10856 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010857 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010858 "Removing non-persistent process during cleanup: " + app);
10859 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010860 if (mHeavyWeightProcess == app) {
10861 mHeavyWeightProcess = null;
10862 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
10863 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 } else if (!app.removed) {
10865 // This app is persistent, so we need to keep its record around.
10866 // If it is not already on the pending app list, add it there
10867 // and start a new process for it.
10868 app.thread = null;
10869 app.forcingToForeground = null;
10870 app.foregroundServices = false;
10871 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10872 mPersistentStartingProcesses.add(app);
10873 restart = true;
10874 }
10875 }
10876 mProcessesOnHold.remove(app);
10877
The Android Open Source Project4df24232009-03-05 14:34:35 -080010878 if (app == mHomeProcess) {
10879 mHomeProcess = null;
10880 }
10881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882 if (restart) {
10883 // We have components that still need to be running in the
10884 // process, so re-launch it.
10885 mProcessNames.put(app.processName, app.info.uid, app);
10886 startProcessLocked(app, "restart", app.processName);
10887 } else if (app.pid > 0 && app.pid != MY_PID) {
10888 // Goodbye!
10889 synchronized (mPidsSelfLocked) {
10890 mPidsSelfLocked.remove(app.pid);
10891 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10892 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010893 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 }
10895 }
10896
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010897 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10898 // Look through the content providers we are waiting to have launched,
10899 // and if any run in this process then either schedule a restart of
10900 // the process or kill the client waiting for it if this process has
10901 // gone bad.
10902 int NL = mLaunchingProviders.size();
10903 boolean restart = false;
10904 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010905 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010906 if (cpr.launchingApp == app) {
10907 if (!alwaysBad && !app.bad) {
10908 restart = true;
10909 } else {
10910 removeDyingProviderLocked(app, cpr);
10911 NL = mLaunchingProviders.size();
10912 }
10913 }
10914 }
10915 return restart;
10916 }
10917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010918 // =========================================================
10919 // SERVICES
10920 // =========================================================
10921
10922 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10923 ActivityManager.RunningServiceInfo info =
10924 new ActivityManager.RunningServiceInfo();
10925 info.service = r.name;
10926 if (r.app != null) {
10927 info.pid = r.app.pid;
10928 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010929 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010930 info.process = r.processName;
10931 info.foreground = r.isForeground;
10932 info.activeSince = r.createTime;
10933 info.started = r.startRequested;
10934 info.clientCount = r.connections.size();
10935 info.crashCount = r.crashCount;
10936 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010937 if (r.isForeground) {
10938 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10939 }
10940 if (r.startRequested) {
10941 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10942 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010943 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010944 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10945 }
10946 if (r.app != null && r.app.persistent) {
10947 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10948 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010949 for (ConnectionRecord conn : r.connections.values()) {
10950 if (conn.clientLabel != 0) {
10951 info.clientPackage = conn.binding.client.info.packageName;
10952 info.clientLabel = conn.clientLabel;
10953 break;
10954 }
10955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010956 return info;
10957 }
10958
10959 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10960 int flags) {
10961 synchronized (this) {
10962 ArrayList<ActivityManager.RunningServiceInfo> res
10963 = new ArrayList<ActivityManager.RunningServiceInfo>();
10964
10965 if (mServices.size() > 0) {
10966 Iterator<ServiceRecord> it = mServices.values().iterator();
10967 while (it.hasNext() && res.size() < maxNum) {
10968 res.add(makeRunningServiceInfoLocked(it.next()));
10969 }
10970 }
10971
10972 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10973 ServiceRecord r = mRestartingServices.get(i);
10974 ActivityManager.RunningServiceInfo info =
10975 makeRunningServiceInfoLocked(r);
10976 info.restarting = r.nextRestartTime;
10977 res.add(info);
10978 }
10979
10980 return res;
10981 }
10982 }
10983
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010984 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10985 synchronized (this) {
10986 ServiceRecord r = mServices.get(name);
10987 if (r != null) {
10988 for (ConnectionRecord conn : r.connections.values()) {
10989 if (conn.clientIntent != null) {
10990 return conn.clientIntent;
10991 }
10992 }
10993 }
10994 }
10995 return null;
10996 }
10997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998 private final ServiceRecord findServiceLocked(ComponentName name,
10999 IBinder token) {
11000 ServiceRecord r = mServices.get(name);
11001 return r == token ? r : null;
11002 }
11003
11004 private final class ServiceLookupResult {
11005 final ServiceRecord record;
11006 final String permission;
11007
11008 ServiceLookupResult(ServiceRecord _record, String _permission) {
11009 record = _record;
11010 permission = _permission;
11011 }
11012 };
11013
11014 private ServiceLookupResult findServiceLocked(Intent service,
11015 String resolvedType) {
11016 ServiceRecord r = null;
11017 if (service.getComponent() != null) {
11018 r = mServices.get(service.getComponent());
11019 }
11020 if (r == null) {
11021 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11022 r = mServicesByIntent.get(filter);
11023 }
11024
11025 if (r == null) {
11026 try {
11027 ResolveInfo rInfo =
11028 ActivityThread.getPackageManager().resolveService(
11029 service, resolvedType, 0);
11030 ServiceInfo sInfo =
11031 rInfo != null ? rInfo.serviceInfo : null;
11032 if (sInfo == null) {
11033 return null;
11034 }
11035
11036 ComponentName name = new ComponentName(
11037 sInfo.applicationInfo.packageName, sInfo.name);
11038 r = mServices.get(name);
11039 } catch (RemoteException ex) {
11040 // pm is in same process, this will never happen.
11041 }
11042 }
11043 if (r != null) {
11044 int callingPid = Binder.getCallingPid();
11045 int callingUid = Binder.getCallingUid();
11046 if (checkComponentPermission(r.permission,
11047 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11048 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011049 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011050 + " from pid=" + callingPid
11051 + ", uid=" + callingUid
11052 + " requires " + r.permission);
11053 return new ServiceLookupResult(null, r.permission);
11054 }
11055 return new ServiceLookupResult(r, null);
11056 }
11057 return null;
11058 }
11059
11060 private class ServiceRestarter implements Runnable {
11061 private ServiceRecord mService;
11062
11063 void setService(ServiceRecord service) {
11064 mService = service;
11065 }
11066
11067 public void run() {
11068 synchronized(ActivityManagerService.this) {
11069 performServiceRestartLocked(mService);
11070 }
11071 }
11072 }
11073
11074 private ServiceLookupResult retrieveServiceLocked(Intent service,
11075 String resolvedType, int callingPid, int callingUid) {
11076 ServiceRecord r = null;
11077 if (service.getComponent() != null) {
11078 r = mServices.get(service.getComponent());
11079 }
11080 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11081 r = mServicesByIntent.get(filter);
11082 if (r == null) {
11083 try {
11084 ResolveInfo rInfo =
11085 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011086 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 ServiceInfo sInfo =
11088 rInfo != null ? rInfo.serviceInfo : null;
11089 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011090 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 ": not found");
11092 return null;
11093 }
11094
11095 ComponentName name = new ComponentName(
11096 sInfo.applicationInfo.packageName, sInfo.name);
11097 r = mServices.get(name);
11098 if (r == null) {
11099 filter = new Intent.FilterComparison(service.cloneFilter());
11100 ServiceRestarter res = new ServiceRestarter();
11101 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11102 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11103 synchronized (stats) {
11104 ss = stats.getServiceStatsLocked(
11105 sInfo.applicationInfo.uid, sInfo.packageName,
11106 sInfo.name);
11107 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080011108 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 res.setService(r);
11110 mServices.put(name, r);
11111 mServicesByIntent.put(filter, r);
11112
11113 // Make sure this component isn't in the pending list.
11114 int N = mPendingServices.size();
11115 for (int i=0; i<N; i++) {
11116 ServiceRecord pr = mPendingServices.get(i);
11117 if (pr.name.equals(name)) {
11118 mPendingServices.remove(i);
11119 i--;
11120 N--;
11121 }
11122 }
11123 }
11124 } catch (RemoteException ex) {
11125 // pm is in same process, this will never happen.
11126 }
11127 }
11128 if (r != null) {
11129 if (checkComponentPermission(r.permission,
11130 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11131 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011132 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011133 + " from pid=" + Binder.getCallingPid()
11134 + ", uid=" + Binder.getCallingUid()
11135 + " requires " + r.permission);
11136 return new ServiceLookupResult(null, r.permission);
11137 }
11138 return new ServiceLookupResult(r, null);
11139 }
11140 return null;
11141 }
11142
11143 private final void bumpServiceExecutingLocked(ServiceRecord r) {
11144 long now = SystemClock.uptimeMillis();
11145 if (r.executeNesting == 0 && r.app != null) {
11146 if (r.app.executingServices.size() == 0) {
11147 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11148 msg.obj = r.app;
11149 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
11150 }
11151 r.app.executingServices.add(r);
11152 }
11153 r.executeNesting++;
11154 r.executingStart = now;
11155 }
11156
11157 private final void sendServiceArgsLocked(ServiceRecord r,
11158 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011159 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011160 if (N == 0) {
11161 return;
11162 }
11163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 int i = 0;
11165 while (i < N) {
11166 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011167 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011168 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011169 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070011170 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011171 // If somehow we got a dummy start at the front, then
11172 // just drop it here.
11173 i++;
11174 continue;
11175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011176 bumpServiceExecutingLocked(r);
11177 if (!oomAdjusted) {
11178 oomAdjusted = true;
11179 updateOomAdjLocked(r.app);
11180 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011181 int flags = 0;
11182 if (si.deliveryCount > 0) {
11183 flags |= Service.START_FLAG_RETRY;
11184 }
11185 if (si.doneExecutingCount > 0) {
11186 flags |= Service.START_FLAG_REDELIVERY;
11187 }
11188 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
11189 si.deliveredTime = SystemClock.uptimeMillis();
11190 r.deliveredStarts.add(si);
11191 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011193 } catch (RemoteException e) {
11194 // Remote process gone... we'll let the normal cleanup take
11195 // care of this.
11196 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011197 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011198 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 break;
11200 }
11201 }
11202 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011203 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 } else {
11205 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011206 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011207 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011208 }
11209 }
11210 }
11211
11212 private final boolean requestServiceBindingLocked(ServiceRecord r,
11213 IntentBindRecord i, boolean rebind) {
11214 if (r.app == null || r.app.thread == null) {
11215 // If service is not currently running, can't yet bind.
11216 return false;
11217 }
11218 if ((!i.requested || rebind) && i.apps.size() > 0) {
11219 try {
11220 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011221 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011222 + ": shouldUnbind=" + i.hasBound);
11223 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11224 if (!rebind) {
11225 i.requested = true;
11226 }
11227 i.hasBound = true;
11228 i.doRebind = false;
11229 } catch (RemoteException e) {
11230 return false;
11231 }
11232 }
11233 return true;
11234 }
11235
11236 private final void requestServiceBindingsLocked(ServiceRecord r) {
11237 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11238 while (bindings.hasNext()) {
11239 IntentBindRecord i = bindings.next();
11240 if (!requestServiceBindingLocked(r, i, false)) {
11241 break;
11242 }
11243 }
11244 }
11245
11246 private final void realStartServiceLocked(ServiceRecord r,
11247 ProcessRecord app) throws RemoteException {
11248 if (app.thread == null) {
11249 throw new RemoteException();
11250 }
11251
11252 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011253 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254
11255 app.services.add(r);
11256 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011257 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258
11259 boolean created = false;
11260 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011261 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011263 mStringBuilder.setLength(0);
11264 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011265 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011267 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011268 synchronized (r.stats.getBatteryStats()) {
11269 r.stats.startLaunchedLocked();
11270 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011271 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011273 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 created = true;
11275 } finally {
11276 if (!created) {
11277 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011278 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011279 }
11280 }
11281
11282 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011283
11284 // If the service is in the started state, and there are no
11285 // pending arguments, then fake up one so its onStartCommand() will
11286 // be called.
11287 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11288 r.lastStartId++;
11289 if (r.lastStartId < 1) {
11290 r.lastStartId = 1;
11291 }
11292 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11293 }
11294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 sendServiceArgsLocked(r, true);
11296 }
11297
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011298 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11299 boolean allowCancel) {
11300 boolean canceled = false;
11301
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011302 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011303 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011304 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011305
11306 // Any delivered but not yet finished starts should be put back
11307 // on the pending list.
11308 final int N = r.deliveredStarts.size();
11309 if (N > 0) {
11310 for (int i=N-1; i>=0; i--) {
11311 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11312 if (si.intent == null) {
11313 // We'll generate this again if needed.
11314 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11315 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11316 r.pendingStarts.add(0, si);
11317 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11318 dur *= 2;
11319 if (minDuration < dur) minDuration = dur;
11320 if (resetTime < dur) resetTime = dur;
11321 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011322 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011323 + r.name);
11324 canceled = true;
11325 }
11326 }
11327 r.deliveredStarts.clear();
11328 }
11329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011330 r.totalRestartCount++;
11331 if (r.restartDelay == 0) {
11332 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011333 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334 } else {
11335 // If it has been a "reasonably long time" since the service
11336 // was started, then reset our restart duration back to
11337 // the beginning, so we don't infinitely increase the duration
11338 // on a service that just occasionally gets killed (which is
11339 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011340 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011342 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011343 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011344 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011345 if (r.restartDelay < minDuration) {
11346 r.restartDelay = minDuration;
11347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011348 }
11349 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011350
11351 r.nextRestartTime = now + r.restartDelay;
11352
11353 // Make sure that we don't end up restarting a bunch of services
11354 // all at the same time.
11355 boolean repeat;
11356 do {
11357 repeat = false;
11358 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11359 ServiceRecord r2 = mRestartingServices.get(i);
11360 if (r2 != r && r.nextRestartTime
11361 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11362 && r.nextRestartTime
11363 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11364 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11365 r.restartDelay = r.nextRestartTime - now;
11366 repeat = true;
11367 break;
11368 }
11369 }
11370 } while (repeat);
11371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011372 if (!mRestartingServices.contains(r)) {
11373 mRestartingServices.add(r);
11374 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011375
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011376 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011378 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011379 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011380 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011381 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011382 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011383 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384 r.shortName, r.restartDelay);
11385
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011386 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387 }
11388
11389 final void performServiceRestartLocked(ServiceRecord r) {
11390 if (!mRestartingServices.contains(r)) {
11391 return;
11392 }
11393 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11394 }
11395
11396 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11397 if (r.restartDelay == 0) {
11398 return false;
11399 }
11400 r.resetRestartCounter();
11401 mRestartingServices.remove(r);
11402 mHandler.removeCallbacks(r.restarter);
11403 return true;
11404 }
11405
11406 private final boolean bringUpServiceLocked(ServiceRecord r,
11407 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011408 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011409 //r.dump(" ");
11410
Dianne Hackborn36124872009-10-08 16:22:03 -070011411 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011412 sendServiceArgsLocked(r, false);
11413 return true;
11414 }
11415
11416 if (!whileRestarting && r.restartDelay > 0) {
11417 // If waiting for a restart, then do nothing.
11418 return true;
11419 }
11420
Joe Onorato8a9b2202010-02-26 18:56:32 -080011421 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011422 + " " + r.intent);
11423
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011424 // We are now bringing the service up, so no longer in the
11425 // restarting state.
11426 mRestartingServices.remove(r);
11427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011428 final String appName = r.processName;
11429 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11430 if (app != null && app.thread != null) {
11431 try {
11432 realStartServiceLocked(r, app);
11433 return true;
11434 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011435 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 }
11437
11438 // If a dead object exception was thrown -- fall through to
11439 // restart the application.
11440 }
11441
Dianne Hackborn36124872009-10-08 16:22:03 -070011442 // Not running -- get it started, and enqueue this service record
11443 // to be executed when the app comes up.
11444 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11445 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011446 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011447 + r.appInfo.packageName + "/"
11448 + r.appInfo.uid + " for service "
11449 + r.intent.getIntent() + ": process is bad");
11450 bringDownServiceLocked(r, true);
11451 return false;
11452 }
11453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011454 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011455 mPendingServices.add(r);
11456 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011458 return true;
11459 }
11460
11461 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011462 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011463 //r.dump(" ");
11464
11465 // Does it still need to run?
11466 if (!force && r.startRequested) {
11467 return;
11468 }
11469 if (r.connections.size() > 0) {
11470 if (!force) {
11471 // XXX should probably keep a count of the number of auto-create
11472 // connections directly in the service.
11473 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11474 while (it.hasNext()) {
11475 ConnectionRecord cr = it.next();
11476 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11477 return;
11478 }
11479 }
11480 }
11481
11482 // Report to all of the connections that the service is no longer
11483 // available.
11484 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11485 while (it.hasNext()) {
11486 ConnectionRecord c = it.next();
11487 try {
11488 // todo: shouldn't be a synchronous call!
11489 c.conn.connected(r.name, null);
11490 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011491 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011492 " to connection " + c.conn.asBinder() +
11493 " (in " + c.binding.client.processName + ")", e);
11494 }
11495 }
11496 }
11497
11498 // Tell the service that it has been unbound.
11499 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11500 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11501 while (it.hasNext()) {
11502 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011503 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011504 + ": hasBound=" + ibr.hasBound);
11505 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11506 try {
11507 bumpServiceExecutingLocked(r);
11508 updateOomAdjLocked(r.app);
11509 ibr.hasBound = false;
11510 r.app.thread.scheduleUnbindService(r,
11511 ibr.intent.getIntent());
11512 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011513 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011514 + r.shortName, e);
11515 serviceDoneExecutingLocked(r, true);
11516 }
11517 }
11518 }
11519 }
11520
Joe Onorato8a9b2202010-02-26 18:56:32 -080011521 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011522 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011523 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011524 System.identityHashCode(r), r.shortName,
11525 (r.app != null) ? r.app.pid : -1);
11526
11527 mServices.remove(r.name);
11528 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011529 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011530 r.totalRestartCount = 0;
11531 unscheduleServiceRestartLocked(r);
11532
11533 // Also make sure it is not on the pending list.
11534 int N = mPendingServices.size();
11535 for (int i=0; i<N; i++) {
11536 if (mPendingServices.get(i) == r) {
11537 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011538 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011539 TAG, "Removed pending service: " + r.shortName);
11540 i--;
11541 N--;
11542 }
11543 }
11544
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011545 r.cancelNotification();
11546 r.isForeground = false;
11547 r.foregroundId = 0;
11548 r.foregroundNoti = null;
11549
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011550 // Clear start entries.
11551 r.deliveredStarts.clear();
11552 r.pendingStarts.clear();
11553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011554 if (r.app != null) {
11555 synchronized (r.stats.getBatteryStats()) {
11556 r.stats.stopLaunchedLocked();
11557 }
11558 r.app.services.remove(r);
11559 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011560 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011561 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011562 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 bumpServiceExecutingLocked(r);
11564 mStoppingServices.add(r);
11565 updateOomAdjLocked(r.app);
11566 r.app.thread.scheduleStopService(r);
11567 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011568 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011569 + r.shortName, e);
11570 serviceDoneExecutingLocked(r, true);
11571 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011572 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011573 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011574 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011575 TAG, "Removed service that has no process: " + r.shortName);
11576 }
11577 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011578 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011579 TAG, "Removed service that is not running: " + r.shortName);
11580 }
11581 }
11582
11583 ComponentName startServiceLocked(IApplicationThread caller,
11584 Intent service, String resolvedType,
11585 int callingPid, int callingUid) {
11586 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011587 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 + " type=" + resolvedType + " args=" + service.getExtras());
11589
11590 if (caller != null) {
11591 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11592 if (callerApp == null) {
11593 throw new SecurityException(
11594 "Unable to find app for caller " + caller
11595 + " (pid=" + Binder.getCallingPid()
11596 + ") when starting service " + service);
11597 }
11598 }
11599
11600 ServiceLookupResult res =
11601 retrieveServiceLocked(service, resolvedType,
11602 callingPid, callingUid);
11603 if (res == null) {
11604 return null;
11605 }
11606 if (res.record == null) {
11607 return new ComponentName("!", res.permission != null
11608 ? res.permission : "private to package");
11609 }
11610 ServiceRecord r = res.record;
11611 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011612 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 + r.shortName);
11614 }
11615 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011616 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011617 r.lastStartId++;
11618 if (r.lastStartId < 1) {
11619 r.lastStartId = 1;
11620 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011621 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011622 r.lastActivity = SystemClock.uptimeMillis();
11623 synchronized (r.stats.getBatteryStats()) {
11624 r.stats.startRunningLocked();
11625 }
11626 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11627 return new ComponentName("!", "Service process is bad");
11628 }
11629 return r.name;
11630 }
11631 }
11632
11633 public ComponentName startService(IApplicationThread caller, Intent service,
11634 String resolvedType) {
11635 // Refuse possible leaked file descriptors
11636 if (service != null && service.hasFileDescriptors() == true) {
11637 throw new IllegalArgumentException("File descriptors passed in Intent");
11638 }
11639
11640 synchronized(this) {
11641 final int callingPid = Binder.getCallingPid();
11642 final int callingUid = Binder.getCallingUid();
11643 final long origId = Binder.clearCallingIdentity();
11644 ComponentName res = startServiceLocked(caller, service,
11645 resolvedType, callingPid, callingUid);
11646 Binder.restoreCallingIdentity(origId);
11647 return res;
11648 }
11649 }
11650
11651 ComponentName startServiceInPackage(int uid,
11652 Intent service, String resolvedType) {
11653 synchronized(this) {
11654 final long origId = Binder.clearCallingIdentity();
11655 ComponentName res = startServiceLocked(null, service,
11656 resolvedType, -1, uid);
11657 Binder.restoreCallingIdentity(origId);
11658 return res;
11659 }
11660 }
11661
11662 public int stopService(IApplicationThread caller, Intent service,
11663 String resolvedType) {
11664 // Refuse possible leaked file descriptors
11665 if (service != null && service.hasFileDescriptors() == true) {
11666 throw new IllegalArgumentException("File descriptors passed in Intent");
11667 }
11668
11669 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011670 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011671 + " type=" + resolvedType);
11672
11673 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11674 if (caller != null && callerApp == null) {
11675 throw new SecurityException(
11676 "Unable to find app for caller " + caller
11677 + " (pid=" + Binder.getCallingPid()
11678 + ") when stopping service " + service);
11679 }
11680
11681 // If this service is active, make sure it is stopped.
11682 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11683 if (r != null) {
11684 if (r.record != null) {
11685 synchronized (r.record.stats.getBatteryStats()) {
11686 r.record.stats.stopRunningLocked();
11687 }
11688 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011689 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011690 final long origId = Binder.clearCallingIdentity();
11691 bringDownServiceLocked(r.record, false);
11692 Binder.restoreCallingIdentity(origId);
11693 return 1;
11694 }
11695 return -1;
11696 }
11697 }
11698
11699 return 0;
11700 }
11701
11702 public IBinder peekService(Intent service, String resolvedType) {
11703 // Refuse possible leaked file descriptors
11704 if (service != null && service.hasFileDescriptors() == true) {
11705 throw new IllegalArgumentException("File descriptors passed in Intent");
11706 }
11707
11708 IBinder ret = null;
11709
11710 synchronized(this) {
11711 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11712
11713 if (r != null) {
11714 // r.record is null if findServiceLocked() failed the caller permission check
11715 if (r.record == null) {
11716 throw new SecurityException(
11717 "Permission Denial: Accessing service " + r.record.name
11718 + " from pid=" + Binder.getCallingPid()
11719 + ", uid=" + Binder.getCallingUid()
11720 + " requires " + r.permission);
11721 }
11722 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11723 if (ib != null) {
11724 ret = ib.binder;
11725 }
11726 }
11727 }
11728
11729 return ret;
11730 }
11731
11732 public boolean stopServiceToken(ComponentName className, IBinder token,
11733 int startId) {
11734 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011735 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011736 + " " + token + " startId=" + startId);
11737 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011738 if (r != null) {
11739 if (startId >= 0) {
11740 // Asked to only stop if done with all work. Note that
11741 // to avoid leaks, we will take this as dropping all
11742 // start items up to and including this one.
11743 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11744 if (si != null) {
11745 while (r.deliveredStarts.size() > 0) {
11746 if (r.deliveredStarts.remove(0) == si) {
11747 break;
11748 }
11749 }
11750 }
11751
11752 if (r.lastStartId != startId) {
11753 return false;
11754 }
11755
11756 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011757 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011758 + " is last, but have " + r.deliveredStarts.size()
11759 + " remaining args");
11760 }
11761 }
11762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 synchronized (r.stats.getBatteryStats()) {
11764 r.stats.stopRunningLocked();
11765 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011766 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011767 }
11768 final long origId = Binder.clearCallingIdentity();
11769 bringDownServiceLocked(r, false);
11770 Binder.restoreCallingIdentity(origId);
11771 return true;
11772 }
11773 }
11774 return false;
11775 }
11776
11777 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011778 int id, Notification notification, boolean removeNotification) {
11779 final long origId = Binder.clearCallingIdentity();
11780 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011781 synchronized(this) {
11782 ServiceRecord r = findServiceLocked(className, token);
11783 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011784 if (id != 0) {
11785 if (notification == null) {
11786 throw new IllegalArgumentException("null notification");
11787 }
11788 if (r.foregroundId != id) {
11789 r.cancelNotification();
11790 r.foregroundId = id;
11791 }
11792 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11793 r.foregroundNoti = notification;
11794 r.isForeground = true;
11795 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011796 if (r.app != null) {
11797 updateServiceForegroundLocked(r.app, true);
11798 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011799 } else {
11800 if (r.isForeground) {
11801 r.isForeground = false;
11802 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011803 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011804 updateServiceForegroundLocked(r.app, true);
11805 }
11806 }
11807 if (removeNotification) {
11808 r.cancelNotification();
11809 r.foregroundId = 0;
11810 r.foregroundNoti = null;
11811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011812 }
11813 }
11814 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011815 } finally {
11816 Binder.restoreCallingIdentity(origId);
11817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011818 }
11819
11820 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11821 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070011822 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011823 if (sr.isForeground) {
11824 anyForeground = true;
11825 break;
11826 }
11827 }
11828 if (anyForeground != proc.foregroundServices) {
11829 proc.foregroundServices = anyForeground;
11830 if (oomAdj) {
11831 updateOomAdjLocked();
11832 }
11833 }
11834 }
11835
11836 public int bindService(IApplicationThread caller, IBinder token,
11837 Intent service, String resolvedType,
11838 IServiceConnection connection, int flags) {
11839 // Refuse possible leaked file descriptors
11840 if (service != null && service.hasFileDescriptors() == true) {
11841 throw new IllegalArgumentException("File descriptors passed in Intent");
11842 }
11843
11844 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011845 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 + " type=" + resolvedType + " conn=" + connection.asBinder()
11847 + " flags=0x" + Integer.toHexString(flags));
11848 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11849 if (callerApp == null) {
11850 throw new SecurityException(
11851 "Unable to find app for caller " + caller
11852 + " (pid=" + Binder.getCallingPid()
11853 + ") when binding service " + service);
11854 }
11855
11856 HistoryRecord activity = null;
11857 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011858 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011859 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011860 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011861 return 0;
11862 }
11863 activity = (HistoryRecord)mHistory.get(aindex);
11864 }
11865
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011866 int clientLabel = 0;
11867 PendingIntent clientIntent = null;
11868
11869 if (callerApp.info.uid == Process.SYSTEM_UID) {
11870 // Hacky kind of thing -- allow system stuff to tell us
11871 // what they are, so we can report this elsewhere for
11872 // others to know why certain services are running.
11873 try {
11874 clientIntent = (PendingIntent)service.getParcelableExtra(
11875 Intent.EXTRA_CLIENT_INTENT);
11876 } catch (RuntimeException e) {
11877 }
11878 if (clientIntent != null) {
11879 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11880 if (clientLabel != 0) {
11881 // There are no useful extras in the intent, trash them.
11882 // System code calling with this stuff just needs to know
11883 // this will happen.
11884 service = service.cloneFilter();
11885 }
11886 }
11887 }
11888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011889 ServiceLookupResult res =
11890 retrieveServiceLocked(service, resolvedType,
11891 Binder.getCallingPid(), Binder.getCallingUid());
11892 if (res == null) {
11893 return 0;
11894 }
11895 if (res.record == null) {
11896 return -1;
11897 }
11898 ServiceRecord s = res.record;
11899
11900 final long origId = Binder.clearCallingIdentity();
11901
11902 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011903 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011904 + s.shortName);
11905 }
11906
11907 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11908 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011909 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910
11911 IBinder binder = connection.asBinder();
11912 s.connections.put(binder, c);
11913 b.connections.add(c);
11914 if (activity != null) {
11915 if (activity.connections == null) {
11916 activity.connections = new HashSet<ConnectionRecord>();
11917 }
11918 activity.connections.add(c);
11919 }
11920 b.client.connections.add(c);
11921 mServiceConnections.put(binder, c);
11922
11923 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11924 s.lastActivity = SystemClock.uptimeMillis();
11925 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11926 return 0;
11927 }
11928 }
11929
11930 if (s.app != null) {
11931 // This could have made the service more important.
11932 updateOomAdjLocked(s.app);
11933 }
11934
Joe Onorato8a9b2202010-02-26 18:56:32 -080011935 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011936 + ": received=" + b.intent.received
11937 + " apps=" + b.intent.apps.size()
11938 + " doRebind=" + b.intent.doRebind);
11939
11940 if (s.app != null && b.intent.received) {
11941 // Service is already running, so we can immediately
11942 // publish the connection.
11943 try {
11944 c.conn.connected(s.name, b.intent.binder);
11945 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011946 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011947 + " to connection " + c.conn.asBinder()
11948 + " (in " + c.binding.client.processName + ")", e);
11949 }
11950
11951 // If this is the first app connected back to this binding,
11952 // and the service had previously asked to be told when
11953 // rebound, then do so.
11954 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11955 requestServiceBindingLocked(s, b.intent, true);
11956 }
11957 } else if (!b.intent.requested) {
11958 requestServiceBindingLocked(s, b.intent, false);
11959 }
11960
11961 Binder.restoreCallingIdentity(origId);
11962 }
11963
11964 return 1;
11965 }
11966
11967 private void removeConnectionLocked(
11968 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
11969 IBinder binder = c.conn.asBinder();
11970 AppBindRecord b = c.binding;
11971 ServiceRecord s = b.service;
11972 s.connections.remove(binder);
11973 b.connections.remove(c);
11974 if (c.activity != null && c.activity != skipAct) {
11975 if (c.activity.connections != null) {
11976 c.activity.connections.remove(c);
11977 }
11978 }
11979 if (b.client != skipApp) {
11980 b.client.connections.remove(c);
11981 }
11982 mServiceConnections.remove(binder);
11983
11984 if (b.connections.size() == 0) {
11985 b.intent.apps.remove(b.client);
11986 }
11987
Joe Onorato8a9b2202010-02-26 18:56:32 -080011988 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011989 + ": shouldUnbind=" + b.intent.hasBound);
11990 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11991 && b.intent.hasBound) {
11992 try {
11993 bumpServiceExecutingLocked(s);
11994 updateOomAdjLocked(s.app);
11995 b.intent.hasBound = false;
11996 // Assume the client doesn't want to know about a rebind;
11997 // we will deal with that later if it asks for one.
11998 b.intent.doRebind = false;
11999 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
12000 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012001 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012002 serviceDoneExecutingLocked(s, true);
12003 }
12004 }
12005
12006 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
12007 bringDownServiceLocked(s, false);
12008 }
12009 }
12010
12011 public boolean unbindService(IServiceConnection connection) {
12012 synchronized (this) {
12013 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012014 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012015 ConnectionRecord r = mServiceConnections.get(binder);
12016 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012017 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012018 + connection.asBinder());
12019 return false;
12020 }
12021
12022 final long origId = Binder.clearCallingIdentity();
12023
12024 removeConnectionLocked(r, null, null);
12025
12026 if (r.binding.service.app != null) {
12027 // This could have made the service less important.
12028 updateOomAdjLocked(r.binding.service.app);
12029 }
12030
12031 Binder.restoreCallingIdentity(origId);
12032 }
12033
12034 return true;
12035 }
12036
12037 public void publishService(IBinder token, Intent intent, IBinder service) {
12038 // Refuse possible leaked file descriptors
12039 if (intent != null && intent.hasFileDescriptors() == true) {
12040 throw new IllegalArgumentException("File descriptors passed in Intent");
12041 }
12042
12043 synchronized(this) {
12044 if (!(token instanceof ServiceRecord)) {
12045 throw new IllegalArgumentException("Invalid service token");
12046 }
12047 ServiceRecord r = (ServiceRecord)token;
12048
12049 final long origId = Binder.clearCallingIdentity();
12050
Joe Onorato8a9b2202010-02-26 18:56:32 -080012051 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012052 + " " + intent + ": " + service);
12053 if (r != null) {
12054 Intent.FilterComparison filter
12055 = new Intent.FilterComparison(intent);
12056 IntentBindRecord b = r.bindings.get(filter);
12057 if (b != null && !b.received) {
12058 b.binder = service;
12059 b.requested = true;
12060 b.received = true;
12061 if (r.connections.size() > 0) {
12062 Iterator<ConnectionRecord> it
12063 = r.connections.values().iterator();
12064 while (it.hasNext()) {
12065 ConnectionRecord c = it.next();
12066 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012067 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012068 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012069 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012070 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012071 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012072 TAG, "Published intent: " + intent);
12073 continue;
12074 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012075 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012076 try {
12077 c.conn.connected(r.name, service);
12078 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012079 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012080 " to connection " + c.conn.asBinder() +
12081 " (in " + c.binding.client.processName + ")", e);
12082 }
12083 }
12084 }
12085 }
12086
12087 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12088
12089 Binder.restoreCallingIdentity(origId);
12090 }
12091 }
12092 }
12093
12094 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
12095 // Refuse possible leaked file descriptors
12096 if (intent != null && intent.hasFileDescriptors() == true) {
12097 throw new IllegalArgumentException("File descriptors passed in Intent");
12098 }
12099
12100 synchronized(this) {
12101 if (!(token instanceof ServiceRecord)) {
12102 throw new IllegalArgumentException("Invalid service token");
12103 }
12104 ServiceRecord r = (ServiceRecord)token;
12105
12106 final long origId = Binder.clearCallingIdentity();
12107
12108 if (r != null) {
12109 Intent.FilterComparison filter
12110 = new Intent.FilterComparison(intent);
12111 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012112 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012113 + " at " + b + ": apps="
12114 + (b != null ? b.apps.size() : 0));
12115 if (b != null) {
12116 if (b.apps.size() > 0) {
12117 // Applications have already bound since the last
12118 // unbind, so just rebind right here.
12119 requestServiceBindingLocked(r, b, true);
12120 } else {
12121 // Note to tell the service the next time there is
12122 // a new client.
12123 b.doRebind = true;
12124 }
12125 }
12126
12127 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12128
12129 Binder.restoreCallingIdentity(origId);
12130 }
12131 }
12132 }
12133
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012134 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012135 synchronized(this) {
12136 if (!(token instanceof ServiceRecord)) {
12137 throw new IllegalArgumentException("Invalid service token");
12138 }
12139 ServiceRecord r = (ServiceRecord)token;
12140 boolean inStopping = mStoppingServices.contains(token);
12141 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012142 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012143 + ": nesting=" + r.executeNesting
12144 + ", inStopping=" + inStopping);
12145 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012146 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012147 + " with incorrect token: given " + token
12148 + ", expected " + r);
12149 return;
12150 }
12151
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012152 if (type == 1) {
12153 // This is a call from a service start... take care of
12154 // book-keeping.
12155 r.callStart = true;
12156 switch (res) {
12157 case Service.START_STICKY_COMPATIBILITY:
12158 case Service.START_STICKY: {
12159 // We are done with the associated start arguments.
12160 r.findDeliveredStart(startId, true);
12161 // Don't stop if killed.
12162 r.stopIfKilled = false;
12163 break;
12164 }
12165 case Service.START_NOT_STICKY: {
12166 // We are done with the associated start arguments.
12167 r.findDeliveredStart(startId, true);
12168 if (r.lastStartId == startId) {
12169 // There is no more work, and this service
12170 // doesn't want to hang around if killed.
12171 r.stopIfKilled = true;
12172 }
12173 break;
12174 }
12175 case Service.START_REDELIVER_INTENT: {
12176 // We'll keep this item until they explicitly
12177 // call stop for it, but keep track of the fact
12178 // that it was delivered.
12179 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12180 if (si != null) {
12181 si.deliveryCount = 0;
12182 si.doneExecutingCount++;
12183 // Don't stop if killed.
12184 r.stopIfKilled = true;
12185 }
12186 break;
12187 }
12188 default:
12189 throw new IllegalArgumentException(
12190 "Unknown service start result: " + res);
12191 }
12192 if (res == Service.START_STICKY_COMPATIBILITY) {
12193 r.callStart = false;
12194 }
12195 }
12196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012197 final long origId = Binder.clearCallingIdentity();
12198 serviceDoneExecutingLocked(r, inStopping);
12199 Binder.restoreCallingIdentity(origId);
12200 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012201 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012202 + " with token " + token);
12203 }
12204 }
12205 }
12206
12207 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
12208 r.executeNesting--;
12209 if (r.executeNesting <= 0 && r.app != null) {
12210 r.app.executingServices.remove(r);
12211 if (r.app.executingServices.size() == 0) {
12212 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12213 }
12214 if (inStopping) {
12215 mStoppingServices.remove(r);
12216 }
12217 updateOomAdjLocked(r.app);
12218 }
12219 }
12220
12221 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012222 String anrMessage = null;
12223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012224 synchronized(this) {
12225 if (proc.executingServices.size() == 0 || proc.thread == null) {
12226 return;
12227 }
12228 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12229 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12230 ServiceRecord timeout = null;
12231 long nextTime = 0;
12232 while (it.hasNext()) {
12233 ServiceRecord sr = it.next();
12234 if (sr.executingStart < maxTime) {
12235 timeout = sr;
12236 break;
12237 }
12238 if (sr.executingStart > nextTime) {
12239 nextTime = sr.executingStart;
12240 }
12241 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012242 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012243 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012244 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012245 } else {
12246 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12247 msg.obj = proc;
12248 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12249 }
12250 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012251
12252 if (anrMessage != null) {
12253 appNotResponding(proc, null, null, anrMessage);
12254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012255 }
12256
12257 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012258 // BACKUP AND RESTORE
12259 // =========================================================
12260
12261 // Cause the target app to be launched if necessary and its backup agent
12262 // instantiated. The backup agent will invoke backupAgentCreated() on the
12263 // activity manager to announce its creation.
12264 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012265 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012266 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12267
12268 synchronized(this) {
12269 // !!! TODO: currently no check here that we're already bound
12270 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12271 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12272 synchronized (stats) {
12273 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12274 }
12275
12276 BackupRecord r = new BackupRecord(ss, app, backupMode);
12277 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12278 // startProcessLocked() returns existing proc's record if it's already running
12279 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012280 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012281 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012282 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012283 return false;
12284 }
12285
12286 r.app = proc;
12287 mBackupTarget = r;
12288 mBackupAppName = app.packageName;
12289
Christopher Tate6fa95972009-06-05 18:43:55 -070012290 // Try not to kill the process during backup
12291 updateOomAdjLocked(proc);
12292
Christopher Tate181fafa2009-05-14 11:12:14 -070012293 // If the process is already attached, schedule the creation of the backup agent now.
12294 // If it is not yet live, this will be done when it attaches to the framework.
12295 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012296 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012297 try {
12298 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12299 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012300 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012301 }
12302 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012303 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012304 }
12305 // Invariants: at this point, the target app process exists and the application
12306 // is either already running or in the process of coming up. mBackupTarget and
12307 // mBackupAppName describe the app, so that when it binds back to the AM we
12308 // know that it's scheduled for a backup-agent operation.
12309 }
12310
12311 return true;
12312 }
12313
12314 // A backup agent has just come up
12315 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012316 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012317 + " = " + agent);
12318
12319 synchronized(this) {
12320 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012321 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012322 return;
12323 }
12324
Christopher Tate043dadc2009-06-02 16:11:00 -070012325 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012326 try {
12327 IBackupManager bm = IBackupManager.Stub.asInterface(
12328 ServiceManager.getService(Context.BACKUP_SERVICE));
12329 bm.agentConnected(agentPackageName, agent);
12330 } catch (RemoteException e) {
12331 // can't happen; the backup manager service is local
12332 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012333 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012334 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012335 } finally {
12336 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012337 }
12338 }
12339 }
12340
12341 // done with this agent
12342 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012343 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012344 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012345 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012346 return;
12347 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012348
12349 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012350 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012351 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012352 return;
12353 }
12354
Christopher Tate181fafa2009-05-14 11:12:14 -070012355 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012356 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012357 return;
12358 }
12359
Christopher Tate6fa95972009-06-05 18:43:55 -070012360 ProcessRecord proc = mBackupTarget.app;
12361 mBackupTarget = null;
12362 mBackupAppName = null;
12363
12364 // Not backing this app up any more; reset its OOM adjustment
12365 updateOomAdjLocked(proc);
12366
Christopher Tatec7b31e32009-06-10 15:49:30 -070012367 // If the app crashed during backup, 'thread' will be null here
12368 if (proc.thread != null) {
12369 try {
12370 proc.thread.scheduleDestroyBackupAgent(appInfo);
12371 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012372 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012373 e.printStackTrace();
12374 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012375 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012376 }
12377 }
12378 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012379 // BROADCASTS
12380 // =========================================================
12381
Josh Bartel7f208742010-02-25 11:01:44 -060012382 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012383 List cur) {
12384 final ContentResolver resolver = mContext.getContentResolver();
12385 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12386 if (list == null) {
12387 return cur;
12388 }
12389 int N = list.size();
12390 for (int i=0; i<N; i++) {
12391 Intent intent = list.get(i);
12392 if (filter.match(resolver, intent, true, TAG) >= 0) {
12393 if (cur == null) {
12394 cur = new ArrayList<Intent>();
12395 }
12396 cur.add(intent);
12397 }
12398 }
12399 return cur;
12400 }
12401
12402 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012403 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012404 + mBroadcastsScheduled);
12405
12406 if (mBroadcastsScheduled) {
12407 return;
12408 }
12409 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12410 mBroadcastsScheduled = true;
12411 }
12412
12413 public Intent registerReceiver(IApplicationThread caller,
12414 IIntentReceiver receiver, IntentFilter filter, String permission) {
12415 synchronized(this) {
12416 ProcessRecord callerApp = null;
12417 if (caller != null) {
12418 callerApp = getRecordForAppLocked(caller);
12419 if (callerApp == null) {
12420 throw new SecurityException(
12421 "Unable to find app for caller " + caller
12422 + " (pid=" + Binder.getCallingPid()
12423 + ") when registering receiver " + receiver);
12424 }
12425 }
12426
12427 List allSticky = null;
12428
12429 // Look for any matching sticky broadcasts...
12430 Iterator actions = filter.actionsIterator();
12431 if (actions != null) {
12432 while (actions.hasNext()) {
12433 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012434 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012435 }
12436 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012437 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012438 }
12439
12440 // The first sticky in the list is returned directly back to
12441 // the client.
12442 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12443
Joe Onorato8a9b2202010-02-26 18:56:32 -080012444 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012445 + ": " + sticky);
12446
12447 if (receiver == null) {
12448 return sticky;
12449 }
12450
12451 ReceiverList rl
12452 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12453 if (rl == null) {
12454 rl = new ReceiverList(this, callerApp,
12455 Binder.getCallingPid(),
12456 Binder.getCallingUid(), receiver);
12457 if (rl.app != null) {
12458 rl.app.receivers.add(rl);
12459 } else {
12460 try {
12461 receiver.asBinder().linkToDeath(rl, 0);
12462 } catch (RemoteException e) {
12463 return sticky;
12464 }
12465 rl.linkedToDeath = true;
12466 }
12467 mRegisteredReceivers.put(receiver.asBinder(), rl);
12468 }
12469 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12470 rl.add(bf);
12471 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012472 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012473 }
12474 mReceiverResolver.addFilter(bf);
12475
12476 // Enqueue broadcasts for all existing stickies that match
12477 // this filter.
12478 if (allSticky != null) {
12479 ArrayList receivers = new ArrayList();
12480 receivers.add(bf);
12481
12482 int N = allSticky.size();
12483 for (int i=0; i<N; i++) {
12484 Intent intent = (Intent)allSticky.get(i);
12485 BroadcastRecord r = new BroadcastRecord(intent, null,
12486 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012487 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012488 if (mParallelBroadcasts.size() == 0) {
12489 scheduleBroadcastsLocked();
12490 }
12491 mParallelBroadcasts.add(r);
12492 }
12493 }
12494
12495 return sticky;
12496 }
12497 }
12498
12499 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012500 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012501
12502 boolean doNext = false;
12503
12504 synchronized(this) {
12505 ReceiverList rl
12506 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12507 if (rl != null) {
12508 if (rl.curBroadcast != null) {
12509 BroadcastRecord r = rl.curBroadcast;
12510 doNext = finishReceiverLocked(
12511 receiver.asBinder(), r.resultCode, r.resultData,
12512 r.resultExtras, r.resultAbort, true);
12513 }
12514
12515 if (rl.app != null) {
12516 rl.app.receivers.remove(rl);
12517 }
12518 removeReceiverLocked(rl);
12519 if (rl.linkedToDeath) {
12520 rl.linkedToDeath = false;
12521 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12522 }
12523 }
12524 }
12525
12526 if (!doNext) {
12527 return;
12528 }
12529
12530 final long origId = Binder.clearCallingIdentity();
12531 processNextBroadcast(false);
12532 trimApplications();
12533 Binder.restoreCallingIdentity(origId);
12534 }
12535
12536 void removeReceiverLocked(ReceiverList rl) {
12537 mRegisteredReceivers.remove(rl.receiver.asBinder());
12538 int N = rl.size();
12539 for (int i=0; i<N; i++) {
12540 mReceiverResolver.removeFilter(rl.get(i));
12541 }
12542 }
12543
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012544 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12545 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12546 ProcessRecord r = mLruProcesses.get(i);
12547 if (r.thread != null) {
12548 try {
12549 r.thread.dispatchPackageBroadcast(cmd, packages);
12550 } catch (RemoteException ex) {
12551 }
12552 }
12553 }
12554 }
12555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012556 private final int broadcastIntentLocked(ProcessRecord callerApp,
12557 String callerPackage, Intent intent, String resolvedType,
12558 IIntentReceiver resultTo, int resultCode, String resultData,
12559 Bundle map, String requiredPermission,
12560 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12561 intent = new Intent(intent);
12562
Joe Onorato8a9b2202010-02-26 18:56:32 -080012563 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012564 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12565 + " ordered=" + ordered);
12566 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012567 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012568 }
12569
12570 // Handle special intents: if this broadcast is from the package
12571 // manager about a package being removed, we need to remove all of
12572 // its activities from the history stack.
12573 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12574 intent.getAction());
12575 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12576 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012577 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 || uidRemoved) {
12579 if (checkComponentPermission(
12580 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12581 callingPid, callingUid, -1)
12582 == PackageManager.PERMISSION_GRANTED) {
12583 if (uidRemoved) {
12584 final Bundle intentExtras = intent.getExtras();
12585 final int uid = intentExtras != null
12586 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12587 if (uid >= 0) {
12588 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12589 synchronized (bs) {
12590 bs.removeUidStatsLocked(uid);
12591 }
12592 }
12593 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012594 // If resources are unvailble just force stop all
12595 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012596 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012597 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12598 if (list != null && (list.length > 0)) {
12599 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012600 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012601 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012602 sendPackageBroadcastLocked(
12603 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012604 }
12605 } else {
12606 Uri data = intent.getData();
12607 String ssp;
12608 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12609 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12610 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012611 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012612 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012613 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12614 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12615 new String[] {ssp});
12616 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012617 }
12618 }
12619 }
12620 } else {
12621 String msg = "Permission Denial: " + intent.getAction()
12622 + " broadcast from " + callerPackage + " (pid=" + callingPid
12623 + ", uid=" + callingUid + ")"
12624 + " requires "
12625 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012626 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012627 throw new SecurityException(msg);
12628 }
12629 }
12630
12631 /*
12632 * If this is the time zone changed action, queue up a message that will reset the timezone
12633 * of all currently running processes. This message will get queued up before the broadcast
12634 * happens.
12635 */
12636 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12637 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12638 }
12639
Dianne Hackborn854060af2009-07-09 18:14:31 -070012640 /*
12641 * Prevent non-system code (defined here to be non-persistent
12642 * processes) from sending protected broadcasts.
12643 */
12644 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12645 || callingUid == Process.SHELL_UID || callingUid == 0) {
12646 // Always okay.
12647 } else if (callerApp == null || !callerApp.persistent) {
12648 try {
12649 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12650 intent.getAction())) {
12651 String msg = "Permission Denial: not allowed to send broadcast "
12652 + intent.getAction() + " from pid="
12653 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012654 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012655 throw new SecurityException(msg);
12656 }
12657 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012658 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012659 return BROADCAST_SUCCESS;
12660 }
12661 }
12662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012663 // Add to the sticky list if requested.
12664 if (sticky) {
12665 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12666 callingPid, callingUid)
12667 != PackageManager.PERMISSION_GRANTED) {
12668 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12669 + callingPid + ", uid=" + callingUid
12670 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012671 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012672 throw new SecurityException(msg);
12673 }
12674 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012675 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012676 + " and enforce permission " + requiredPermission);
12677 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12678 }
12679 if (intent.getComponent() != null) {
12680 throw new SecurityException(
12681 "Sticky broadcasts can't target a specific component");
12682 }
12683 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12684 if (list == null) {
12685 list = new ArrayList<Intent>();
12686 mStickyBroadcasts.put(intent.getAction(), list);
12687 }
12688 int N = list.size();
12689 int i;
12690 for (i=0; i<N; i++) {
12691 if (intent.filterEquals(list.get(i))) {
12692 // This sticky already exists, replace it.
12693 list.set(i, new Intent(intent));
12694 break;
12695 }
12696 }
12697 if (i >= N) {
12698 list.add(new Intent(intent));
12699 }
12700 }
12701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012702 // Figure out who all will receive this broadcast.
12703 List receivers = null;
12704 List<BroadcastFilter> registeredReceivers = null;
12705 try {
12706 if (intent.getComponent() != null) {
12707 // Broadcast is going to one specific receiver class...
12708 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012709 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012710 if (ai != null) {
12711 receivers = new ArrayList();
12712 ResolveInfo ri = new ResolveInfo();
12713 ri.activityInfo = ai;
12714 receivers.add(ri);
12715 }
12716 } else {
12717 // Need to resolve the intent to interested receivers...
12718 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12719 == 0) {
12720 receivers =
12721 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012722 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012723 }
Mihai Preda074edef2009-05-18 17:13:31 +020012724 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012725 }
12726 } catch (RemoteException ex) {
12727 // pm is in same process, this will never happen.
12728 }
12729
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012730 final boolean replacePending =
12731 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12732
Joe Onorato8a9b2202010-02-26 18:56:32 -080012733 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012734 + " replacePending=" + replacePending);
12735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012736 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12737 if (!ordered && NR > 0) {
12738 // If we are not serializing this broadcast, then send the
12739 // registered receivers separately so they don't wait for the
12740 // components to be launched.
12741 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12742 callerPackage, callingPid, callingUid, requiredPermission,
12743 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012744 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012745 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012746 TAG, "Enqueueing parallel broadcast " + r
12747 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012748 boolean replaced = false;
12749 if (replacePending) {
12750 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12751 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012752 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012753 "***** DROPPING PARALLEL: " + intent);
12754 mParallelBroadcasts.set(i, r);
12755 replaced = true;
12756 break;
12757 }
12758 }
12759 }
12760 if (!replaced) {
12761 mParallelBroadcasts.add(r);
12762 scheduleBroadcastsLocked();
12763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012764 registeredReceivers = null;
12765 NR = 0;
12766 }
12767
12768 // Merge into one list.
12769 int ir = 0;
12770 if (receivers != null) {
12771 // A special case for PACKAGE_ADDED: do not allow the package
12772 // being added to see this broadcast. This prevents them from
12773 // using this as a back door to get run as soon as they are
12774 // installed. Maybe in the future we want to have a special install
12775 // broadcast or such for apps, but we'd like to deliberately make
12776 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012777 String skipPackages[] = null;
12778 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12779 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12780 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12781 Uri data = intent.getData();
12782 if (data != null) {
12783 String pkgName = data.getSchemeSpecificPart();
12784 if (pkgName != null) {
12785 skipPackages = new String[] { pkgName };
12786 }
12787 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012788 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012789 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012790 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012791 if (skipPackages != null && (skipPackages.length > 0)) {
12792 for (String skipPackage : skipPackages) {
12793 if (skipPackage != null) {
12794 int NT = receivers.size();
12795 for (int it=0; it<NT; it++) {
12796 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12797 if (curt.activityInfo.packageName.equals(skipPackage)) {
12798 receivers.remove(it);
12799 it--;
12800 NT--;
12801 }
12802 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012803 }
12804 }
12805 }
12806
12807 int NT = receivers != null ? receivers.size() : 0;
12808 int it = 0;
12809 ResolveInfo curt = null;
12810 BroadcastFilter curr = null;
12811 while (it < NT && ir < NR) {
12812 if (curt == null) {
12813 curt = (ResolveInfo)receivers.get(it);
12814 }
12815 if (curr == null) {
12816 curr = registeredReceivers.get(ir);
12817 }
12818 if (curr.getPriority() >= curt.priority) {
12819 // Insert this broadcast record into the final list.
12820 receivers.add(it, curr);
12821 ir++;
12822 curr = null;
12823 it++;
12824 NT++;
12825 } else {
12826 // Skip to the next ResolveInfo in the final list.
12827 it++;
12828 curt = null;
12829 }
12830 }
12831 }
12832 while (ir < NR) {
12833 if (receivers == null) {
12834 receivers = new ArrayList();
12835 }
12836 receivers.add(registeredReceivers.get(ir));
12837 ir++;
12838 }
12839
12840 if ((receivers != null && receivers.size() > 0)
12841 || resultTo != null) {
12842 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12843 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012844 receivers, resultTo, resultCode, resultData, map, ordered,
12845 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012846 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012847 TAG, "Enqueueing ordered broadcast " + r
12848 + ": prev had " + mOrderedBroadcasts.size());
12849 if (DEBUG_BROADCAST) {
12850 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012851 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012852 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012853 boolean replaced = false;
12854 if (replacePending) {
12855 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12856 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012857 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012858 "***** DROPPING ORDERED: " + intent);
12859 mOrderedBroadcasts.set(i, r);
12860 replaced = true;
12861 break;
12862 }
12863 }
12864 }
12865 if (!replaced) {
12866 mOrderedBroadcasts.add(r);
12867 scheduleBroadcastsLocked();
12868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012869 }
12870
12871 return BROADCAST_SUCCESS;
12872 }
12873
12874 public final int broadcastIntent(IApplicationThread caller,
12875 Intent intent, String resolvedType, IIntentReceiver resultTo,
12876 int resultCode, String resultData, Bundle map,
12877 String requiredPermission, boolean serialized, boolean sticky) {
12878 // Refuse possible leaked file descriptors
12879 if (intent != null && intent.hasFileDescriptors() == true) {
12880 throw new IllegalArgumentException("File descriptors passed in Intent");
12881 }
12882
12883 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012884 int flags = intent.getFlags();
12885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012886 if (!mSystemReady) {
12887 // if the caller really truly claims to know what they're doing, go
12888 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012889 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12890 intent = new Intent(intent);
12891 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12892 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012893 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012894 + " before boot completion");
12895 throw new IllegalStateException("Cannot broadcast before boot completed");
12896 }
12897 }
12898
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012899 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12900 throw new IllegalArgumentException(
12901 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12902 }
12903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012904 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12905 final int callingPid = Binder.getCallingPid();
12906 final int callingUid = Binder.getCallingUid();
12907 final long origId = Binder.clearCallingIdentity();
12908 int res = broadcastIntentLocked(callerApp,
12909 callerApp != null ? callerApp.info.packageName : null,
12910 intent, resolvedType, resultTo,
12911 resultCode, resultData, map, requiredPermission, serialized,
12912 sticky, callingPid, callingUid);
12913 Binder.restoreCallingIdentity(origId);
12914 return res;
12915 }
12916 }
12917
12918 int broadcastIntentInPackage(String packageName, int uid,
12919 Intent intent, String resolvedType, IIntentReceiver resultTo,
12920 int resultCode, String resultData, Bundle map,
12921 String requiredPermission, boolean serialized, boolean sticky) {
12922 synchronized(this) {
12923 final long origId = Binder.clearCallingIdentity();
12924 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12925 resultTo, resultCode, resultData, map, requiredPermission,
12926 serialized, sticky, -1, uid);
12927 Binder.restoreCallingIdentity(origId);
12928 return res;
12929 }
12930 }
12931
12932 public final void unbroadcastIntent(IApplicationThread caller,
12933 Intent intent) {
12934 // Refuse possible leaked file descriptors
12935 if (intent != null && intent.hasFileDescriptors() == true) {
12936 throw new IllegalArgumentException("File descriptors passed in Intent");
12937 }
12938
12939 synchronized(this) {
12940 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12941 != PackageManager.PERMISSION_GRANTED) {
12942 String msg = "Permission Denial: unbroadcastIntent() from pid="
12943 + Binder.getCallingPid()
12944 + ", uid=" + Binder.getCallingUid()
12945 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012946 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012947 throw new SecurityException(msg);
12948 }
12949 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12950 if (list != null) {
12951 int N = list.size();
12952 int i;
12953 for (i=0; i<N; i++) {
12954 if (intent.filterEquals(list.get(i))) {
12955 list.remove(i);
12956 break;
12957 }
12958 }
12959 }
12960 }
12961 }
12962
12963 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12964 String resultData, Bundle resultExtras, boolean resultAbort,
12965 boolean explicit) {
12966 if (mOrderedBroadcasts.size() == 0) {
12967 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012968 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012969 }
12970 return false;
12971 }
12972 BroadcastRecord r = mOrderedBroadcasts.get(0);
12973 if (r.receiver == null) {
12974 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012975 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012976 }
12977 return false;
12978 }
12979 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012980 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012981 return false;
12982 }
12983 int state = r.state;
12984 r.state = r.IDLE;
12985 if (state == r.IDLE) {
12986 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012987 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012988 }
12989 }
12990 r.receiver = null;
12991 r.intent.setComponent(null);
12992 if (r.curApp != null) {
12993 r.curApp.curReceiver = null;
12994 }
12995 if (r.curFilter != null) {
12996 r.curFilter.receiverList.curBroadcast = null;
12997 }
12998 r.curFilter = null;
12999 r.curApp = null;
13000 r.curComponent = null;
13001 r.curReceiver = null;
13002 mPendingBroadcast = null;
13003
13004 r.resultCode = resultCode;
13005 r.resultData = resultData;
13006 r.resultExtras = resultExtras;
13007 r.resultAbort = resultAbort;
13008
13009 // We will process the next receiver right now if this is finishing
13010 // an app receiver (which is always asynchronous) or after we have
13011 // come back from calling a receiver.
13012 return state == BroadcastRecord.APP_RECEIVE
13013 || state == BroadcastRecord.CALL_DONE_RECEIVE;
13014 }
13015
13016 public void finishReceiver(IBinder who, int resultCode, String resultData,
13017 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013018 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013019
13020 // Refuse possible leaked file descriptors
13021 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
13022 throw new IllegalArgumentException("File descriptors passed in Bundle");
13023 }
13024
13025 boolean doNext;
13026
13027 final long origId = Binder.clearCallingIdentity();
13028
13029 synchronized(this) {
13030 doNext = finishReceiverLocked(
13031 who, resultCode, resultData, resultExtras, resultAbort, true);
13032 }
13033
13034 if (doNext) {
13035 processNextBroadcast(false);
13036 }
13037 trimApplications();
13038
13039 Binder.restoreCallingIdentity(origId);
13040 }
13041
13042 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
13043 if (r.nextReceiver > 0) {
13044 Object curReceiver = r.receivers.get(r.nextReceiver-1);
13045 if (curReceiver instanceof BroadcastFilter) {
13046 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080013047 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013048 System.identityHashCode(r),
13049 r.intent.getAction(),
13050 r.nextReceiver - 1,
13051 System.identityHashCode(bf));
13052 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080013053 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013054 System.identityHashCode(r),
13055 r.intent.getAction(),
13056 r.nextReceiver - 1,
13057 ((ResolveInfo)curReceiver).toString());
13058 }
13059 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013060 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013061 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013062 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013063 System.identityHashCode(r),
13064 r.intent.getAction(),
13065 r.nextReceiver,
13066 "NONE");
13067 }
13068 }
13069
13070 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013071 ProcessRecord app = null;
13072 String anrMessage = null;
13073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013074 synchronized (this) {
13075 if (mOrderedBroadcasts.size() == 0) {
13076 return;
13077 }
13078 long now = SystemClock.uptimeMillis();
13079 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013080 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013081 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013082 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013083 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013084 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013085 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013086 return;
13087 }
13088
Joe Onorato8a9b2202010-02-26 18:56:32 -080013089 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013090 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013091 r.anrCount++;
13092
13093 // Current receiver has passed its expiration date.
13094 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013095 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013096 return;
13097 }
13098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013099 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013100 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013101 logBroadcastReceiverDiscard(r);
13102 if (curReceiver instanceof BroadcastFilter) {
13103 BroadcastFilter bf = (BroadcastFilter)curReceiver;
13104 if (bf.receiverList.pid != 0
13105 && bf.receiverList.pid != MY_PID) {
13106 synchronized (this.mPidsSelfLocked) {
13107 app = this.mPidsSelfLocked.get(
13108 bf.receiverList.pid);
13109 }
13110 }
13111 } else {
13112 app = r.curApp;
13113 }
13114
13115 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013116 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013117 }
13118
13119 if (mPendingBroadcast == r) {
13120 mPendingBroadcast = null;
13121 }
13122
13123 // Move on to the next receiver.
13124 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13125 r.resultExtras, r.resultAbort, true);
13126 scheduleBroadcastsLocked();
13127 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013128
13129 if (anrMessage != null) {
13130 appNotResponding(app, null, null, anrMessage);
13131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013132 }
13133
13134 private final void processCurBroadcastLocked(BroadcastRecord r,
13135 ProcessRecord app) throws RemoteException {
13136 if (app.thread == null) {
13137 throw new RemoteException();
13138 }
13139 r.receiver = app.thread.asBinder();
13140 r.curApp = app;
13141 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013142 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013143
13144 // Tell the application to launch this receiver.
13145 r.intent.setComponent(r.curComponent);
13146
13147 boolean started = false;
13148 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013149 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013150 "Delivering to component " + r.curComponent
13151 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070013152 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013153 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
13154 r.resultCode, r.resultData, r.resultExtras, r.ordered);
13155 started = true;
13156 } finally {
13157 if (!started) {
13158 r.receiver = null;
13159 r.curApp = null;
13160 app.curReceiver = null;
13161 }
13162 }
13163
13164 }
13165
13166 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013167 Intent intent, int resultCode, String data, Bundle extras,
13168 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013169 if (app != null && app.thread != null) {
13170 // If we have an app thread, do the call through that so it is
13171 // correctly ordered with other one-way calls.
13172 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013173 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013174 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013175 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013176 }
13177 }
13178
13179 private final void deliverToRegisteredReceiver(BroadcastRecord r,
13180 BroadcastFilter filter, boolean ordered) {
13181 boolean skip = false;
13182 if (filter.requiredPermission != null) {
13183 int perm = checkComponentPermission(filter.requiredPermission,
13184 r.callingPid, r.callingUid, -1);
13185 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013186 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013187 + r.intent.toString()
13188 + " from " + r.callerPackage + " (pid="
13189 + r.callingPid + ", uid=" + r.callingUid + ")"
13190 + " requires " + filter.requiredPermission
13191 + " due to registered receiver " + filter);
13192 skip = true;
13193 }
13194 }
13195 if (r.requiredPermission != null) {
13196 int perm = checkComponentPermission(r.requiredPermission,
13197 filter.receiverList.pid, filter.receiverList.uid, -1);
13198 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013199 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013200 + r.intent.toString()
13201 + " to " + filter.receiverList.app
13202 + " (pid=" + filter.receiverList.pid
13203 + ", uid=" + filter.receiverList.uid + ")"
13204 + " requires " + r.requiredPermission
13205 + " due to sender " + r.callerPackage
13206 + " (uid " + r.callingUid + ")");
13207 skip = true;
13208 }
13209 }
13210
13211 if (!skip) {
13212 // If this is not being sent as an ordered broadcast, then we
13213 // don't want to touch the fields that keep track of the current
13214 // state of ordered broadcasts.
13215 if (ordered) {
13216 r.receiver = filter.receiverList.receiver.asBinder();
13217 r.curFilter = filter;
13218 filter.receiverList.curBroadcast = r;
13219 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013220 if (filter.receiverList.app != null) {
13221 // Bump hosting application to no longer be in background
13222 // scheduling class. Note that we can't do that if there
13223 // isn't an app... but we can only be in that case for
13224 // things that directly call the IActivityManager API, which
13225 // are already core system stuff so don't matter for this.
13226 r.curApp = filter.receiverList.app;
13227 filter.receiverList.app.curReceiver = r;
13228 updateOomAdjLocked();
13229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013230 }
13231 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013232 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013233 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013234 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013235 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013236 }
13237 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13238 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013239 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013240 if (ordered) {
13241 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13242 }
13243 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013244 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013245 if (ordered) {
13246 r.receiver = null;
13247 r.curFilter = null;
13248 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013249 if (filter.receiverList.app != null) {
13250 filter.receiverList.app.curReceiver = null;
13251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013252 }
13253 }
13254 }
13255 }
13256
Dianne Hackborn12527f92009-11-11 17:39:50 -080013257 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13258 if (r.callingUid < 0) {
13259 // This was from a registerReceiver() call; ignore it.
13260 return;
13261 }
13262 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13263 MAX_BROADCAST_HISTORY-1);
13264 r.finishTime = SystemClock.uptimeMillis();
13265 mBroadcastHistory[0] = r;
13266 }
13267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013268 private final void processNextBroadcast(boolean fromMsg) {
13269 synchronized(this) {
13270 BroadcastRecord r;
13271
Joe Onorato8a9b2202010-02-26 18:56:32 -080013272 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013273 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013274 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013275
13276 updateCpuStats();
13277
13278 if (fromMsg) {
13279 mBroadcastsScheduled = false;
13280 }
13281
13282 // First, deliver any non-serialized broadcasts right away.
13283 while (mParallelBroadcasts.size() > 0) {
13284 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013285 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013286 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013287 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013288 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013289 for (int i=0; i<N; i++) {
13290 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013291 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013292 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013293 + target + ": " + r);
13294 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13295 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013296 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013297 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013298 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013299 }
13300
13301 // Now take care of the next serialized one...
13302
13303 // If we are waiting for a process to come up to handle the next
13304 // broadcast, then do nothing at this point. Just in case, we
13305 // check that the process we're waiting for still exists.
13306 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013307 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013308 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013309 + mPendingBroadcast.curApp);
13310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013311
13312 boolean isDead;
13313 synchronized (mPidsSelfLocked) {
13314 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13315 }
13316 if (!isDead) {
13317 // It's still alive, so keep waiting
13318 return;
13319 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013320 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013321 + " died before responding to broadcast");
13322 mPendingBroadcast = null;
13323 }
13324 }
13325
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013326 boolean looped = false;
13327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013328 do {
13329 if (mOrderedBroadcasts.size() == 0) {
13330 // No more broadcasts pending, so all done!
13331 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013332 if (looped) {
13333 // If we had finished the last ordered broadcast, then
13334 // make sure all processes have correct oom and sched
13335 // adjustments.
13336 updateOomAdjLocked();
13337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013338 return;
13339 }
13340 r = mOrderedBroadcasts.get(0);
13341 boolean forceReceive = false;
13342
13343 // Ensure that even if something goes awry with the timeout
13344 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013345 // and continue to make progress.
13346 //
13347 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
13348 // receivers don't get executed with with timeouts. They're intended for
13349 // one time heavy lifting after system upgrades and can take
13350 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013351 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013352 if (mSystemReady && r.dispatchTime > 0) {
13353 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013354 if ((numReceivers > 0) &&
13355 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013356 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013357 + " now=" + now
13358 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013359 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013360 + " intent=" + r.intent
13361 + " numReceivers=" + numReceivers
13362 + " nextReceiver=" + r.nextReceiver
13363 + " state=" + r.state);
13364 broadcastTimeout(); // forcibly finish this broadcast
13365 forceReceive = true;
13366 r.state = BroadcastRecord.IDLE;
13367 }
13368 }
13369
13370 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013371 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013372 "processNextBroadcast() called when not idle (state="
13373 + r.state + ")");
13374 return;
13375 }
13376
13377 if (r.receivers == null || r.nextReceiver >= numReceivers
13378 || r.resultAbort || forceReceive) {
13379 // No more receivers for this broadcast! Send the final
13380 // result if requested...
13381 if (r.resultTo != null) {
13382 try {
13383 if (DEBUG_BROADCAST) {
13384 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013385 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013386 + " seq=" + seq + " app=" + r.callerApp);
13387 }
13388 performReceive(r.callerApp, r.resultTo,
13389 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013390 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013391 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013392 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013393 }
13394 }
13395
Joe Onorato8a9b2202010-02-26 18:56:32 -080013396 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013397 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13398
Joe Onorato8a9b2202010-02-26 18:56:32 -080013399 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013400 + r);
13401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013402 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013403 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013404 mOrderedBroadcasts.remove(0);
13405 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013406 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013407 continue;
13408 }
13409 } while (r == null);
13410
13411 // Get the next receiver...
13412 int recIdx = r.nextReceiver++;
13413
13414 // Keep track of when this receiver started, and make sure there
13415 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013416 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013417 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013418 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013419
Joe Onorato8a9b2202010-02-26 18:56:32 -080013420 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013421 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013422 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013423 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013424 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013425 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013426 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013427 }
13428
13429 Object nextReceiver = r.receivers.get(recIdx);
13430 if (nextReceiver instanceof BroadcastFilter) {
13431 // Simple case: this is a registered receiver who gets
13432 // a direct call.
13433 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013434 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013435 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013436 + filter + ": " + r);
13437 deliverToRegisteredReceiver(r, filter, r.ordered);
13438 if (r.receiver == null || !r.ordered) {
13439 // The receiver has already finished, so schedule to
13440 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013441 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13442 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013443 r.state = BroadcastRecord.IDLE;
13444 scheduleBroadcastsLocked();
13445 }
13446 return;
13447 }
13448
13449 // Hard case: need to instantiate the receiver, possibly
13450 // starting its application process to host it.
13451
13452 ResolveInfo info =
13453 (ResolveInfo)nextReceiver;
13454
13455 boolean skip = false;
13456 int perm = checkComponentPermission(info.activityInfo.permission,
13457 r.callingPid, r.callingUid,
13458 info.activityInfo.exported
13459 ? -1 : info.activityInfo.applicationInfo.uid);
13460 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013461 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013462 + r.intent.toString()
13463 + " from " + r.callerPackage + " (pid=" + r.callingPid
13464 + ", uid=" + r.callingUid + ")"
13465 + " requires " + info.activityInfo.permission
13466 + " due to receiver " + info.activityInfo.packageName
13467 + "/" + info.activityInfo.name);
13468 skip = true;
13469 }
13470 if (r.callingUid != Process.SYSTEM_UID &&
13471 r.requiredPermission != null) {
13472 try {
13473 perm = ActivityThread.getPackageManager().
13474 checkPermission(r.requiredPermission,
13475 info.activityInfo.applicationInfo.packageName);
13476 } catch (RemoteException e) {
13477 perm = PackageManager.PERMISSION_DENIED;
13478 }
13479 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013480 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013481 + r.intent + " to "
13482 + info.activityInfo.applicationInfo.packageName
13483 + " requires " + r.requiredPermission
13484 + " due to sender " + r.callerPackage
13485 + " (uid " + r.callingUid + ")");
13486 skip = true;
13487 }
13488 }
13489 if (r.curApp != null && r.curApp.crashing) {
13490 // If the target process is crashing, just skip it.
13491 skip = true;
13492 }
13493
13494 if (skip) {
13495 r.receiver = null;
13496 r.curFilter = null;
13497 r.state = BroadcastRecord.IDLE;
13498 scheduleBroadcastsLocked();
13499 return;
13500 }
13501
13502 r.state = BroadcastRecord.APP_RECEIVE;
13503 String targetProcess = info.activityInfo.processName;
13504 r.curComponent = new ComponentName(
13505 info.activityInfo.applicationInfo.packageName,
13506 info.activityInfo.name);
13507 r.curReceiver = info.activityInfo;
13508
13509 // Is this receiver's application already running?
13510 ProcessRecord app = getProcessRecordLocked(targetProcess,
13511 info.activityInfo.applicationInfo.uid);
13512 if (app != null && app.thread != null) {
13513 try {
13514 processCurBroadcastLocked(r, app);
13515 return;
13516 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013517 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013518 + r.curComponent, e);
13519 }
13520
13521 // If a dead object exception was thrown -- fall through to
13522 // restart the application.
13523 }
13524
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013525 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013526 if ((r.curApp=startProcessLocked(targetProcess,
13527 info.activityInfo.applicationInfo, true,
13528 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013529 "broadcast", r.curComponent,
13530 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13531 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013532 // Ah, this recipient is unavailable. Finish it if necessary,
13533 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013534 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013535 + info.activityInfo.applicationInfo.packageName + "/"
13536 + info.activityInfo.applicationInfo.uid + " for broadcast "
13537 + r.intent + ": process is bad");
13538 logBroadcastReceiverDiscard(r);
13539 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13540 r.resultExtras, r.resultAbort, true);
13541 scheduleBroadcastsLocked();
13542 r.state = BroadcastRecord.IDLE;
13543 return;
13544 }
13545
13546 mPendingBroadcast = r;
13547 }
13548 }
13549
13550 // =========================================================
13551 // INSTRUMENTATION
13552 // =========================================================
13553
13554 public boolean startInstrumentation(ComponentName className,
13555 String profileFile, int flags, Bundle arguments,
13556 IInstrumentationWatcher watcher) {
13557 // Refuse possible leaked file descriptors
13558 if (arguments != null && arguments.hasFileDescriptors()) {
13559 throw new IllegalArgumentException("File descriptors passed in Bundle");
13560 }
13561
13562 synchronized(this) {
13563 InstrumentationInfo ii = null;
13564 ApplicationInfo ai = null;
13565 try {
13566 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013567 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013568 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013569 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013570 } catch (PackageManager.NameNotFoundException e) {
13571 }
13572 if (ii == null) {
13573 reportStartInstrumentationFailure(watcher, className,
13574 "Unable to find instrumentation info for: " + className);
13575 return false;
13576 }
13577 if (ai == null) {
13578 reportStartInstrumentationFailure(watcher, className,
13579 "Unable to find instrumentation target package: " + ii.targetPackage);
13580 return false;
13581 }
13582
13583 int match = mContext.getPackageManager().checkSignatures(
13584 ii.targetPackage, ii.packageName);
13585 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13586 String msg = "Permission Denial: starting instrumentation "
13587 + className + " from pid="
13588 + Binder.getCallingPid()
13589 + ", uid=" + Binder.getCallingPid()
13590 + " not allowed because package " + ii.packageName
13591 + " does not have a signature matching the target "
13592 + ii.targetPackage;
13593 reportStartInstrumentationFailure(watcher, className, msg);
13594 throw new SecurityException(msg);
13595 }
13596
13597 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013598 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013599 ProcessRecord app = addAppLocked(ai);
13600 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013601 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013602 app.instrumentationProfileFile = profileFile;
13603 app.instrumentationArguments = arguments;
13604 app.instrumentationWatcher = watcher;
13605 app.instrumentationResultClass = className;
13606 Binder.restoreCallingIdentity(origId);
13607 }
13608
13609 return true;
13610 }
13611
13612 /**
13613 * Report errors that occur while attempting to start Instrumentation. Always writes the
13614 * error to the logs, but if somebody is watching, send the report there too. This enables
13615 * the "am" command to report errors with more information.
13616 *
13617 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13618 * @param cn The component name of the instrumentation.
13619 * @param report The error report.
13620 */
13621 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13622 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013623 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013624 try {
13625 if (watcher != null) {
13626 Bundle results = new Bundle();
13627 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13628 results.putString("Error", report);
13629 watcher.instrumentationStatus(cn, -1, results);
13630 }
13631 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013632 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013633 }
13634 }
13635
13636 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13637 if (app.instrumentationWatcher != null) {
13638 try {
13639 // NOTE: IInstrumentationWatcher *must* be oneway here
13640 app.instrumentationWatcher.instrumentationFinished(
13641 app.instrumentationClass,
13642 resultCode,
13643 results);
13644 } catch (RemoteException e) {
13645 }
13646 }
13647 app.instrumentationWatcher = null;
13648 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013649 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013650 app.instrumentationProfileFile = null;
13651 app.instrumentationArguments = null;
13652
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013653 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013654 }
13655
13656 public void finishInstrumentation(IApplicationThread target,
13657 int resultCode, Bundle results) {
13658 // Refuse possible leaked file descriptors
13659 if (results != null && results.hasFileDescriptors()) {
13660 throw new IllegalArgumentException("File descriptors passed in Intent");
13661 }
13662
13663 synchronized(this) {
13664 ProcessRecord app = getRecordForAppLocked(target);
13665 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013666 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013667 return;
13668 }
13669 final long origId = Binder.clearCallingIdentity();
13670 finishInstrumentationLocked(app, resultCode, results);
13671 Binder.restoreCallingIdentity(origId);
13672 }
13673 }
13674
13675 // =========================================================
13676 // CONFIGURATION
13677 // =========================================================
13678
13679 public ConfigurationInfo getDeviceConfigurationInfo() {
13680 ConfigurationInfo config = new ConfigurationInfo();
13681 synchronized (this) {
13682 config.reqTouchScreen = mConfiguration.touchscreen;
13683 config.reqKeyboardType = mConfiguration.keyboard;
13684 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013685 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13686 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013687 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13688 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013689 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13690 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013691 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13692 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013693 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013694 }
13695 return config;
13696 }
13697
13698 public Configuration getConfiguration() {
13699 Configuration ci;
13700 synchronized(this) {
13701 ci = new Configuration(mConfiguration);
13702 }
13703 return ci;
13704 }
13705
13706 public void updateConfiguration(Configuration values) {
13707 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13708 "updateConfiguration()");
13709
13710 synchronized(this) {
13711 if (values == null && mWindowManager != null) {
13712 // sentinel: fetch the current configuration from the window manager
13713 values = mWindowManager.computeNewConfiguration();
13714 }
13715
13716 final long origId = Binder.clearCallingIdentity();
13717 updateConfigurationLocked(values, null);
13718 Binder.restoreCallingIdentity(origId);
13719 }
13720 }
13721
13722 /**
13723 * Do either or both things: (1) change the current configuration, and (2)
13724 * make sure the given activity is running with the (now) current
13725 * configuration. Returns true if the activity has been left running, or
13726 * false if <var>starting</var> is being destroyed to match the new
13727 * configuration.
13728 */
13729 public boolean updateConfigurationLocked(Configuration values,
13730 HistoryRecord starting) {
13731 int changes = 0;
13732
13733 boolean kept = true;
13734
13735 if (values != null) {
13736 Configuration newConfig = new Configuration(mConfiguration);
13737 changes = newConfig.updateFrom(values);
13738 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013739 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013740 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013741 }
13742
Doug Zongker2bec3d42009-12-04 12:52:44 -080013743 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013744
13745 if (values.locale != null) {
13746 saveLocaleLocked(values.locale,
13747 !values.locale.equals(mConfiguration.locale),
13748 values.userSetLocale);
13749 }
13750
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013751 mConfigurationSeq++;
13752 if (mConfigurationSeq <= 0) {
13753 mConfigurationSeq = 1;
13754 }
13755 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013756 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013757 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013758
13759 AttributeCache ac = AttributeCache.instance();
13760 if (ac != null) {
13761 ac.updateConfiguration(mConfiguration);
13762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013763
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013764 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13765 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13766 msg.obj = new Configuration(mConfiguration);
13767 mHandler.sendMessage(msg);
13768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013769
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013770 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13771 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013772 try {
13773 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013774 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013775 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013776 app.thread.scheduleConfigurationChanged(mConfiguration);
13777 }
13778 } catch (Exception e) {
13779 }
13780 }
13781 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013782 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13783 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013784 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13785 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013786 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13787 broadcastIntentLocked(null, null,
13788 new Intent(Intent.ACTION_LOCALE_CHANGED),
13789 null, null, 0, null, null,
13790 null, false, false, MY_PID, Process.SYSTEM_UID);
13791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013792 }
13793 }
13794
13795 if (changes != 0 && starting == null) {
13796 // If the configuration changed, and the caller is not already
13797 // in the process of starting an activity, then find the top
13798 // activity to check if its configuration needs to change.
13799 starting = topRunningActivityLocked(null);
13800 }
13801
13802 if (starting != null) {
13803 kept = ensureActivityConfigurationLocked(starting, changes);
13804 if (kept) {
13805 // If this didn't result in the starting activity being
13806 // destroyed, then we need to make sure at this point that all
13807 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013808 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013809 + ", ensuring others are correct.");
13810 ensureActivitiesVisibleLocked(starting, changes);
13811 }
13812 }
13813
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013814 if (values != null && mWindowManager != null) {
13815 mWindowManager.setNewConfiguration(mConfiguration);
13816 }
13817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013818 return kept;
13819 }
13820
13821 private final boolean relaunchActivityLocked(HistoryRecord r,
13822 int changes, boolean andResume) {
13823 List<ResultInfo> results = null;
13824 List<Intent> newIntents = null;
13825 if (andResume) {
13826 results = r.results;
13827 newIntents = r.newIntents;
13828 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013829 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013830 + " with results=" + results + " newIntents=" + newIntents
13831 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013832 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13833 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013834 r.task.taskId, r.shortComponentName);
13835
13836 r.startFreezingScreenLocked(r.app, 0);
13837
13838 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013839 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013840 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013841 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013842 // Note: don't need to call pauseIfSleepingLocked() here, because
13843 // the caller will only pass in 'andResume' if this activity is
13844 // currently resumed, which implies we aren't sleeping.
13845 } catch (RemoteException e) {
13846 return false;
13847 }
13848
13849 if (andResume) {
13850 r.results = null;
13851 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013852 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013853 }
13854
13855 return true;
13856 }
13857
13858 /**
13859 * Make sure the given activity matches the current configuration. Returns
13860 * false if the activity had to be destroyed. Returns true if the
13861 * configuration is the same, or the activity will remain running as-is
13862 * for whatever reason. Ensures the HistoryRecord is updated with the
13863 * correct configuration and all other bookkeeping is handled.
13864 */
13865 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13866 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013867 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013868 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13869 "Skipping config check (will change): " + r);
13870 return true;
13871 }
13872
Joe Onorato8a9b2202010-02-26 18:56:32 -080013873 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013874 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013875
13876 // Short circuit: if the two configurations are the exact same
13877 // object (the common case), then there is nothing to do.
13878 Configuration newConfig = mConfiguration;
13879 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013880 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013881 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013882 return true;
13883 }
13884
13885 // We don't worry about activities that are finishing.
13886 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013887 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013888 "Configuration doesn't matter in finishing " + r);
13889 r.stopFreezingScreenLocked(false);
13890 return true;
13891 }
13892
13893 // Okay we now are going to make this activity have the new config.
13894 // But then we need to figure out how it needs to deal with that.
13895 Configuration oldConfig = r.configuration;
13896 r.configuration = newConfig;
13897
13898 // If the activity isn't currently running, just leave the new
13899 // configuration and it will pick that up next time it starts.
13900 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013901 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013902 "Configuration doesn't matter not running " + r);
13903 r.stopFreezingScreenLocked(false);
13904 return true;
13905 }
13906
13907 // If the activity isn't persistent, there is a chance we will
13908 // need to restart it.
13909 if (!r.persistent) {
13910
13911 // Figure out what has changed between the two configurations.
13912 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013913 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013914 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013915 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013916 + Integer.toHexString(r.info.configChanges)
13917 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013918 }
13919 if ((changes&(~r.info.configChanges)) != 0) {
13920 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13921 r.configChangeFlags |= changes;
13922 r.startFreezingScreenLocked(r.app, globalChanges);
13923 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013924 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013925 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013926 destroyActivityLocked(r, true);
13927 } else if (r.state == ActivityState.PAUSING) {
13928 // A little annoying: we are waiting for this activity to
13929 // finish pausing. Let's not do anything now, but just
13930 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013931 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013932 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013933 r.configDestroy = true;
13934 return true;
13935 } else if (r.state == ActivityState.RESUMED) {
13936 // Try to optimize this case: the configuration is changing
13937 // and we need to restart the top, resumed activity.
13938 // Instead of doing the normal handshaking, just say
13939 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013940 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013941 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013942 relaunchActivityLocked(r, r.configChangeFlags, true);
13943 r.configChangeFlags = 0;
13944 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013945 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013946 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013947 relaunchActivityLocked(r, r.configChangeFlags, false);
13948 r.configChangeFlags = 0;
13949 }
13950
13951 // All done... tell the caller we weren't able to keep this
13952 // activity around.
13953 return false;
13954 }
13955 }
13956
13957 // Default case: the activity can handle this new configuration, so
13958 // hand it over. Note that we don't need to give it the new
13959 // configuration, since we always send configuration changes to all
13960 // process when they happen so it can just use whatever configuration
13961 // it last got.
13962 if (r.app != null && r.app.thread != null) {
13963 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013964 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013965 r.app.thread.scheduleActivityConfigurationChanged(r);
13966 } catch (RemoteException e) {
13967 // If process died, whatever.
13968 }
13969 }
13970 r.stopFreezingScreenLocked(false);
13971
13972 return true;
13973 }
13974
13975 /**
13976 * Save the locale. You must be inside a synchronized (this) block.
13977 */
13978 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13979 if(isDiff) {
13980 SystemProperties.set("user.language", l.getLanguage());
13981 SystemProperties.set("user.region", l.getCountry());
13982 }
13983
13984 if(isPersist) {
13985 SystemProperties.set("persist.sys.language", l.getLanguage());
13986 SystemProperties.set("persist.sys.country", l.getCountry());
13987 SystemProperties.set("persist.sys.localevar", l.getVariant());
13988 }
13989 }
13990
13991 // =========================================================
13992 // LIFETIME MANAGEMENT
13993 // =========================================================
13994
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013995 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
13996 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013997 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013998 // This adjustment has already been computed. If we are calling
13999 // from the top, we may have already computed our adjustment with
14000 // an earlier hidden adjustment that isn't really for us... if
14001 // so, use the new hidden adjustment.
14002 if (!recursed && app.hidden) {
14003 app.curAdj = hiddenAdj;
14004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014005 return app.curAdj;
14006 }
14007
14008 if (app.thread == null) {
14009 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014010 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014011 return (app.curAdj=EMPTY_APP_ADJ);
14012 }
14013
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014014 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
14015 // The max adjustment doesn't allow this app to be anything
14016 // below foreground, so it is not worth doing work for it.
14017 app.adjType = "fixed";
14018 app.adjSeq = mAdjSeq;
14019 app.curRawAdj = app.maxAdj;
14020 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
14021 return (app.curAdj=app.maxAdj);
14022 }
14023
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014024 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014025 app.adjSource = null;
14026 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014027 app.empty = false;
14028 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014029
The Android Open Source Project4df24232009-03-05 14:34:35 -080014030 // Determine the importance of the process, starting with most
14031 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014032 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014033 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014034 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014035 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014036 // The last app on the list is the foreground app.
14037 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014038 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014039 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014040 } else if (app.instrumentationClass != null) {
14041 // Don't want to kill running instrumentation.
14042 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014043 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014044 app.adjType = "instrumentation";
Dianne Hackborn860755f2010-06-03 18:47:52 -070014045 } else if (app == mHeavyWeightProcess) {
14046 // We don't want to kill the current heavy-weight process.
14047 adj = FOREGROUND_APP_ADJ;
14048 schedGroup = Process.THREAD_GROUP_DEFAULT;
14049 app.adjType = "heavy";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014050 } else if (app.persistentActivities > 0) {
14051 // Special persistent activities... shouldn't be used these days.
14052 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014053 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014054 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014055 } else if (app.curReceiver != null ||
14056 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
14057 // An app that is currently receiving a broadcast also
14058 // counts as being in the foreground.
14059 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014060 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014061 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014062 } else if (app.executingServices.size() > 0) {
14063 // An app that is currently executing a service callback also
14064 // counts as being in the foreground.
14065 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014066 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014067 app.adjType = "exec-service";
14068 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014069 // The user is aware of this app, so make it visible.
14070 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014071 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014072 app.adjType = "foreground-service";
14073 } else if (app.forcingToForeground != null) {
14074 // The user is aware of this app, so make it visible.
14075 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014076 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014077 app.adjType = "force-foreground";
14078 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080014079 } else if (app == mHomeProcess) {
14080 // This process is hosting what we currently consider to be the
14081 // home app, so we don't want to let it go into the background.
14082 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014083 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014084 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014085 } else if ((N=app.activities.size()) != 0) {
14086 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014087 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014088 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014089 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014090 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014091 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014092 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014093 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014094 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014095 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014096 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014097 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014098 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014099 break;
14100 }
14101 }
14102 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014103 // A very not-needed process. If this is lower in the lru list,
14104 // we will push it in to the empty bucket.
14105 app.hidden = true;
14106 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014107 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014108 adj = hiddenAdj;
14109 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014110 }
14111
Joe Onorato8a9b2202010-02-26 18:56:32 -080014112 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014113
The Android Open Source Project4df24232009-03-05 14:34:35 -080014114 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014115 // there are applications dependent on our services or providers, but
14116 // this gives us a baseline and makes sure we don't get into an
14117 // infinite recursion.
14118 app.adjSeq = mAdjSeq;
14119 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014120
Christopher Tate6fa95972009-06-05 18:43:55 -070014121 if (mBackupTarget != null && app == mBackupTarget.app) {
14122 // If possible we want to avoid killing apps while they're being backed up
14123 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014124 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070014125 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014126 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014127 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070014128 }
14129 }
14130
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014131 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
14132 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014133 final long now = SystemClock.uptimeMillis();
14134 // This process is more important if the top activity is
14135 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070014136 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014137 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014138 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014139 if (s.startRequested) {
14140 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14141 // This service has seen some activity within
14142 // recent memory, so we will keep its process ahead
14143 // of the background processes.
14144 if (adj > SECONDARY_SERVER_ADJ) {
14145 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014146 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014147 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014148 }
14149 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014150 // If we have let the service slide into the background
14151 // state, still have some text describing what it is doing
14152 // even though the service no longer has an impact.
14153 if (adj > SECONDARY_SERVER_ADJ) {
14154 app.adjType = "started-bg-services";
14155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014156 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014157 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
14158 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014159 Iterator<ConnectionRecord> kt
14160 = s.connections.values().iterator();
14161 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14162 // XXX should compute this based on the max of
14163 // all connected clients.
14164 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014165 if (cr.binding.client == app) {
14166 // Binding to ourself is not interesting.
14167 continue;
14168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014169 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
14170 ProcessRecord client = cr.binding.client;
14171 int myHiddenAdj = hiddenAdj;
14172 if (myHiddenAdj > client.hiddenAdj) {
14173 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
14174 myHiddenAdj = client.hiddenAdj;
14175 } else {
14176 myHiddenAdj = VISIBLE_APP_ADJ;
14177 }
14178 }
14179 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014180 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014181 if (adj > clientAdj) {
14182 adj = clientAdj > VISIBLE_APP_ADJ
14183 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014184 if (!client.hidden) {
14185 app.hidden = false;
14186 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014187 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014188 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14189 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014190 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014191 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014192 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014193 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14194 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14195 schedGroup = Process.THREAD_GROUP_DEFAULT;
14196 }
14197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014198 }
14199 HistoryRecord a = cr.activity;
14200 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014201 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014202 //}
14203 if (a != null && adj > FOREGROUND_APP_ADJ &&
14204 (a.state == ActivityState.RESUMED
14205 || a.state == ActivityState.PAUSING)) {
14206 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014207 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014208 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014209 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014210 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14211 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014212 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014213 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014214 }
14215 }
14216 }
14217 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014218
14219 // Finally, f this process has active services running in it, we
14220 // would like to avoid killing it unless it would prevent the current
14221 // application from running. By default we put the process in
14222 // with the rest of the background processes; as we scan through
14223 // its services we may bump it up from there.
14224 if (adj > hiddenAdj) {
14225 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014226 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014227 app.adjType = "bg-services";
14228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014229 }
14230
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014231 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
14232 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014233 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014234 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
14235 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014236 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014237 if (cpr.clients.size() != 0) {
14238 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14239 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14240 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014241 if (client == app) {
14242 // Being our own client is not interesting.
14243 continue;
14244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014245 int myHiddenAdj = hiddenAdj;
14246 if (myHiddenAdj > client.hiddenAdj) {
14247 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14248 myHiddenAdj = client.hiddenAdj;
14249 } else {
14250 myHiddenAdj = FOREGROUND_APP_ADJ;
14251 }
14252 }
14253 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014254 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014255 if (adj > clientAdj) {
14256 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014257 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014258 if (!client.hidden) {
14259 app.hidden = false;
14260 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014261 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014262 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14263 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014264 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014265 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014266 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014267 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14268 schedGroup = Process.THREAD_GROUP_DEFAULT;
14269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014270 }
14271 }
14272 // If the provider has external (non-framework) process
14273 // dependencies, ensure that its adjustment is at least
14274 // FOREGROUND_APP_ADJ.
14275 if (cpr.externals != 0) {
14276 if (adj > FOREGROUND_APP_ADJ) {
14277 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014278 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014279 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014280 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014281 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014282 }
14283 }
14284 }
14285 }
14286
14287 app.curRawAdj = adj;
14288
Joe Onorato8a9b2202010-02-26 18:56:32 -080014289 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014290 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14291 if (adj > app.maxAdj) {
14292 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014293 if (app.maxAdj <= VISIBLE_APP_ADJ) {
14294 schedGroup = Process.THREAD_GROUP_DEFAULT;
14295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014296 }
14297
14298 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014299 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014301 return adj;
14302 }
14303
14304 /**
14305 * Ask a given process to GC right now.
14306 */
14307 final void performAppGcLocked(ProcessRecord app) {
14308 try {
14309 app.lastRequestedGc = SystemClock.uptimeMillis();
14310 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014311 if (app.reportLowMemory) {
14312 app.reportLowMemory = false;
14313 app.thread.scheduleLowMemory();
14314 } else {
14315 app.thread.processInBackground();
14316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014317 }
14318 } catch (Exception e) {
14319 // whatever.
14320 }
14321 }
14322
14323 /**
14324 * Returns true if things are idle enough to perform GCs.
14325 */
Josh Bartel7f208742010-02-25 11:01:44 -060014326 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014327 return mParallelBroadcasts.size() == 0
14328 && mOrderedBroadcasts.size() == 0
14329 && (mSleeping || (mResumedActivity != null &&
14330 mResumedActivity.idle));
14331 }
14332
14333 /**
14334 * Perform GCs on all processes that are waiting for it, but only
14335 * if things are idle.
14336 */
14337 final void performAppGcsLocked() {
14338 final int N = mProcessesToGc.size();
14339 if (N <= 0) {
14340 return;
14341 }
Josh Bartel7f208742010-02-25 11:01:44 -060014342 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014343 while (mProcessesToGc.size() > 0) {
14344 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014345 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
14346 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14347 <= SystemClock.uptimeMillis()) {
14348 // To avoid spamming the system, we will GC processes one
14349 // at a time, waiting a few seconds between each.
14350 performAppGcLocked(proc);
14351 scheduleAppGcsLocked();
14352 return;
14353 } else {
14354 // It hasn't been long enough since we last GCed this
14355 // process... put it in the list to wait for its time.
14356 addProcessToGcListLocked(proc);
14357 break;
14358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014359 }
14360 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014361
14362 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014363 }
14364 }
14365
14366 /**
14367 * If all looks good, perform GCs on all processes waiting for them.
14368 */
14369 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014370 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014371 performAppGcsLocked();
14372 return;
14373 }
14374 // Still not idle, wait some more.
14375 scheduleAppGcsLocked();
14376 }
14377
14378 /**
14379 * Schedule the execution of all pending app GCs.
14380 */
14381 final void scheduleAppGcsLocked() {
14382 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014383
14384 if (mProcessesToGc.size() > 0) {
14385 // Schedule a GC for the time to the next process.
14386 ProcessRecord proc = mProcessesToGc.get(0);
14387 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14388
14389 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14390 long now = SystemClock.uptimeMillis();
14391 if (when < (now+GC_TIMEOUT)) {
14392 when = now + GC_TIMEOUT;
14393 }
14394 mHandler.sendMessageAtTime(msg, when);
14395 }
14396 }
14397
14398 /**
14399 * Add a process to the array of processes waiting to be GCed. Keeps the
14400 * list in sorted order by the last GC time. The process can't already be
14401 * on the list.
14402 */
14403 final void addProcessToGcListLocked(ProcessRecord proc) {
14404 boolean added = false;
14405 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14406 if (mProcessesToGc.get(i).lastRequestedGc <
14407 proc.lastRequestedGc) {
14408 added = true;
14409 mProcessesToGc.add(i+1, proc);
14410 break;
14411 }
14412 }
14413 if (!added) {
14414 mProcessesToGc.add(0, proc);
14415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014416 }
14417
14418 /**
14419 * Set up to ask a process to GC itself. This will either do it
14420 * immediately, or put it on the list of processes to gc the next
14421 * time things are idle.
14422 */
14423 final void scheduleAppGcLocked(ProcessRecord app) {
14424 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014425 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014426 return;
14427 }
14428 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014429 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014430 scheduleAppGcsLocked();
14431 }
14432 }
14433
14434 private final boolean updateOomAdjLocked(
14435 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14436 app.hiddenAdj = hiddenAdj;
14437
14438 if (app.thread == null) {
14439 return true;
14440 }
14441
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014442 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014443
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014444 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014445 if (app.curRawAdj != app.setRawAdj) {
14446 if (app.curRawAdj > FOREGROUND_APP_ADJ
14447 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14448 // If this app is transitioning from foreground to
14449 // non-foreground, have it do a gc.
14450 scheduleAppGcLocked(app);
14451 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14452 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14453 // Likewise do a gc when an app is moving in to the
14454 // background (such as a service stopping).
14455 scheduleAppGcLocked(app);
14456 }
14457 app.setRawAdj = app.curRawAdj;
14458 }
14459 if (adj != app.setAdj) {
14460 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014461 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014462 TAG, "Set app " + app.processName +
14463 " oom adj to " + adj);
14464 app.setAdj = adj;
14465 } else {
14466 return false;
14467 }
14468 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014469 if (app.setSchedGroup != app.curSchedGroup) {
14470 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014471 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014472 "Setting process group of " + app.processName
14473 + " to " + app.curSchedGroup);
14474 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014475 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014476 try {
14477 Process.setProcessGroup(app.pid, app.curSchedGroup);
14478 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014479 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014480 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014481 e.printStackTrace();
14482 } finally {
14483 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014484 }
14485 }
14486 if (false) {
14487 if (app.thread != null) {
14488 try {
14489 app.thread.setSchedulingGroup(app.curSchedGroup);
14490 } catch (RemoteException e) {
14491 }
14492 }
14493 }
14494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014495 }
14496
14497 return true;
14498 }
14499
14500 private final HistoryRecord resumedAppLocked() {
14501 HistoryRecord resumedActivity = mResumedActivity;
14502 if (resumedActivity == null || resumedActivity.app == null) {
14503 resumedActivity = mPausingActivity;
14504 if (resumedActivity == null || resumedActivity.app == null) {
14505 resumedActivity = topRunningActivityLocked(null);
14506 }
14507 }
14508 return resumedActivity;
14509 }
14510
14511 private final boolean updateOomAdjLocked(ProcessRecord app) {
14512 final HistoryRecord TOP_ACT = resumedAppLocked();
14513 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14514 int curAdj = app.curAdj;
14515 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14516 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14517
14518 mAdjSeq++;
14519
14520 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14521 if (res) {
14522 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14523 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14524 if (nowHidden != wasHidden) {
14525 // Changed to/from hidden state, so apps after it in the LRU
14526 // list may also be changed.
14527 updateOomAdjLocked();
14528 }
14529 }
14530 return res;
14531 }
14532
14533 private final boolean updateOomAdjLocked() {
14534 boolean didOomAdj = true;
14535 final HistoryRecord TOP_ACT = resumedAppLocked();
14536 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14537
14538 if (false) {
14539 RuntimeException e = new RuntimeException();
14540 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014541 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014542 }
14543
14544 mAdjSeq++;
14545
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014546 // Let's determine how many processes we have running vs.
14547 // how many slots we have for background processes; we may want
14548 // to put multiple processes in a slot of there are enough of
14549 // them.
14550 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14551 int factor = (mLruProcesses.size()-4)/numSlots;
14552 if (factor < 1) factor = 1;
14553 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014554 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014556 // First try updating the OOM adjustment for each of the
14557 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014558 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014559 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14560 while (i > 0) {
14561 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014562 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014563 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014564 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014565 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014566 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014567 step++;
14568 if (step >= factor) {
14569 step = 0;
14570 curHiddenAdj++;
14571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014572 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014573 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014574 if (!app.killedBackground) {
14575 numHidden++;
14576 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014577 Slog.i(TAG, "No longer want " + app.processName
14578 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014579 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14580 app.processName, app.setAdj, "too many background");
14581 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014582 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014583 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014584 }
14585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014586 } else {
14587 didOomAdj = false;
14588 }
14589 }
14590
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014591 // If we return false, we will fall back on killing processes to
14592 // have a fixed limit. Do this if a limit has been requested; else
14593 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014594 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14595 }
14596
14597 private final void trimApplications() {
14598 synchronized (this) {
14599 int i;
14600
14601 // First remove any unused application processes whose package
14602 // has been removed.
14603 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14604 final ProcessRecord app = mRemovedProcesses.get(i);
14605 if (app.activities.size() == 0
14606 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014607 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014608 TAG, "Exiting empty application process "
14609 + app.processName + " ("
14610 + (app.thread != null ? app.thread.asBinder() : null)
14611 + ")\n");
14612 if (app.pid > 0 && app.pid != MY_PID) {
14613 Process.killProcess(app.pid);
14614 } else {
14615 try {
14616 app.thread.scheduleExit();
14617 } catch (Exception e) {
14618 // Ignore exceptions.
14619 }
14620 }
14621 cleanUpApplicationRecordLocked(app, false, -1);
14622 mRemovedProcesses.remove(i);
14623
14624 if (app.persistent) {
14625 if (app.persistent) {
14626 addAppLocked(app.info);
14627 }
14628 }
14629 }
14630 }
14631
14632 // Now try updating the OOM adjustment for each of the
14633 // application processes based on their current state.
14634 // If the setOomAdj() API is not supported, then go with our
14635 // back-up plan...
14636 if (!updateOomAdjLocked()) {
14637
14638 // Count how many processes are running services.
14639 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014640 for (i=mLruProcesses.size()-1; i>=0; i--) {
14641 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014642
14643 if (app.persistent || app.services.size() != 0
14644 || app.curReceiver != null
14645 || app.persistentActivities > 0) {
14646 // Don't count processes holding services against our
14647 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014648 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014649 TAG, "Not trimming app " + app + " with services: "
14650 + app.services);
14651 numServiceProcs++;
14652 }
14653 }
14654
14655 int curMaxProcs = mProcessLimit;
14656 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14657 if (mAlwaysFinishActivities) {
14658 curMaxProcs = 1;
14659 }
14660 curMaxProcs += numServiceProcs;
14661
14662 // Quit as many processes as we can to get down to the desired
14663 // process count. First remove any processes that no longer
14664 // have activites running in them.
14665 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014666 i<mLruProcesses.size()
14667 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014668 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014669 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014670 // Quit an application only if it is not currently
14671 // running any activities.
14672 if (!app.persistent && app.activities.size() == 0
14673 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014674 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014675 TAG, "Exiting empty application process "
14676 + app.processName + " ("
14677 + (app.thread != null ? app.thread.asBinder() : null)
14678 + ")\n");
14679 if (app.pid > 0 && app.pid != MY_PID) {
14680 Process.killProcess(app.pid);
14681 } else {
14682 try {
14683 app.thread.scheduleExit();
14684 } catch (Exception e) {
14685 // Ignore exceptions.
14686 }
14687 }
14688 // todo: For now we assume the application is not buggy
14689 // or evil, and will quit as a result of our request.
14690 // Eventually we need to drive this off of the death
14691 // notification, and kill the process if it takes too long.
14692 cleanUpApplicationRecordLocked(app, false, i);
14693 i--;
14694 }
14695 }
14696
14697 // If we still have too many processes, now from the least
14698 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014699 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014700 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014701 " of " + curMaxProcs + " processes");
14702 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014703 i<mLruProcesses.size()
14704 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014705 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014706 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014707 // Quit the application only if we have a state saved for
14708 // all of its activities.
14709 boolean canQuit = !app.persistent && app.curReceiver == null
14710 && app.services.size() == 0
14711 && app.persistentActivities == 0;
14712 int NUMA = app.activities.size();
14713 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014714 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014715 TAG, "Looking to quit " + app.processName);
14716 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014717 HistoryRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014718 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014719 TAG, " " + r.intent.getComponent().flattenToShortString()
14720 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14721 canQuit = (r.haveState || !r.stateNotNeeded)
14722 && !r.visible && r.stopped;
14723 }
14724 if (canQuit) {
14725 // Finish all of the activities, and then the app itself.
14726 for (j=0; j<NUMA; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014727 HistoryRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014728 if (!r.finishing) {
14729 destroyActivityLocked(r, false);
14730 }
14731 r.resultTo = null;
14732 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014733 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014734 + app.processName + " ("
14735 + (app.thread != null ? app.thread.asBinder() : null)
14736 + ")\n");
14737 if (app.pid > 0 && app.pid != MY_PID) {
14738 Process.killProcess(app.pid);
14739 } else {
14740 try {
14741 app.thread.scheduleExit();
14742 } catch (Exception e) {
14743 // Ignore exceptions.
14744 }
14745 }
14746 // todo: For now we assume the application is not buggy
14747 // or evil, and will quit as a result of our request.
14748 // Eventually we need to drive this off of the death
14749 // notification, and kill the process if it takes too long.
14750 cleanUpApplicationRecordLocked(app, false, i);
14751 i--;
14752 //dump();
14753 }
14754 }
14755
14756 }
14757
14758 int curMaxActivities = MAX_ACTIVITIES;
14759 if (mAlwaysFinishActivities) {
14760 curMaxActivities = 1;
14761 }
14762
14763 // Finally, if there are too many activities now running, try to
14764 // finish as many as we can to get back down to the limit.
14765 for ( i=0;
14766 i<mLRUActivities.size()
14767 && mLRUActivities.size() > curMaxActivities;
14768 i++) {
14769 final HistoryRecord r
14770 = (HistoryRecord)mLRUActivities.get(i);
14771
14772 // We can finish this one if we have its icicle saved and
14773 // it is not persistent.
14774 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14775 && r.stopped && !r.persistent && !r.finishing) {
14776 final int origSize = mLRUActivities.size();
14777 destroyActivityLocked(r, true);
14778
14779 // This will remove it from the LRU list, so keep
14780 // our index at the same value. Note that this check to
14781 // see if the size changes is just paranoia -- if
14782 // something unexpected happens, we don't want to end up
14783 // in an infinite loop.
14784 if (origSize > mLRUActivities.size()) {
14785 i--;
14786 }
14787 }
14788 }
14789 }
14790 }
14791
14792 /** This method sends the specified signal to each of the persistent apps */
14793 public void signalPersistentProcesses(int sig) throws RemoteException {
14794 if (sig != Process.SIGNAL_USR1) {
14795 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14796 }
14797
14798 synchronized (this) {
14799 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14800 != PackageManager.PERMISSION_GRANTED) {
14801 throw new SecurityException("Requires permission "
14802 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14803 }
14804
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014805 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14806 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014807 if (r.thread != null && r.persistent) {
14808 Process.sendSignal(r.pid, sig);
14809 }
14810 }
14811 }
14812 }
14813
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014814 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014815 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014816
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014817 try {
14818 synchronized (this) {
14819 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14820 // its own permission.
14821 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14822 != PackageManager.PERMISSION_GRANTED) {
14823 throw new SecurityException("Requires permission "
14824 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014825 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014826
14827 if (start && fd == null) {
14828 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014829 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014830
14831 ProcessRecord proc = null;
14832 try {
14833 int pid = Integer.parseInt(process);
14834 synchronized (mPidsSelfLocked) {
14835 proc = mPidsSelfLocked.get(pid);
14836 }
14837 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014838 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014839
14840 if (proc == null) {
14841 HashMap<String, SparseArray<ProcessRecord>> all
14842 = mProcessNames.getMap();
14843 SparseArray<ProcessRecord> procs = all.get(process);
14844 if (procs != null && procs.size() > 0) {
14845 proc = procs.valueAt(0);
14846 }
14847 }
14848
14849 if (proc == null || proc.thread == null) {
14850 throw new IllegalArgumentException("Unknown process: " + process);
14851 }
14852
14853 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14854 if (isSecure) {
14855 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14856 throw new SecurityException("Process not debuggable: " + proc);
14857 }
14858 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014859
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014860 proc.thread.profilerControl(start, path, fd);
14861 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014862 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014863 }
14864 } catch (RemoteException e) {
14865 throw new IllegalStateException("Process disappeared");
14866 } finally {
14867 if (fd != null) {
14868 try {
14869 fd.close();
14870 } catch (IOException e) {
14871 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014872 }
14873 }
14874 }
14875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014876 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14877 public void monitor() {
14878 synchronized (this) { }
14879 }
14880}