blob: cfcac86c8b23af27435e11a8e47ebe2458af3ee1 [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;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001026 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027
1028 AlertDialog mUidAlert;
1029
1030 final Handler mHandler = new Handler() {
1031 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001032 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 //}
1034
1035 public void handleMessage(Message msg) {
1036 switch (msg.what) {
1037 case SHOW_ERROR_MSG: {
1038 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 synchronized (ActivityManagerService.this) {
1040 ProcessRecord proc = (ProcessRecord)data.get("app");
1041 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001042 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 return;
1044 }
1045 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -07001046 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -08001047 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 d.show();
1049 proc.crashDialog = d;
1050 } else {
1051 // The device is asleep, so just pretend that the user
1052 // saw a crash dialog and hit "force quit".
1053 res.set(0);
1054 }
1055 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001056
1057 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 } break;
1059 case SHOW_NOT_RESPONDING_MSG: {
1060 synchronized (ActivityManagerService.this) {
1061 HashMap data = (HashMap) msg.obj;
1062 ProcessRecord proc = (ProcessRecord)data.get("app");
1063 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001064 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 return;
1066 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001067
1068 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
1069 null, null, 0, null, null, null,
1070 false, false, MY_PID, Process.SYSTEM_UID);
1071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
1073 mContext, proc, (HistoryRecord)data.get("activity"));
1074 d.show();
1075 proc.anrDialog = d;
1076 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001077
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001078 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001080 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1081 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1082 synchronized (ActivityManagerService.this) {
1083 ProcessRecord proc = (ProcessRecord) data.get("app");
1084 if (proc == null) {
1085 Slog.e(TAG, "App not found when showing strict mode dialog.");
1086 break;
1087 }
1088 if (proc.crashDialog != null) {
1089 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1090 return;
1091 }
1092 AppErrorResult res = (AppErrorResult) data.get("result");
1093 if (!mSleeping && !mShuttingDown) {
1094 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1095 d.show();
1096 proc.crashDialog = d;
1097 } else {
1098 // The device is asleep, so just pretend that the user
1099 // saw a crash dialog and hit "force quit".
1100 res.set(0);
1101 }
1102 }
1103 ensureBootCompleted();
1104 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 case SHOW_FACTORY_ERROR_MSG: {
1106 Dialog d = new FactoryErrorDialog(
1107 mContext, msg.getData().getCharSequence("msg"));
1108 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001109 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 } break;
1111 case UPDATE_CONFIGURATION_MSG: {
1112 final ContentResolver resolver = mContext.getContentResolver();
1113 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1114 } break;
1115 case GC_BACKGROUND_PROCESSES_MSG: {
1116 synchronized (ActivityManagerService.this) {
1117 performAppGcsIfAppropriateLocked();
1118 }
1119 } break;
1120 case WAIT_FOR_DEBUGGER_MSG: {
1121 synchronized (ActivityManagerService.this) {
1122 ProcessRecord app = (ProcessRecord)msg.obj;
1123 if (msg.arg1 != 0) {
1124 if (!app.waitedForDebugger) {
1125 Dialog d = new AppWaitingForDebuggerDialog(
1126 ActivityManagerService.this,
1127 mContext, app);
1128 app.waitDialog = d;
1129 app.waitedForDebugger = true;
1130 d.show();
1131 }
1132 } else {
1133 if (app.waitDialog != null) {
1134 app.waitDialog.dismiss();
1135 app.waitDialog = null;
1136 }
1137 }
1138 }
1139 } break;
1140 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001141 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 TAG, "Received BROADCAST_INTENT_MSG");
1143 processNextBroadcast(true);
1144 } break;
1145 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001146 if (mDidDexOpt) {
1147 mDidDexOpt = false;
1148 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1149 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1150 return;
1151 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001152 // Only process broadcast timeouts if the system is ready. That way
1153 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1154 // to do heavy lifting for system up
1155 if (mSystemReady) {
1156 broadcastTimeout();
1157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 } break;
1159 case PAUSE_TIMEOUT_MSG: {
1160 IBinder token = (IBinder)msg.obj;
1161 // We don't at this point know if the activity is fullscreen,
1162 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001163 Slog.w(TAG, "Activity pause timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 activityPaused(token, null, true);
1165 } break;
1166 case IDLE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001167 if (mDidDexOpt) {
1168 mDidDexOpt = false;
1169 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1170 nmsg.obj = msg.obj;
1171 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
1172 return;
1173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 // We don't at this point know if the activity is fullscreen,
1175 // so we need to be conservative and assume it isn't.
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001176 IBinder token = (IBinder)msg.obj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001177 Slog.w(TAG, "Activity idle timeout for " + token);
Dianne Hackborne88846e2009-09-30 21:34:25 -07001178 activityIdleInternal(token, true, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 } break;
1180 case DESTROY_TIMEOUT_MSG: {
1181 IBinder token = (IBinder)msg.obj;
1182 // We don't at this point know if the activity is fullscreen,
1183 // so we need to be conservative and assume it isn't.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001184 Slog.w(TAG, "Activity destroy timeout for " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 activityDestroyed(token);
1186 } break;
1187 case IDLE_NOW_MSG: {
1188 IBinder token = (IBinder)msg.obj;
Dianne Hackborne88846e2009-09-30 21:34:25 -07001189 activityIdle(token, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 } break;
1191 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001192 if (mDidDexOpt) {
1193 mDidDexOpt = false;
1194 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1195 nmsg.obj = msg.obj;
1196 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1197 return;
1198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 serviceTimeout((ProcessRecord)msg.obj);
1200 } break;
1201 case UPDATE_TIME_ZONE: {
1202 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001203 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1204 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 if (r.thread != null) {
1206 try {
1207 r.thread.updateTimeZone();
1208 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001209 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210 }
1211 }
1212 }
1213 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001214 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 case SHOW_UID_ERROR_MSG: {
1216 // XXX This is a temporary dialog, no need to localize.
1217 AlertDialog d = new BaseErrorDialog(mContext);
1218 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1219 d.setCancelable(false);
1220 d.setTitle("System UIDs Inconsistent");
1221 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1222 d.setButton("I'm Feeling Lucky",
1223 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1224 mUidAlert = d;
1225 d.show();
1226 } break;
1227 case IM_FEELING_LUCKY_MSG: {
1228 if (mUidAlert != null) {
1229 mUidAlert.dismiss();
1230 mUidAlert = null;
1231 }
1232 } break;
1233 case LAUNCH_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001234 if (mDidDexOpt) {
1235 mDidDexOpt = false;
1236 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1237 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
1238 return;
1239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 synchronized (ActivityManagerService.this) {
1241 if (mLaunchingActivity.isHeld()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001242 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 mLaunchingActivity.release();
1244 }
1245 }
1246 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 case RESUME_TOP_ACTIVITY_MSG: {
1248 synchronized (ActivityManagerService.this) {
1249 resumeTopActivityLocked(null);
1250 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001251 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001253 if (mDidDexOpt) {
1254 mDidDexOpt = false;
1255 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1256 nmsg.obj = msg.obj;
1257 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1258 return;
1259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 ProcessRecord app = (ProcessRecord)msg.obj;
1261 synchronized (ActivityManagerService.this) {
1262 processStartTimedOutLocked(app);
1263 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001264 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001265 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1266 synchronized (ActivityManagerService.this) {
1267 doPendingActivityLaunchesLocked(true);
1268 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001269 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001270 case KILL_APPLICATION_MSG: {
1271 synchronized (ActivityManagerService.this) {
1272 int uid = msg.arg1;
1273 boolean restart = (msg.arg2 == 1);
1274 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001275 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001276 }
1277 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001278 case FINALIZE_PENDING_INTENT_MSG: {
1279 ((PendingIntentRecord)msg.obj).completeFinalize();
1280 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001281 case POST_HEAVY_NOTIFICATION_MSG: {
1282 INotificationManager inm = NotificationManager.getService();
1283 if (inm == null) {
1284 return;
1285 }
1286
1287 HistoryRecord root = (HistoryRecord)msg.obj;
1288 ProcessRecord process = root.app;
1289 if (process == null) {
1290 return;
1291 }
1292
1293 try {
1294 Context context = mContext.createPackageContext(process.info.packageName, 0);
1295 String text = mContext.getString(R.string.heavy_weight_notification,
1296 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1297 Notification notification = new Notification();
1298 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1299 notification.when = 0;
1300 notification.flags = Notification.FLAG_ONGOING_EVENT;
1301 notification.tickerText = text;
1302 notification.defaults = 0; // please be quiet
1303 notification.sound = null;
1304 notification.vibrate = null;
1305 notification.setLatestEventInfo(context, text,
1306 mContext.getText(R.string.heavy_weight_notification_detail),
1307 PendingIntent.getActivity(mContext, 0, root.intent,
1308 PendingIntent.FLAG_CANCEL_CURRENT));
1309
1310 try {
1311 int[] outId = new int[1];
1312 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1313 notification, outId);
1314 } catch (RuntimeException e) {
1315 Slog.w(ActivityManagerService.TAG,
1316 "Error showing notification for heavy-weight app", e);
1317 } catch (RemoteException e) {
1318 }
1319 } catch (NameNotFoundException e) {
1320 Log.w(TAG, "Unable to create context for heavy notification", e);
1321 }
1322 } break;
1323 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1324 INotificationManager inm = NotificationManager.getService();
1325 if (inm == null) {
1326 return;
1327 }
1328 try {
1329 inm.cancelNotification("android",
1330 R.string.heavy_weight_notification);
1331 } catch (RuntimeException e) {
1332 Slog.w(ActivityManagerService.TAG,
1333 "Error canceling notification for service", e);
1334 } catch (RemoteException e) {
1335 }
1336 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 }
1338 }
1339 };
1340
1341 public static void setSystemProcess() {
1342 try {
1343 ActivityManagerService m = mSelf;
1344
1345 ServiceManager.addService("activity", m);
1346 ServiceManager.addService("meminfo", new MemBinder(m));
1347 if (MONITOR_CPU_USAGE) {
1348 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 ServiceManager.addService("permission", new PermissionController(m));
1351
1352 ApplicationInfo info =
1353 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001354 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001355 mSystemThread.installSystemApplicationInfo(info);
1356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 synchronized (mSelf) {
1358 ProcessRecord app = mSelf.newProcessRecordLocked(
1359 mSystemThread.getApplicationThread(), info,
1360 info.processName);
1361 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001362 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 app.maxAdj = SYSTEM_ADJ;
1364 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1365 synchronized (mSelf.mPidsSelfLocked) {
1366 mSelf.mPidsSelfLocked.put(app.pid, app);
1367 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001368 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 }
1370 } catch (PackageManager.NameNotFoundException e) {
1371 throw new RuntimeException(
1372 "Unable to find android system package", e);
1373 }
1374 }
1375
1376 public void setWindowManager(WindowManagerService wm) {
1377 mWindowManager = wm;
1378 }
1379
1380 public static final Context main(int factoryTest) {
1381 AThread thr = new AThread();
1382 thr.start();
1383
1384 synchronized (thr) {
1385 while (thr.mService == null) {
1386 try {
1387 thr.wait();
1388 } catch (InterruptedException e) {
1389 }
1390 }
1391 }
1392
1393 ActivityManagerService m = thr.mService;
1394 mSelf = m;
1395 ActivityThread at = ActivityThread.systemMain();
1396 mSystemThread = at;
1397 Context context = at.getSystemContext();
1398 m.mContext = context;
1399 m.mFactoryTest = factoryTest;
1400 PowerManager pm =
1401 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
1402 m.mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
1403 m.mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
1404 m.mLaunchingActivity.setReferenceCounted(false);
1405
1406 m.mBatteryStatsService.publish(context);
1407 m.mUsageStatsService.publish(context);
1408
1409 synchronized (thr) {
1410 thr.mReady = true;
1411 thr.notifyAll();
1412 }
1413
1414 m.startRunning(null, null, null, null);
1415
1416 return context;
1417 }
1418
1419 public static ActivityManagerService self() {
1420 return mSelf;
1421 }
1422
1423 static class AThread extends Thread {
1424 ActivityManagerService mService;
1425 boolean mReady = false;
1426
1427 public AThread() {
1428 super("ActivityManager");
1429 }
1430
1431 public void run() {
1432 Looper.prepare();
1433
1434 android.os.Process.setThreadPriority(
1435 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1436
1437 ActivityManagerService m = new ActivityManagerService();
1438
1439 synchronized (this) {
1440 mService = m;
1441 notifyAll();
1442 }
1443
1444 synchronized (this) {
1445 while (!mReady) {
1446 try {
1447 wait();
1448 } catch (InterruptedException e) {
1449 }
1450 }
1451 }
1452
1453 Looper.loop();
1454 }
1455 }
1456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 static class MemBinder extends Binder {
1458 ActivityManagerService mActivityManagerService;
1459 MemBinder(ActivityManagerService activityManagerService) {
1460 mActivityManagerService = activityManagerService;
1461 }
1462
1463 @Override
1464 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1465 ActivityManagerService service = mActivityManagerService;
1466 ArrayList<ProcessRecord> procs;
1467 synchronized (mActivityManagerService) {
1468 if (args != null && args.length > 0
1469 && args[0].charAt(0) != '-') {
1470 procs = new ArrayList<ProcessRecord>();
1471 int pid = -1;
1472 try {
1473 pid = Integer.parseInt(args[0]);
1474 } catch (NumberFormatException e) {
1475
1476 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001477 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1478 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 if (proc.pid == pid) {
1480 procs.add(proc);
1481 } else if (proc.processName.equals(args[0])) {
1482 procs.add(proc);
1483 }
1484 }
1485 if (procs.size() <= 0) {
1486 pw.println("No process found for: " + args[0]);
1487 return;
1488 }
1489 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001490 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 }
1492 }
1493 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1494 }
1495 }
1496
1497 static class CpuBinder extends Binder {
1498 ActivityManagerService mActivityManagerService;
1499 CpuBinder(ActivityManagerService activityManagerService) {
1500 mActivityManagerService = activityManagerService;
1501 }
1502
1503 @Override
1504 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1505 synchronized (mActivityManagerService.mProcessStatsThread) {
1506 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1507 }
1508 }
1509 }
1510
1511 private ActivityManagerService() {
1512 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1513 if (v != null && Integer.getInteger(v) != 0) {
1514 mSimpleProcessManagement = true;
1515 }
1516 v = System.getenv("ANDROID_DEBUG_APP");
1517 if (v != null) {
1518 mSimpleProcessManagement = true;
1519 }
1520
Joe Onorato8a9b2202010-02-26 18:56:32 -08001521 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 File dataDir = Environment.getDataDirectory();
1524 File systemDir = new File(dataDir, "system");
1525 systemDir.mkdirs();
1526 mBatteryStatsService = new BatteryStatsService(new File(
1527 systemDir, "batterystats.bin").toString());
1528 mBatteryStatsService.getActiveStatistics().readLocked();
1529 mBatteryStatsService.getActiveStatistics().writeLocked();
1530
1531 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001532 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533
Jack Palevichb90d28c2009-07-22 15:35:24 -07001534 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1535 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1536
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001537 mConfiguration.setToDefaults();
1538 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 mProcessStats.init();
1540
1541 // Add ourself to the Watchdog monitors.
1542 Watchdog.getInstance().addMonitor(this);
1543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 mProcessStatsThread = new Thread("ProcessStats") {
1545 public void run() {
1546 while (true) {
1547 try {
1548 try {
1549 synchronized(this) {
1550 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001551 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001553 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 // + ", write delay=" + nextWriteDelay);
1555 if (nextWriteDelay < nextCpuDelay) {
1556 nextCpuDelay = nextWriteDelay;
1557 }
1558 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001559 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 this.wait(nextCpuDelay);
1561 }
1562 }
1563 } catch (InterruptedException e) {
1564 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 updateCpuStatsNow();
1566 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001567 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 }
1569 }
1570 }
1571 };
1572 mProcessStatsThread.start();
1573 }
1574
1575 @Override
1576 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1577 throws RemoteException {
1578 try {
1579 return super.onTransact(code, data, reply, flags);
1580 } catch (RuntimeException e) {
1581 // The activity manager only throws security exceptions, so let's
1582 // log all others.
1583 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001584 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 }
1586 throw e;
1587 }
1588 }
1589
1590 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001591 final long now = SystemClock.uptimeMillis();
1592 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1593 return;
1594 }
1595 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1596 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 mProcessStatsThread.notify();
1598 }
1599 }
1600 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 void updateCpuStatsNow() {
1603 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001604 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 final long now = SystemClock.uptimeMillis();
1606 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001609 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1610 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 haveNewCpuStats = true;
1612 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001613 //Slog.i(TAG, mProcessStats.printCurrentState());
1614 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 // + mProcessStats.getTotalCpuPercent() + "%");
1616
Joe Onorato8a9b2202010-02-26 18:56:32 -08001617 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 if ("true".equals(SystemProperties.get("events.cpu"))) {
1619 int user = mProcessStats.getLastUserTime();
1620 int system = mProcessStats.getLastSystemTime();
1621 int iowait = mProcessStats.getLastIoWaitTime();
1622 int irq = mProcessStats.getLastIrqTime();
1623 int softIrq = mProcessStats.getLastSoftIrqTime();
1624 int idle = mProcessStats.getLastIdleTime();
1625
1626 int total = user + system + iowait + irq + softIrq + idle;
1627 if (total == 0) total = 1;
1628
Doug Zongker2bec3d42009-12-04 12:52:44 -08001629 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 ((user+system+iowait+irq+softIrq) * 100) / total,
1631 (user * 100) / total,
1632 (system * 100) / total,
1633 (iowait * 100) / total,
1634 (irq * 100) / total,
1635 (softIrq * 100) / total);
1636 }
1637 }
1638
Amith Yamasanie43530a2009-08-21 13:11:37 -07001639 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001640 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001641 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 synchronized(mPidsSelfLocked) {
1643 if (haveNewCpuStats) {
1644 if (mBatteryStatsService.isOnBattery()) {
1645 final int N = mProcessStats.countWorkingStats();
1646 for (int i=0; i<N; i++) {
1647 ProcessStats.Stats st
1648 = mProcessStats.getWorkingStats(i);
1649 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1650 if (pr != null) {
1651 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1652 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001653 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001654 } else {
1655 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001656 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001657 if (ps != null) {
1658 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001659 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 }
1662 }
1663 }
1664 }
1665 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1668 mLastWriteTime = now;
1669 mBatteryStatsService.getActiveStatistics().writeLocked();
1670 }
1671 }
1672 }
1673 }
1674
1675 /**
1676 * Initialize the application bind args. These are passed to each
1677 * process when the bindApplication() IPC is sent to the process. They're
1678 * lazily setup to make sure the services are running when they're asked for.
1679 */
1680 private HashMap<String, IBinder> getCommonServicesLocked() {
1681 if (mAppBindArgs == null) {
1682 mAppBindArgs = new HashMap<String, IBinder>();
1683
1684 // Setup the application init args
1685 mAppBindArgs.put("package", ServiceManager.getService("package"));
1686 mAppBindArgs.put("window", ServiceManager.getService("window"));
1687 mAppBindArgs.put(Context.ALARM_SERVICE,
1688 ServiceManager.getService(Context.ALARM_SERVICE));
1689 }
1690 return mAppBindArgs;
1691 }
1692
1693 private final void setFocusedActivityLocked(HistoryRecord r) {
1694 if (mFocusedActivity != r) {
1695 mFocusedActivity = r;
1696 mWindowManager.setFocusedApp(r, true);
1697 }
1698 }
1699
Dianne Hackborn906497c2010-05-10 15:57:38 -07001700 private final void updateLruProcessInternalLocked(ProcessRecord app,
1701 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001703 int lrui = mLruProcesses.indexOf(app);
1704 if (lrui >= 0) mLruProcesses.remove(lrui);
1705
1706 int i = mLruProcesses.size()-1;
1707 int skipTop = 0;
1708
Dianne Hackborn906497c2010-05-10 15:57:38 -07001709 app.lruSeq = mLruSeq;
1710
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001711 // compute the new weight for this process.
1712 if (updateActivityTime) {
1713 app.lastActivityTime = SystemClock.uptimeMillis();
1714 }
1715 if (app.activities.size() > 0) {
1716 // If this process has activities, we more strongly want to keep
1717 // it around.
1718 app.lruWeight = app.lastActivityTime;
1719 } else if (app.pubProviders.size() > 0) {
1720 // If this process contains content providers, we want to keep
1721 // it a little more strongly.
1722 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1723 // Also don't let it kick out the first few "real" hidden processes.
1724 skipTop = MIN_HIDDEN_APPS;
1725 } else {
1726 // If this process doesn't have activities, we less strongly
1727 // want to keep it around, and generally want to avoid getting
1728 // in front of any very recently used activities.
1729 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1730 // Also don't let it kick out the first few "real" hidden processes.
1731 skipTop = MIN_HIDDEN_APPS;
1732 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001733
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001734 while (i >= 0) {
1735 ProcessRecord p = mLruProcesses.get(i);
1736 // If this app shouldn't be in front of the first N background
1737 // apps, then skip over that many that are currently hidden.
1738 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1739 skipTop--;
1740 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001741 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001742 mLruProcesses.add(i+1, app);
1743 break;
1744 }
1745 i--;
1746 }
1747 if (i < 0) {
1748 mLruProcesses.add(0, app);
1749 }
1750
Dianne Hackborn906497c2010-05-10 15:57:38 -07001751 // If the app is currently using a content provider or service,
1752 // bump those processes as well.
1753 if (app.connections.size() > 0) {
1754 for (ConnectionRecord cr : app.connections) {
1755 if (cr.binding != null && cr.binding.service != null
1756 && cr.binding.service.app != null
1757 && cr.binding.service.app.lruSeq != mLruSeq) {
1758 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1759 updateActivityTime, i+1);
1760 }
1761 }
1762 }
1763 if (app.conProviders.size() > 0) {
1764 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1765 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1766 updateLruProcessInternalLocked(cpr.app, oomAdj,
1767 updateActivityTime, i+1);
1768 }
1769 }
1770 }
1771
Joe Onorato8a9b2202010-02-26 18:56:32 -08001772 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 if (oomAdj) {
1774 updateOomAdjLocked();
1775 }
1776 }
1777
Dianne Hackborn906497c2010-05-10 15:57:38 -07001778 private final void updateLruProcessLocked(ProcessRecord app,
1779 boolean oomAdj, boolean updateActivityTime) {
1780 mLruSeq++;
1781 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1782 }
1783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 private final boolean updateLRUListLocked(HistoryRecord r) {
1785 final boolean hadit = mLRUActivities.remove(r);
1786 mLRUActivities.add(r);
1787 return hadit;
1788 }
1789
1790 private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
1791 int i = mHistory.size()-1;
1792 while (i >= 0) {
1793 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1794 if (!r.finishing && r != notTop) {
1795 return r;
1796 }
1797 i--;
1798 }
1799 return null;
1800 }
1801
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001802 private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
1803 int i = mHistory.size()-1;
1804 while (i >= 0) {
1805 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1806 if (!r.finishing && !r.delayedResume && r != notTop) {
1807 return r;
1808 }
1809 i--;
1810 }
1811 return null;
1812 }
1813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 /**
1815 * This is a simplified version of topRunningActivityLocked that provides a number of
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001816 * optional skip-over modes. It is intended for use with the ActivityController hook only.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 *
1818 * @param token If non-null, any history records matching this token will be skipped.
1819 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
1820 *
1821 * @return Returns the HistoryRecord of the next activity on the stack.
1822 */
1823 private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
1824 int i = mHistory.size()-1;
1825 while (i >= 0) {
1826 HistoryRecord r = (HistoryRecord)mHistory.get(i);
1827 // Note: the taskId check depends on real taskId fields being non-zero
1828 if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
1829 return r;
1830 }
1831 i--;
1832 }
1833 return null;
1834 }
1835
1836 private final ProcessRecord getProcessRecordLocked(
1837 String processName, int uid) {
1838 if (uid == Process.SYSTEM_UID) {
1839 // The system gets to run in any process. If there are multiple
1840 // processes with the same uid, just pick the first (this
1841 // should never happen).
1842 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1843 processName);
1844 return procs != null ? procs.valueAt(0) : null;
1845 }
1846 ProcessRecord proc = mProcessNames.get(processName, uid);
1847 return proc;
1848 }
1849
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001850 private void ensurePackageDexOpt(String packageName) {
1851 IPackageManager pm = ActivityThread.getPackageManager();
1852 try {
1853 if (pm.performDexOpt(packageName)) {
1854 mDidDexOpt = true;
1855 }
1856 } catch (RemoteException e) {
1857 }
1858 }
1859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 private boolean isNextTransitionForward() {
1861 int transit = mWindowManager.getPendingAppTransition();
1862 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1863 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1864 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1865 }
1866
1867 private final boolean realStartActivityLocked(HistoryRecord r,
1868 ProcessRecord app, boolean andResume, boolean checkConfig)
1869 throws RemoteException {
1870
1871 r.startFreezingScreenLocked(app, 0);
1872 mWindowManager.setAppVisibility(r, true);
1873
1874 // Have the window manager re-evaluate the orientation of
1875 // the screen based on the new activity order. Note that
1876 // as a result of this, it can call back into the activity
1877 // manager with a new orientation. We don't care about that,
1878 // because the activity is not currently running so we are
1879 // just restarting it anyway.
1880 if (checkConfig) {
1881 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07001882 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 r.mayFreezeScreenLocked(app) ? r : null);
1884 updateConfigurationLocked(config, r);
1885 }
1886
1887 r.app = app;
1888
Joe Onorato8a9b2202010-02-26 18:56:32 -08001889 if (localLOGV) Slog.v(TAG, "Launching: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890
1891 int idx = app.activities.indexOf(r);
1892 if (idx < 0) {
1893 app.activities.add(r);
1894 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001895 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896
1897 try {
1898 if (app.thread == null) {
1899 throw new RemoteException();
1900 }
1901 List<ResultInfo> results = null;
1902 List<Intent> newIntents = null;
1903 if (andResume) {
1904 results = r.results;
1905 newIntents = r.newIntents;
1906 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001907 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001908 + " icicle=" + r.icicle
1909 + " with results=" + results + " newIntents=" + newIntents
1910 + " andResume=" + andResume);
1911 if (andResume) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001912 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 System.identityHashCode(r),
1914 r.task.taskId, r.shortComponentName);
1915 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001916 if (r.isHomeActivity) {
1917 mHomeProcess = app;
1918 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001919 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001921 System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 r.info, r.icicle, results, newIntents, !andResume,
1923 isNextTransitionForward());
Dianne Hackborn860755f2010-06-03 18:47:52 -07001924
1925 if ((app.info.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
1926 // This may be a heavy-weight process! Note that the package
1927 // manager will ensure that only activity can run in the main
1928 // process of the .apk, which is the only thing that will be
1929 // considered heavy-weight.
1930 if (app.processName.equals(app.info.packageName)) {
1931 if (mHeavyWeightProcess != null && mHeavyWeightProcess != app) {
1932 Log.w(TAG, "Starting new heavy weight process " + app
1933 + " when already running " + mHeavyWeightProcess);
1934 }
1935 mHeavyWeightProcess = app;
1936 Message msg = mHandler.obtainMessage(POST_HEAVY_NOTIFICATION_MSG);
1937 msg.obj = r;
1938 mHandler.sendMessage(msg);
1939 }
1940 }
1941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 } catch (RemoteException e) {
1943 if (r.launchFailed) {
1944 // This is the second time we failed -- finish activity
1945 // and give up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001946 Slog.e(TAG, "Second failure launching "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001947 + r.intent.getComponent().flattenToShortString()
1948 + ", giving up", e);
1949 appDiedLocked(app, app.pid, app.thread);
1950 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
1951 "2nd-crash");
1952 return false;
1953 }
1954
1955 // This is the first time we failed -- restart process and
1956 // retry.
1957 app.activities.remove(r);
1958 throw e;
1959 }
1960
1961 r.launchFailed = false;
1962 if (updateLRUListLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001963 Slog.w(TAG, "Activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001964 + " being launched, but already in LRU list");
1965 }
1966
1967 if (andResume) {
1968 // As part of the process of launching, ActivityThread also performs
1969 // a resume.
1970 r.state = ActivityState.RESUMED;
1971 r.icicle = null;
1972 r.haveState = false;
1973 r.stopped = false;
1974 mResumedActivity = r;
1975 r.task.touchActiveTime();
1976 completeResumeLocked(r);
1977 pauseIfSleepingLocked();
1978 } else {
1979 // This activity is not starting in the resumed state... which
1980 // should look like we asked it to pause+stop (but remain visible),
1981 // and it has done so and reported back the current icicle and
1982 // other state.
1983 r.state = ActivityState.STOPPED;
1984 r.stopped = true;
1985 }
1986
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001987 // Launch the new version setup screen if needed. We do this -after-
1988 // launching the initial activity (that is, home), so that it can have
1989 // a chance to initialize itself while in the background, making the
1990 // switch back to it faster and look better.
1991 startSetupActivityLocked();
1992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 return true;
1994 }
1995
1996 private final void startSpecificActivityLocked(HistoryRecord r,
1997 boolean andResume, boolean checkConfig) {
1998 // Is this activity's application already running?
1999 ProcessRecord app = getProcessRecordLocked(r.processName,
2000 r.info.applicationInfo.uid);
2001
2002 if (r.startTime == 0) {
2003 r.startTime = SystemClock.uptimeMillis();
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002004 if (mInitialStartTime == 0) {
2005 mInitialStartTime = r.startTime;
2006 }
2007 } else if (mInitialStartTime == 0) {
2008 mInitialStartTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002009 }
2010
2011 if (app != null && app.thread != null) {
2012 try {
2013 realStartActivityLocked(r, app, andResume, checkConfig);
2014 return;
2015 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002016 Slog.w(TAG, "Exception when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 + r.intent.getComponent().flattenToShortString(), e);
2018 }
2019
2020 // If a dead object exception was thrown -- fall through to
2021 // restart the application.
2022 }
2023
2024 startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002025 "activity", r.intent.getComponent(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 }
2027
2028 private final ProcessRecord startProcessLocked(String processName,
2029 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002030 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
2032 // We don't have to do anything more if:
2033 // (1) There is an existing application record; and
2034 // (2) The caller doesn't think it is dead, OR there is no thread
2035 // object attached to it so we know it couldn't have crashed; and
2036 // (3) There is a pid assigned to it, so it is either starting or
2037 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002038 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039 + " app=" + app + " knownToBeDead=" + knownToBeDead
2040 + " thread=" + (app != null ? app.thread : null)
2041 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01002042 if (app != null && app.pid > 0) {
2043 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002044 // We already have the app running, or are waiting for it to
2045 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01002046 return app;
2047 } else {
2048 // An application record is attached to a previous process,
2049 // clean it up now.
2050 handleAppDiedLocked(app, true);
2051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002052 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 String hostingNameStr = hostingName != null
2055 ? hostingName.flattenToShortString() : null;
2056
2057 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
2058 // If we are in the background, then check to see if this process
2059 // is bad. If so, we will just silently fail.
2060 if (mBadProcesses.get(info.processName, info.uid) != null) {
2061 return null;
2062 }
2063 } else {
2064 // When the user is explicitly starting a process, then clear its
2065 // crash count so that we won't make it bad until they see at
2066 // least one crash dialog again, and make the process good again
2067 // if it had been bad.
2068 mProcessCrashTimes.remove(info.processName, info.uid);
2069 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002070 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 info.processName);
2072 mBadProcesses.remove(info.processName, info.uid);
2073 if (app != null) {
2074 app.bad = false;
2075 }
2076 }
2077 }
2078
2079 if (app == null) {
2080 app = newProcessRecordLocked(null, info, processName);
2081 mProcessNames.put(processName, info.uid, app);
2082 } else {
2083 // If this is a new package in the process, add the package to the list
2084 app.addPackage(info.packageName);
2085 }
2086
2087 // If the system is not ready yet, then hold off on starting this
2088 // process until it is.
2089 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002090 && !isAllowedWhileBooting(info)
2091 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002092 if (!mProcessesOnHold.contains(app)) {
2093 mProcessesOnHold.add(app);
2094 }
2095 return app;
2096 }
2097
2098 startProcessLocked(app, hostingType, hostingNameStr);
2099 return (app.pid != 0) ? app : null;
2100 }
2101
Dianne Hackborn9acc0302009-08-25 00:27:12 -07002102 boolean isAllowedWhileBooting(ApplicationInfo ai) {
2103 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
2104 }
2105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002106 private final void startProcessLocked(ProcessRecord app,
2107 String hostingType, String hostingNameStr) {
2108 if (app.pid > 0 && app.pid != MY_PID) {
2109 synchronized (mPidsSelfLocked) {
2110 mPidsSelfLocked.remove(app.pid);
2111 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
2112 }
2113 app.pid = 0;
2114 }
2115
2116 mProcessesOnHold.remove(app);
2117
2118 updateCpuStats();
2119
2120 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
2121 mProcDeaths[0] = 0;
2122
2123 try {
2124 int uid = app.info.uid;
2125 int[] gids = null;
2126 try {
2127 gids = mContext.getPackageManager().getPackageGids(
2128 app.info.packageName);
2129 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002130 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131 }
2132 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
2133 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2134 && mTopComponent != null
2135 && app.processName.equals(mTopComponent.getPackageName())) {
2136 uid = 0;
2137 }
2138 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
2139 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
2140 uid = 0;
2141 }
2142 }
2143 int debugFlags = 0;
2144 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
2145 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
2146 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08002147 // Run the app in safe mode if its manifest requests so or the
2148 // system is booted in safe mode.
2149 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
2150 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08002151 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
2152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
2154 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
2155 }
2156 if ("1".equals(SystemProperties.get("debug.assert"))) {
2157 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2158 }
2159 int pid = Process.start("android.app.ActivityThread",
2160 mSimpleProcessManagement ? app.processName : null, uid, uid,
2161 gids, debugFlags, null);
2162 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2163 synchronized (bs) {
2164 if (bs.isOnBattery()) {
2165 app.batteryStats.incStartsLocked();
2166 }
2167 }
2168
Doug Zongker2bec3d42009-12-04 12:52:44 -08002169 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 app.processName, hostingType,
2171 hostingNameStr != null ? hostingNameStr : "");
2172
2173 if (app.persistent) {
2174 Watchdog.getInstance().processStarted(app, app.processName, pid);
2175 }
2176
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002177 StringBuilder buf = mStringBuilder;
2178 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 buf.append("Start proc ");
2180 buf.append(app.processName);
2181 buf.append(" for ");
2182 buf.append(hostingType);
2183 if (hostingNameStr != null) {
2184 buf.append(" ");
2185 buf.append(hostingNameStr);
2186 }
2187 buf.append(": pid=");
2188 buf.append(pid);
2189 buf.append(" uid=");
2190 buf.append(uid);
2191 buf.append(" gids={");
2192 if (gids != null) {
2193 for (int gi=0; gi<gids.length; gi++) {
2194 if (gi != 0) buf.append(", ");
2195 buf.append(gids[gi]);
2196
2197 }
2198 }
2199 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002200 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 if (pid == 0 || pid == MY_PID) {
2202 // Processes are being emulated with threads.
2203 app.pid = MY_PID;
2204 app.removed = false;
2205 mStartingProcesses.add(app);
2206 } else if (pid > 0) {
2207 app.pid = pid;
2208 app.removed = false;
2209 synchronized (mPidsSelfLocked) {
2210 this.mPidsSelfLocked.put(pid, app);
2211 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2212 msg.obj = app;
2213 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
2214 }
2215 } else {
2216 app.pid = 0;
2217 RuntimeException e = new RuntimeException(
2218 "Failure starting process " + app.processName
2219 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002220 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221 }
2222 } catch (RuntimeException e) {
2223 // XXX do better error recovery.
2224 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002225 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002226 }
2227 }
2228
2229 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
2230 if (mPausingActivity != null) {
2231 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002232 Slog.e(TAG, "Trying to pause when pause is already pending for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 + mPausingActivity, e);
2234 }
2235 HistoryRecord prev = mResumedActivity;
2236 if (prev == null) {
2237 RuntimeException e = new RuntimeException();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002238 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002239 resumeTopActivityLocked(null);
2240 return;
2241 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002242 if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 mResumedActivity = null;
2244 mPausingActivity = prev;
2245 mLastPausedActivity = prev;
2246 prev.state = ActivityState.PAUSING;
2247 prev.task.touchActiveTime();
2248
2249 updateCpuStats();
2250
2251 if (prev.app != null && prev.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002252 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 try {
Doug Zongker2bec3d42009-12-04 12:52:44 -08002254 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002255 System.identityHashCode(prev),
2256 prev.shortComponentName);
2257 prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
2258 prev.configChangeFlags);
2259 updateUsageStats(prev, false);
2260 } catch (Exception e) {
2261 // Ignore exception, if process died other code will cleanup.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002262 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263 mPausingActivity = null;
2264 mLastPausedActivity = null;
2265 }
2266 } else {
2267 mPausingActivity = null;
2268 mLastPausedActivity = null;
2269 }
2270
2271 // If we are not going to sleep, we want to ensure the device is
2272 // awake until the next activity is started.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002273 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 mLaunchingActivity.acquire();
2275 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
2276 // To be safe, don't allow the wake lock to be held for too long.
2277 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
2278 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
2279 }
2280 }
2281
2282
2283 if (mPausingActivity != null) {
2284 // Have the window manager pause its key dispatching until the new
2285 // activity has started. If we're pausing the activity just because
2286 // the screen is being turned off and the UI is sleeping, don't interrupt
2287 // key dispatch; the same activity will pick it up again on wakeup.
2288 if (!uiSleeping) {
2289 prev.pauseKeyDispatchingLocked();
2290 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002291 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292 }
2293
2294 // Schedule a pause timeout in case the app doesn't respond.
2295 // We don't give it much time because this directly impacts the
2296 // responsiveness seen by the user.
2297 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
2298 msg.obj = prev;
2299 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002300 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301 } else {
2302 // This activity failed to schedule the
2303 // pause, so just treat it as being paused now.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002304 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 resumeTopActivityLocked(null);
2306 }
2307 }
2308
2309 private final void completePauseLocked() {
2310 HistoryRecord prev = mPausingActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002311 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312
2313 if (prev != null) {
2314 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002315 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002316 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
2317 } else if (prev.app != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002318 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002319 if (prev.waitingVisible) {
2320 prev.waitingVisible = false;
2321 mWaitingVisibleActivities.remove(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002322 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 TAG, "Complete pause, no longer waiting: " + prev);
2324 }
2325 if (prev.configDestroy) {
2326 // The previous is being paused because the configuration
2327 // is changing, which means it is actually stopping...
2328 // To juggle the fact that we are also starting a new
2329 // instance right now, we need to first completely stop
2330 // the current instance before starting the new one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002331 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 destroyActivityLocked(prev, true);
2333 } else {
2334 mStoppingActivities.add(prev);
2335 if (mStoppingActivities.size() > 3) {
2336 // If we already have a few activities waiting to stop,
2337 // then give up on things going idle and start clearing
2338 // them out.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002339 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002340 Message msg = Message.obtain();
2341 msg.what = ActivityManagerService.IDLE_NOW_MSG;
2342 mHandler.sendMessage(msg);
2343 }
2344 }
2345 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002346 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002347 prev = null;
2348 }
2349 mPausingActivity = null;
2350 }
2351
Dianne Hackborn55280a92009-05-07 15:53:46 -07002352 if (!mSleeping && !mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 resumeTopActivityLocked(prev);
2354 } else {
2355 if (mGoingToSleep.isHeld()) {
2356 mGoingToSleep.release();
2357 }
Dianne Hackborn55280a92009-05-07 15:53:46 -07002358 if (mShuttingDown) {
2359 notifyAll();
2360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 }
2362
2363 if (prev != null) {
2364 prev.resumeKeyDispatchingLocked();
2365 }
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002366
2367 if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
2368 long diff = 0;
2369 synchronized (mProcessStatsThread) {
2370 diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
2371 }
2372 if (diff > 0) {
2373 BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
2374 synchronized (bsi) {
2375 BatteryStatsImpl.Uid.Proc ps =
2376 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
2377 prev.info.packageName);
2378 if (ps != null) {
2379 ps.addForegroundTimeLocked(diff);
2380 }
2381 }
2382 }
2383 }
2384 prev.cpuTimeAtResume = 0; // reset it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 }
2386
2387 /**
2388 * Once we know that we have asked an application to put an activity in
2389 * the resumed state (either by launching it or explicitly telling it),
2390 * this function updates the rest of our state to match that fact.
2391 */
2392 private final void completeResumeLocked(HistoryRecord next) {
2393 next.idle = false;
2394 next.results = null;
2395 next.newIntents = null;
2396
2397 // schedule an idle timeout in case the app doesn't do it for us.
2398 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2399 msg.obj = next;
2400 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2401
2402 if (false) {
2403 // The activity was never told to pause, so just keep
2404 // things going as-is. To maintain our own state,
2405 // we need to emulate it coming back and saying it is
2406 // idle.
2407 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
2408 msg.obj = next;
2409 mHandler.sendMessage(msg);
2410 }
2411
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002412 reportResumedActivityLocked(next);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002414 next.thumbnail = null;
2415 setFocusedActivityLocked(next);
2416 next.resumeKeyDispatchingLocked();
2417 ensureActivitiesVisibleLocked(null, 0);
2418 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002419 mNoAnimActivities.clear();
Amith Yamasanieaeb6632009-06-03 15:16:10 -07002420
2421 // Mark the point when the activity is resuming
2422 // TODO: To be more accurate, the mark should be before the onCreate,
2423 // not after the onResume. But for subsequent starts, onResume is fine.
2424 if (next.app != null) {
2425 synchronized (mProcessStatsThread) {
2426 next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
2427 }
2428 } else {
2429 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002431 }
2432
2433 /**
2434 * Make sure that all activities that need to be visible (that is, they
2435 * currently can be seen by the user) actually are.
2436 */
2437 private final void ensureActivitiesVisibleLocked(HistoryRecord top,
2438 HistoryRecord starting, String onlyThisProcess, int configChanges) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002439 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002440 TAG, "ensureActivitiesVisible behind " + top
2441 + " configChanges=0x" + Integer.toHexString(configChanges));
2442
2443 // If the top activity is not fullscreen, then we need to
2444 // make sure any activities under it are now visible.
2445 final int count = mHistory.size();
2446 int i = count-1;
2447 while (mHistory.get(i) != top) {
2448 i--;
2449 }
2450 HistoryRecord r;
2451 boolean behindFullscreen = false;
2452 for (; i>=0; i--) {
2453 r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002454 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002455 TAG, "Make visible? " + r + " finishing=" + r.finishing
2456 + " state=" + r.state);
2457 if (r.finishing) {
2458 continue;
2459 }
2460
2461 final boolean doThisProcess = onlyThisProcess == null
2462 || onlyThisProcess.equals(r.processName);
2463
2464 // First: if this is not the current activity being started, make
2465 // sure it matches the current configuration.
2466 if (r != starting && doThisProcess) {
2467 ensureActivityConfigurationLocked(r, 0);
2468 }
2469
2470 if (r.app == null || r.app.thread == null) {
2471 if (onlyThisProcess == null
2472 || onlyThisProcess.equals(r.processName)) {
2473 // This activity needs to be visible, but isn't even
2474 // running... get it started, but don't resume it
2475 // at this point.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002476 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 TAG, "Start and freeze screen for " + r);
2478 if (r != starting) {
2479 r.startFreezingScreenLocked(r.app, configChanges);
2480 }
2481 if (!r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002482 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002483 TAG, "Starting and making visible: " + r);
2484 mWindowManager.setAppVisibility(r, true);
2485 }
2486 if (r != starting) {
2487 startSpecificActivityLocked(r, false, false);
2488 }
2489 }
2490
2491 } else if (r.visible) {
2492 // If this activity is already visible, then there is nothing
2493 // else to do here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002494 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 TAG, "Skipping: already visible at " + r);
2496 r.stopFreezingScreenLocked(false);
2497
2498 } else if (onlyThisProcess == null) {
2499 // This activity is not currently visible, but is running.
2500 // Tell it to become visible.
2501 r.visible = true;
2502 if (r.state != ActivityState.RESUMED && r != starting) {
2503 // If this activity is paused, tell it
2504 // to now show its window.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002505 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 TAG, "Making visible and scheduling visibility: " + r);
2507 try {
2508 mWindowManager.setAppVisibility(r, true);
2509 r.app.thread.scheduleWindowVisibility(r, true);
2510 r.stopFreezingScreenLocked(false);
2511 } catch (Exception e) {
2512 // Just skip on any failure; we'll make it
2513 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002514 Slog.w(TAG, "Exception thrown making visibile: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 + r.intent.getComponent(), e);
2516 }
2517 }
2518 }
2519
2520 // Aggregate current change flags.
2521 configChanges |= r.configChangeFlags;
2522
2523 if (r.fullscreen) {
2524 // At this point, nothing else needs to be shown
Joe Onorato8a9b2202010-02-26 18:56:32 -08002525 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 TAG, "Stopping: fullscreen at " + r);
2527 behindFullscreen = true;
2528 i--;
2529 break;
2530 }
2531 }
2532
2533 // Now for any activities that aren't visible to the user, make
2534 // sure they no longer are keeping the screen frozen.
2535 while (i >= 0) {
2536 r = (HistoryRecord)mHistory.get(i);
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, "Make invisible? " + r + " finishing=" + r.finishing
2539 + " state=" + r.state
2540 + " behindFullscreen=" + behindFullscreen);
2541 if (!r.finishing) {
2542 if (behindFullscreen) {
2543 if (r.visible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002544 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 TAG, "Making invisible: " + r);
2546 r.visible = false;
2547 try {
2548 mWindowManager.setAppVisibility(r, false);
2549 if ((r.state == ActivityState.STOPPING
2550 || r.state == ActivityState.STOPPED)
2551 && r.app != null && r.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002552 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 TAG, "Scheduling invisibility: " + r);
2554 r.app.thread.scheduleWindowVisibility(r, false);
2555 }
2556 } catch (Exception e) {
2557 // Just skip on any failure; we'll make it
2558 // visible when it next restarts.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002559 Slog.w(TAG, "Exception thrown making hidden: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 + r.intent.getComponent(), e);
2561 }
2562 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002563 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002564 TAG, "Already invisible: " + r);
2565 }
2566 } else if (r.fullscreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002567 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 TAG, "Now behindFullscreen: " + r);
2569 behindFullscreen = true;
2570 }
2571 }
2572 i--;
2573 }
2574 }
2575
2576 /**
2577 * Version of ensureActivitiesVisible that can easily be called anywhere.
2578 */
2579 private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
2580 int configChanges) {
2581 HistoryRecord r = topRunningActivityLocked(null);
2582 if (r != null) {
2583 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
2584 }
2585 }
2586
2587 private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
2588 if (resumed) {
2589 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2590 } else {
2591 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2592 }
2593 }
2594
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002595 private boolean startHomeActivityLocked() {
2596 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2597 && mTopAction == null) {
2598 // We are running in factory test mode, but unable to find
2599 // the factory test app, so just sit around displaying the
2600 // error message and don't try to start anything.
2601 return false;
2602 }
2603 Intent intent = new Intent(
2604 mTopAction,
2605 mTopData != null ? Uri.parse(mTopData) : null);
2606 intent.setComponent(mTopComponent);
2607 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2608 intent.addCategory(Intent.CATEGORY_HOME);
2609 }
2610 ActivityInfo aInfo =
2611 intent.resolveActivityInfo(mContext.getPackageManager(),
2612 STOCK_PM_FLAGS);
2613 if (aInfo != null) {
2614 intent.setComponent(new ComponentName(
2615 aInfo.applicationInfo.packageName, aInfo.name));
2616 // Don't do this if the home app is currently being
2617 // instrumented.
2618 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2619 aInfo.applicationInfo.uid);
2620 if (app == null || app.instrumentationClass == null) {
2621 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
2622 startActivityLocked(null, intent, null, null, 0, aInfo,
2623 null, null, 0, 0, 0, false, false);
2624 }
2625 }
2626
2627
2628 return true;
2629 }
2630
2631 /**
2632 * Starts the "new version setup screen" if appropriate.
2633 */
2634 private void startSetupActivityLocked() {
2635 // Only do this once per boot.
2636 if (mCheckedForSetup) {
2637 return;
2638 }
2639
2640 // We will show this screen if the current one is a different
2641 // version than the last one shown, and we are not running in
2642 // low-level factory test mode.
2643 final ContentResolver resolver = mContext.getContentResolver();
2644 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2645 Settings.Secure.getInt(resolver,
2646 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2647 mCheckedForSetup = true;
2648
2649 // See if we should be showing the platform update setup UI.
2650 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2651 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2652 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2653
2654 // We don't allow third party apps to replace this.
2655 ResolveInfo ri = null;
2656 for (int i=0; ris != null && i<ris.size(); i++) {
2657 if ((ris.get(i).activityInfo.applicationInfo.flags
2658 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2659 ri = ris.get(i);
2660 break;
2661 }
2662 }
2663
2664 if (ri != null) {
2665 String vers = ri.activityInfo.metaData != null
2666 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2667 : null;
2668 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2669 vers = ri.activityInfo.applicationInfo.metaData.getString(
2670 Intent.METADATA_SETUP_VERSION);
2671 }
2672 String lastVers = Settings.Secure.getString(
2673 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2674 if (vers != null && !vers.equals(lastVers)) {
2675 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2676 intent.setComponent(new ComponentName(
2677 ri.activityInfo.packageName, ri.activityInfo.name));
2678 startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
2679 null, null, 0, 0, 0, false, false);
2680 }
2681 }
2682 }
2683 }
2684
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -07002685 private void reportResumedActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002686 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002687
2688 final int identHash = System.identityHashCode(r);
2689 updateUsageStats(r, true);
2690
2691 int i = mWatchers.beginBroadcast();
2692 while (i > 0) {
2693 i--;
2694 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2695 if (w != null) {
2696 try {
2697 w.activityResuming(identHash);
2698 } catch (RemoteException e) {
2699 }
2700 }
2701 }
2702 mWatchers.finishBroadcast();
2703 }
2704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 /**
2706 * Ensure that the top activity in the stack is resumed.
2707 *
2708 * @param prev The previously resumed activity, for when in the process
2709 * of pausing; can be null to call from elsewhere.
2710 *
2711 * @return Returns true if something is being resumed, or false if
2712 * nothing happened.
2713 */
2714 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
2715 // Find the first activity that is not finishing.
2716 HistoryRecord next = topRunningActivityLocked(null);
2717
2718 // Remember how we'll process this pause/resume situation, and ensure
2719 // that the state is reset however we wind up proceeding.
2720 final boolean userLeaving = mUserLeaving;
2721 mUserLeaving = false;
2722
2723 if (next == null) {
2724 // There are no more activities! Let's just start up the
2725 // Launcher...
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002726 return startHomeActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 }
2728
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002729 next.delayedResume = false;
2730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 // If the top activity is the resumed one, nothing to do.
2732 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
2733 // Make sure we have executed any pending transitions, since there
2734 // should be nothing left to do at this point.
2735 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002736 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 return false;
2738 }
2739
2740 // If we are sleeping, and there is no resumed activity, and the top
2741 // activity is paused, well that is the state we want.
Dianne Hackborn55280a92009-05-07 15:53:46 -07002742 if ((mSleeping || mShuttingDown)
2743 && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744 // Make sure we have executed any pending transitions, since there
2745 // should be nothing left to do at this point.
2746 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002747 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 return false;
2749 }
2750
2751 // The activity may be waiting for stop, but that is no longer
2752 // appropriate for it.
2753 mStoppingActivities.remove(next);
2754 mWaitingVisibleActivities.remove(next);
2755
Joe Onorato8a9b2202010-02-26 18:56:32 -08002756 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002757
2758 // If we are currently pausing an activity, then don't do anything
2759 // until that is done.
2760 if (mPausingActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002761 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002762 return false;
2763 }
2764
2765 // We need to start pausing the current activity so the top one
2766 // can be resumed...
2767 if (mResumedActivity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002768 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002769 startPausingLocked(userLeaving, false);
2770 return true;
2771 }
2772
2773 if (prev != null && prev != next) {
2774 if (!prev.waitingVisible && next != null && !next.nowVisible) {
2775 prev.waitingVisible = true;
2776 mWaitingVisibleActivities.add(prev);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002777 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002778 TAG, "Resuming top, waiting visible to hide: " + prev);
2779 } else {
2780 // The next activity is already visible, so hide the previous
2781 // activity's windows right now so we can show the new one ASAP.
2782 // We only do this if the previous is finishing, which should mean
2783 // it is on top of the one being resumed so hiding it quickly
2784 // is good. Otherwise, we want to do the normal route of allowing
2785 // the resumed activity to be shown so we can decide if the
2786 // previous should actually be hidden depending on whether the
2787 // new one is found to be full-screen or not.
2788 if (prev.finishing) {
2789 mWindowManager.setAppVisibility(prev, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002790 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 + prev + ", waitingVisible="
2792 + (prev != null ? prev.waitingVisible : null)
2793 + ", nowVisible=" + next.nowVisible);
2794 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002795 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002796 + prev + ", waitingVisible="
2797 + (prev != null ? prev.waitingVisible : null)
2798 + ", nowVisible=" + next.nowVisible);
2799 }
2800 }
2801 }
2802
2803 // We are starting up the next activity, so tell the window manager
2804 // that the previous one will be hidden soon. This way it can know
2805 // to ignore it when computing the desired screen orientation.
2806 if (prev != null) {
2807 if (prev.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002808 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 "Prepare close transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002810 if (mNoAnimActivities.contains(prev)) {
2811 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2812 } else {
2813 mWindowManager.prepareAppTransition(prev.task == next.task
2814 ? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
2815 : WindowManagerPolicy.TRANSIT_TASK_CLOSE);
2816 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 mWindowManager.setAppWillBeHidden(prev);
2818 mWindowManager.setAppVisibility(prev, false);
2819 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002820 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002821 "Prepare open transition: prev=" + prev);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002822 if (mNoAnimActivities.contains(next)) {
2823 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2824 } else {
2825 mWindowManager.prepareAppTransition(prev.task == next.task
2826 ? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
2827 : WindowManagerPolicy.TRANSIT_TASK_OPEN);
2828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002829 }
2830 if (false) {
2831 mWindowManager.setAppWillBeHidden(prev);
2832 mWindowManager.setAppVisibility(prev, false);
2833 }
2834 } else if (mHistory.size() > 1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002835 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002836 "Prepare open transition: no previous");
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002837 if (mNoAnimActivities.contains(next)) {
2838 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
2839 } else {
2840 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
2841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002842 }
2843
2844 if (next.app != null && next.app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002845 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002846
2847 // This activity is now becoming visible.
2848 mWindowManager.setAppVisibility(next, true);
2849
2850 HistoryRecord lastResumedActivity = mResumedActivity;
2851 ActivityState lastState = next.state;
2852
2853 updateCpuStats();
2854
2855 next.state = ActivityState.RESUMED;
2856 mResumedActivity = next;
2857 next.task.touchActiveTime();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002858 updateLruProcessLocked(next.app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 updateLRUListLocked(next);
2860
2861 // Have the window manager re-evaluate the orientation of
2862 // the screen based on the new activity order.
Eric Fischerd4d04de2009-10-27 18:55:57 -07002863 boolean updated;
2864 synchronized (this) {
2865 Configuration config = mWindowManager.updateOrientationFromAppTokens(
2866 mConfiguration,
2867 next.mayFreezeScreenLocked(next.app) ? next : null);
2868 if (config != null) {
Eric Fischerd4d04de2009-10-27 18:55:57 -07002869 next.frozenBeforeDestroy = true;
2870 }
2871 updated = updateConfigurationLocked(config, next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872 }
Eric Fischerd4d04de2009-10-27 18:55:57 -07002873 if (!updated) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 // The configuration update wasn't able to keep the existing
2875 // instance of the activity, and instead started a new one.
2876 // We should be all done, but let's just make sure our activity
2877 // is still at the top and schedule another run if something
2878 // weird happened.
2879 HistoryRecord nextNext = topRunningActivityLocked(null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002880 if (DEBUG_SWITCH) Slog.i(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002881 "Activity config changed during resume: " + next
2882 + ", new next: " + nextNext);
2883 if (nextNext != next) {
2884 // Do over!
2885 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2886 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002887 setFocusedActivityLocked(next);
2888 ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002889 mWindowManager.executeAppTransition();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002890 mNoAnimActivities.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891 return true;
2892 }
2893
2894 try {
2895 // Deliver all pending results.
2896 ArrayList a = next.results;
2897 if (a != null) {
2898 final int N = a.size();
2899 if (!next.finishing && N > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002900 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002901 TAG, "Delivering results to " + next
2902 + ": " + a);
2903 next.app.thread.scheduleSendResult(next, a);
2904 }
2905 }
2906
2907 if (next.newIntents != null) {
2908 next.app.thread.scheduleNewIntent(next.newIntents, next);
2909 }
2910
Doug Zongker2bec3d42009-12-04 12:52:44 -08002911 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 System.identityHashCode(next),
2913 next.task.taskId, next.shortComponentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002914
2915 next.app.thread.scheduleResumeActivity(next,
2916 isNextTransitionForward());
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002918 pauseIfSleepingLocked();
2919
2920 } catch (Exception e) {
2921 // Whoops, need to restart this activity!
2922 next.state = lastState;
2923 mResumedActivity = lastResumedActivity;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002924 Slog.i(TAG, "Restarting because process died: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 if (!next.hasBeenLaunched) {
2926 next.hasBeenLaunched = true;
2927 } else {
2928 if (SHOW_APP_STARTING_ICON) {
2929 mWindowManager.setAppStartingWindow(
2930 next, next.packageName, next.theme,
2931 next.nonLocalizedLabel,
2932 next.labelRes, next.icon, null, true);
2933 }
2934 }
2935 startSpecificActivityLocked(next, true, false);
2936 return true;
2937 }
2938
2939 // From this point on, if something goes wrong there is no way
2940 // to recover the activity.
2941 try {
2942 next.visible = true;
2943 completeResumeLocked(next);
2944 } catch (Exception e) {
2945 // If any exception gets thrown, toss away this
2946 // activity and try the next one.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002947 Slog.w(TAG, "Exception thrown during resume of " + next, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948 requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
2949 "resume-exception");
2950 return true;
2951 }
2952
2953 // Didn't need to use the icicle, and it is now out of date.
2954 next.icicle = null;
2955 next.haveState = false;
2956 next.stopped = false;
2957
2958 } else {
2959 // Whoops, need to restart this activity!
2960 if (!next.hasBeenLaunched) {
2961 next.hasBeenLaunched = true;
2962 } else {
2963 if (SHOW_APP_STARTING_ICON) {
2964 mWindowManager.setAppStartingWindow(
2965 next, next.packageName, next.theme,
2966 next.nonLocalizedLabel,
2967 next.labelRes, next.icon, null, true);
2968 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002969 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 }
2971 startSpecificActivityLocked(next, true, true);
2972 }
2973
2974 return true;
2975 }
2976
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002977 private final void startActivityLocked(HistoryRecord r, boolean newTask,
2978 boolean doResume) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002979 final int NH = mHistory.size();
2980
2981 int addPos = -1;
2982
2983 if (!newTask) {
2984 // If starting in an existing task, find where that is...
2985 HistoryRecord next = null;
2986 boolean startIt = true;
2987 for (int i = NH-1; i >= 0; i--) {
2988 HistoryRecord p = (HistoryRecord)mHistory.get(i);
2989 if (p.finishing) {
2990 continue;
2991 }
2992 if (p.task == r.task) {
2993 // Here it is! Now, if this is not yet visible to the
2994 // user, then just add it without starting; it will
2995 // get started when the user navigates back to it.
2996 addPos = i+1;
2997 if (!startIt) {
2998 mHistory.add(addPos, r);
2999 r.inHistory = true;
3000 r.task.numActivities++;
3001 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3002 r.info.screenOrientation, r.fullscreen);
3003 if (VALIDATE_TOKENS) {
3004 mWindowManager.validateAppTokens(mHistory);
3005 }
3006 return;
3007 }
3008 break;
3009 }
3010 if (p.fullscreen) {
3011 startIt = false;
3012 }
3013 next = p;
3014 }
3015 }
3016
3017 // Place a new activity at top of stack, so it is next to interact
3018 // with the user.
3019 if (addPos < 0) {
3020 addPos = mHistory.size();
3021 }
3022
3023 // If we are not placing the new activity frontmost, we do not want
3024 // to deliver the onUserLeaving callback to the actual frontmost
3025 // activity
3026 if (addPos < NH) {
3027 mUserLeaving = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003028 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003029 }
3030
3031 // Slot the activity into the history stack and proceed
3032 mHistory.add(addPos, r);
3033 r.inHistory = true;
3034 r.frontOfTask = newTask;
3035 r.task.numActivities++;
3036 if (NH > 0) {
3037 // We want to show the starting preview window if we are
3038 // switching to a new task, or the next activity's process is
3039 // not currently running.
3040 boolean showStartingIcon = newTask;
3041 ProcessRecord proc = r.app;
3042 if (proc == null) {
3043 proc = mProcessNames.get(r.processName, r.info.applicationInfo.uid);
3044 }
3045 if (proc == null || proc.thread == null) {
3046 showStartingIcon = true;
3047 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003048 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 "Prepare open transition: starting " + r);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003050 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3051 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
3052 mNoAnimActivities.add(r);
3053 } else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3054 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_OPEN);
3055 mNoAnimActivities.remove(r);
3056 } else {
3057 mWindowManager.prepareAppTransition(newTask
3058 ? WindowManagerPolicy.TRANSIT_TASK_OPEN
3059 : WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN);
3060 mNoAnimActivities.remove(r);
3061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 mWindowManager.addAppToken(
3063 addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
3064 boolean doShow = true;
3065 if (newTask) {
3066 // Even though this activity is starting fresh, we still need
3067 // to reset it to make sure we apply affinities to move any
3068 // existing activities from other tasks in to it.
3069 // If the caller has requested that the target task be
3070 // reset, then do so.
3071 if ((r.intent.getFlags()
3072 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3073 resetTaskIfNeededLocked(r, r);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003074 doShow = topRunningNonDelayedActivityLocked(null) == r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 }
3076 }
3077 if (SHOW_APP_STARTING_ICON && doShow) {
3078 // Figure out if we are transitioning from another activity that is
3079 // "has the same starting icon" as the next one. This allows the
3080 // window manager to keep the previous window it had previously
3081 // created, if it still had one.
3082 HistoryRecord prev = mResumedActivity;
3083 if (prev != null) {
3084 // We don't want to reuse the previous starting preview if:
3085 // (1) The current activity is in a different task.
3086 if (prev.task != r.task) prev = null;
3087 // (2) The current activity is already displayed.
3088 else if (prev.nowVisible) prev = null;
3089 }
3090 mWindowManager.setAppStartingWindow(
3091 r, r.packageName, r.theme, r.nonLocalizedLabel,
3092 r.labelRes, r.icon, prev, showStartingIcon);
3093 }
3094 } else {
3095 // If this is the first activity, don't do any fancy animations,
3096 // because there is nothing for it to animate on top of.
3097 mWindowManager.addAppToken(addPos, r, r.task.taskId,
3098 r.info.screenOrientation, r.fullscreen);
3099 }
3100 if (VALIDATE_TOKENS) {
3101 mWindowManager.validateAppTokens(mHistory);
3102 }
3103
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003104 if (doResume) {
3105 resumeTopActivityLocked(null);
3106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 }
3108
3109 /**
3110 * Perform clear operation as requested by
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003111 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
3112 * stack to the given task, then look for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 * an instance of that activity in the stack and, if found, finish all
3114 * activities on top of it and return the instance.
3115 *
3116 * @param newR Description of the new activity being started.
3117 * @return Returns the old activity that should be continue to be used,
3118 * or null if none was found.
3119 */
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003120 private final HistoryRecord performClearTaskLocked(int taskId,
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003121 HistoryRecord newR, int launchFlags, boolean doClear) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003122 int i = mHistory.size();
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003123
3124 // First find the requested task.
3125 while (i > 0) {
3126 i--;
3127 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3128 if (r.task.taskId == taskId) {
3129 i++;
3130 break;
3131 }
3132 }
3133
3134 // Now clear it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003135 while (i > 0) {
3136 i--;
3137 HistoryRecord r = (HistoryRecord)mHistory.get(i);
3138 if (r.finishing) {
3139 continue;
3140 }
3141 if (r.task.taskId != taskId) {
3142 return null;
3143 }
3144 if (r.realActivity.equals(newR.realActivity)) {
3145 // Here it is! Now finish everything in front...
3146 HistoryRecord ret = r;
3147 if (doClear) {
3148 while (i < (mHistory.size()-1)) {
3149 i++;
3150 r = (HistoryRecord)mHistory.get(i);
3151 if (r.finishing) {
3152 continue;
3153 }
3154 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3155 null, "clear")) {
3156 i--;
3157 }
3158 }
3159 }
3160
3161 // Finally, if this is a normal launch mode (that is, not
3162 // expecting onNewIntent()), then we will finish the current
3163 // instance of the activity so a new fresh one can be started.
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003164 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
3165 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 if (!ret.finishing) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003167 int index = indexOfTokenLocked(ret);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003168 if (index >= 0) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07003169 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003170 null, "clear");
3171 }
3172 return null;
3173 }
3174 }
3175
3176 return ret;
3177 }
3178 }
3179
3180 return null;
3181 }
3182
3183 /**
3184 * Find the activity in the history stack within the given task. Returns
3185 * the index within the history at which it's found, or < 0 if not found.
3186 */
3187 private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
3188 int i = mHistory.size();
3189 while (i > 0) {
3190 i--;
3191 HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
3192 if (candidate.task.taskId != task) {
3193 break;
3194 }
3195 if (candidate.realActivity.equals(r.realActivity)) {
3196 return i;
3197 }
3198 }
3199
3200 return -1;
3201 }
3202
3203 /**
3204 * Reorder the history stack so that the activity at the given index is
3205 * brought to the front.
3206 */
3207 private final HistoryRecord moveActivityToFrontLocked(int where) {
3208 HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
3209 int top = mHistory.size();
3210 HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
3211 mHistory.add(top, newTop);
3212 oldTop.frontOfTask = false;
3213 newTop.frontOfTask = true;
3214 return newTop;
3215 }
3216
3217 /**
3218 * Deliver a new Intent to an existing activity, so that its onNewIntent()
3219 * method will be called at the proper time.
3220 */
3221 private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
3222 boolean sent = false;
3223 if (r.state == ActivityState.RESUMED
3224 && r.app != null && r.app.thread != null) {
3225 try {
3226 ArrayList<Intent> ar = new ArrayList<Intent>();
3227 ar.add(new Intent(intent));
3228 r.app.thread.scheduleNewIntent(ar, r);
3229 sent = true;
3230 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003231 Slog.w(TAG, "Exception thrown sending new intent to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 }
3233 }
3234 if (!sent) {
3235 r.addNewIntentLocked(new Intent(intent));
3236 }
3237 }
3238
3239 private final void logStartActivity(int tag, HistoryRecord r,
3240 TaskRecord task) {
3241 EventLog.writeEvent(tag,
3242 System.identityHashCode(r), task.taskId,
3243 r.shortComponentName, r.intent.getAction(),
3244 r.intent.getType(), r.intent.getDataString(),
3245 r.intent.getFlags());
3246 }
3247
3248 private final int startActivityLocked(IApplicationThread caller,
3249 Intent intent, String resolvedType,
3250 Uri[] grantedUriPermissions,
3251 int grantedMode, ActivityInfo aInfo, IBinder resultTo,
3252 String resultWho, int requestCode,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003253 int callingPid, int callingUid, boolean onlyIfNeeded,
3254 boolean componentSpecified) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003255 Slog.i(TAG, "Starting activity: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256
3257 HistoryRecord sourceRecord = null;
3258 HistoryRecord resultRecord = null;
3259 if (resultTo != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07003260 int index = indexOfTokenLocked(resultTo);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003261 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 TAG, "Sending result to " + resultTo + " (index " + index + ")");
3263 if (index >= 0) {
3264 sourceRecord = (HistoryRecord)mHistory.get(index);
3265 if (requestCode >= 0 && !sourceRecord.finishing) {
3266 resultRecord = sourceRecord;
3267 }
3268 }
3269 }
3270
3271 int launchFlags = intent.getFlags();
3272
3273 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
3274 && sourceRecord != null) {
3275 // Transfer the result target from the source activity to the new
3276 // one being started, including any failures.
3277 if (requestCode >= 0) {
3278 return START_FORWARD_AND_REQUEST_CONFLICT;
3279 }
3280 resultRecord = sourceRecord.resultTo;
3281 resultWho = sourceRecord.resultWho;
3282 requestCode = sourceRecord.requestCode;
3283 sourceRecord.resultTo = null;
3284 if (resultRecord != null) {
3285 resultRecord.removeResultsLocked(
3286 sourceRecord, resultWho, requestCode);
3287 }
3288 }
3289
3290 int err = START_SUCCESS;
3291
3292 if (intent.getComponent() == null) {
3293 // We couldn't find a class that can handle the given Intent.
3294 // That's the end of that!
3295 err = START_INTENT_NOT_RESOLVED;
3296 }
3297
3298 if (err == START_SUCCESS && aInfo == null) {
3299 // We couldn't find the specific class specified in the Intent.
3300 // Also the end of the line.
3301 err = START_CLASS_NOT_FOUND;
3302 }
3303
3304 ProcessRecord callerApp = null;
3305 if (err == START_SUCCESS && caller != null) {
3306 callerApp = getRecordForAppLocked(caller);
3307 if (callerApp != null) {
3308 callingPid = callerApp.pid;
3309 callingUid = callerApp.info.uid;
3310 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003311 Slog.w(TAG, "Unable to find app for caller " + caller
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 + " (pid=" + callingPid + ") when starting: "
3313 + intent.toString());
3314 err = START_PERMISSION_DENIED;
3315 }
3316 }
3317
3318 if (err != START_SUCCESS) {
3319 if (resultRecord != null) {
3320 sendActivityResultLocked(-1,
3321 resultRecord, resultWho, requestCode,
3322 Activity.RESULT_CANCELED, null);
3323 }
3324 return err;
3325 }
3326
3327 final int perm = checkComponentPermission(aInfo.permission, callingPid,
3328 callingUid, aInfo.exported ? -1 : aInfo.applicationInfo.uid);
3329 if (perm != PackageManager.PERMISSION_GRANTED) {
3330 if (resultRecord != null) {
3331 sendActivityResultLocked(-1,
3332 resultRecord, resultWho, requestCode,
3333 Activity.RESULT_CANCELED, null);
3334 }
3335 String msg = "Permission Denial: starting " + intent.toString()
3336 + " from " + callerApp + " (pid=" + callingPid
3337 + ", uid=" + callingUid + ")"
3338 + " requires " + aInfo.permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003339 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 throw new SecurityException(msg);
3341 }
3342
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003343 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 boolean abort = false;
3345 try {
3346 // The Intent we give to the watcher has the extra data
3347 // stripped off, since it can contain private information.
3348 Intent watchIntent = intent.cloneFilter();
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003349 abort = !mController.activityStarting(watchIntent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003350 aInfo.applicationInfo.packageName);
3351 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003352 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 }
3354
3355 if (abort) {
3356 if (resultRecord != null) {
3357 sendActivityResultLocked(-1,
3358 resultRecord, resultWho, requestCode,
3359 Activity.RESULT_CANCELED, null);
3360 }
3361 // We pretend to the caller that it was really started, but
3362 // they will just get a cancel result.
3363 return START_SUCCESS;
3364 }
3365 }
3366
3367 HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
3368 intent, resolvedType, aInfo, mConfiguration,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003369 resultRecord, resultWho, requestCode, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003371 if (mResumedActivity == null
3372 || mResumedActivity.info.applicationInfo.uid != callingUid) {
3373 if (!checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
3374 PendingActivityLaunch pal = new PendingActivityLaunch();
3375 pal.r = r;
3376 pal.sourceRecord = sourceRecord;
3377 pal.grantedUriPermissions = grantedUriPermissions;
3378 pal.grantedMode = grantedMode;
3379 pal.onlyIfNeeded = onlyIfNeeded;
3380 mPendingActivityLaunches.add(pal);
3381 return START_SWITCHES_CANCELED;
3382 }
3383 }
3384
3385 if (mDidAppSwitch) {
3386 // This is the second allowed switch since we stopped switches,
3387 // so now just generally allow switches. Use case: user presses
3388 // home (switches disabled, switch to home, mDidAppSwitch now true);
3389 // user taps a home icon (coming from home so allowed, we hit here
3390 // and now allow anyone to switch again).
3391 mAppSwitchesAllowedTime = 0;
3392 } else {
3393 mDidAppSwitch = true;
3394 }
3395
3396 doPendingActivityLaunchesLocked(false);
3397
3398 return startActivityUncheckedLocked(r, sourceRecord,
3399 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
3400 }
3401
3402 private final void doPendingActivityLaunchesLocked(boolean doResume) {
3403 final int N = mPendingActivityLaunches.size();
3404 if (N <= 0) {
3405 return;
3406 }
3407 for (int i=0; i<N; i++) {
3408 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
3409 startActivityUncheckedLocked(pal.r, pal.sourceRecord,
3410 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
3411 doResume && i == (N-1));
3412 }
3413 mPendingActivityLaunches.clear();
3414 }
3415
3416 private final int startActivityUncheckedLocked(HistoryRecord r,
3417 HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
3418 int grantedMode, boolean onlyIfNeeded, boolean doResume) {
3419 final Intent intent = r.intent;
3420 final int callingUid = r.launchedFromUid;
3421
3422 int launchFlags = intent.getFlags();
3423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 // We'll invoke onUserLeaving before onPause only if the launching
3425 // activity did not explicitly state that this is an automated launch.
3426 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003427 if (DEBUG_USER_LEAVING) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003428 "startActivity() => mUserLeaving=" + mUserLeaving);
3429
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003430 // If the caller has asked not to resume at this point, we make note
3431 // of this in the record so that we can skip it when trying to find
3432 // the top running activity.
3433 if (!doResume) {
3434 r.delayedResume = true;
3435 }
3436
3437 HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
3438 != 0 ? r : null;
3439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 // If the onlyIfNeeded flag is set, then we can do this if the activity
3441 // being launched is the same as the one making the call... or, as
3442 // a special case, if we do not know the caller then we count the
3443 // current top activity as the caller.
3444 if (onlyIfNeeded) {
3445 HistoryRecord checkedCaller = sourceRecord;
3446 if (checkedCaller == null) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003447 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 }
3449 if (!checkedCaller.realActivity.equals(r.realActivity)) {
3450 // Caller is not the same as launcher, so always needed.
3451 onlyIfNeeded = false;
3452 }
3453 }
3454
3455 if (grantedUriPermissions != null && callingUid > 0) {
3456 for (int i=0; i<grantedUriPermissions.length; i++) {
3457 grantUriPermissionLocked(callingUid, r.packageName,
3458 grantedUriPermissions[i], grantedMode, r);
3459 }
3460 }
3461
3462 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3463 intent, r);
3464
3465 if (sourceRecord == null) {
3466 // This activity is not being started from another... in this
3467 // case we -always- start a new task.
3468 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003469 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 -08003470 + intent);
3471 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3472 }
3473 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3474 // The original activity who is starting us is running as a single
3475 // instance... this new activity it is starting must go on its
3476 // own task.
3477 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3478 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
3479 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
3480 // The activity being started is a single instance... it always
3481 // gets launched into its own task.
3482 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
3483 }
3484
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003485 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486 // For whatever reason this activity is being launched into a new
3487 // task... yet the caller has requested a result back. Well, that
3488 // is pretty messed up, so instead immediately send back a cancel
3489 // and let the new task continue launched as normal without a
3490 // dependency on its originator.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003491 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003493 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494 Activity.RESULT_CANCELED, null);
3495 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 }
3497
3498 boolean addingToTask = false;
3499 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
3500 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
3501 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3502 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3503 // If bring to front is requested, and no result is requested, and
3504 // we can find a task that was started with this same
3505 // component, then instead of launching bring that one to the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003506 if (r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 // See if there is a task to bring to the front. If this is
3508 // a SINGLE_INSTANCE activity, there can be one and only one
3509 // instance of it in the history, and it is always in its own
3510 // unique task, so we do a special search.
3511 HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
3512 ? findTaskLocked(intent, r.info)
3513 : findActivityLocked(intent, r.info);
3514 if (taskTop != null) {
3515 if (taskTop.task.intent == null) {
3516 // This task was started because of movement of
3517 // the activity based on affinity... now that we
3518 // are actually launching it, we can assign the
3519 // base intent.
3520 taskTop.task.setIntent(intent, r.info);
3521 }
3522 // If the target task is not in the front, then we need
3523 // to bring it to the front... except... well, with
3524 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
3525 // to have the same behavior as if a new instance was
3526 // being started, which means not bringing it to the front
3527 // if the caller is not itself in the front.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003528 HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 if (curTop.task != taskTop.task) {
3530 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
3531 boolean callerAtFront = sourceRecord == null
3532 || curTop.task == sourceRecord.task;
3533 if (callerAtFront) {
3534 // We really do want to push this one into the
3535 // user's face, right now.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003536 moveTaskToFrontLocked(taskTop.task, r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 }
3538 }
3539 // If the caller has requested that the target task be
3540 // reset, then do so.
3541 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
3542 taskTop = resetTaskIfNeededLocked(taskTop, r);
3543 }
3544 if (onlyIfNeeded) {
3545 // We don't need to start a new activity, and
3546 // the client said not to do anything if that
3547 // is the case, so this is it! And for paranoia, make
3548 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003549 if (doResume) {
3550 resumeTopActivityLocked(null);
3551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 return START_RETURN_INTENT_TO_CALLER;
3553 }
3554 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
3555 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
3556 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
3557 // In this situation we want to remove all activities
3558 // from the task up to the one being started. In most
3559 // cases this means we are resetting the task to its
3560 // initial state.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003561 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003562 taskTop.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563 if (top != null) {
3564 if (top.frontOfTask) {
3565 // Activity aliases may mean we use different
3566 // intents for the top activity, so make sure
3567 // the task now has the identity of the new
3568 // intent.
3569 top.task.setIntent(r.intent, r.info);
3570 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003571 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 deliverNewIntentLocked(top, r.intent);
3573 } else {
3574 // A special case: we need to
3575 // start the activity because it is not currently
3576 // running, and the caller has asked to clear the
3577 // current task to have this activity at the top.
3578 addingToTask = true;
3579 // Now pretend like this activity is being started
3580 // by the top of its task, so it is put in the
3581 // right place.
3582 sourceRecord = taskTop;
3583 }
3584 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
3585 // In this case the top activity on the task is the
3586 // same as the one being launched, so we take that
3587 // as a request to bring the task to the foreground.
3588 // If the top activity in the task is the root
3589 // activity, deliver this new intent to it if it
3590 // desires.
3591 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3592 && taskTop.realActivity.equals(r.realActivity)) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003593 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 if (taskTop.frontOfTask) {
3595 taskTop.task.setIntent(r.intent, r.info);
3596 }
3597 deliverNewIntentLocked(taskTop, r.intent);
3598 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
3599 // In this case we are launching the root activity
3600 // of the task, but with a different intent. We
3601 // should start a new instance on top.
3602 addingToTask = true;
3603 sourceRecord = taskTop;
3604 }
3605 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
3606 // In this case an activity is being launched in to an
3607 // existing task, without resetting that task. This
3608 // is typically the situation of launching an activity
3609 // from a notification or shortcut. We want to place
3610 // the new activity on top of the current task.
3611 addingToTask = true;
3612 sourceRecord = taskTop;
3613 } else if (!taskTop.task.rootWasReset) {
3614 // In this case we are launching in to an existing task
3615 // that has not yet been started from its front door.
3616 // The current task has been brought to the front.
3617 // Ideally, we'd probably like to place this new task
3618 // at the bottom of its stack, but that's a little hard
3619 // to do with the current organization of the code so
3620 // for now we'll just drop it.
3621 taskTop.task.setIntent(r.intent, r.info);
3622 }
3623 if (!addingToTask) {
3624 // We didn't do anything... but it was needed (a.k.a., client
3625 // don't use that intent!) And for paranoia, make
3626 // sure we have correctly resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003627 if (doResume) {
3628 resumeTopActivityLocked(null);
3629 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 return START_TASK_TO_FRONT;
3631 }
3632 }
3633 }
3634 }
3635
3636 //String uri = r.intent.toURI();
3637 //Intent intent2 = new Intent(uri);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003638 //Slog.i(TAG, "Given intent: " + r.intent);
3639 //Slog.i(TAG, "URI is: " + uri);
3640 //Slog.i(TAG, "To intent: " + intent2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641
3642 if (r.packageName != null) {
3643 // If the activity being launched is the same as the one currently
3644 // at the top, then we need to check if it should only be launched
3645 // once.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003646 HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
3647 if (top != null && r.resultTo == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 if (top.realActivity.equals(r.realActivity)) {
3649 if (top.app != null && top.app.thread != null) {
3650 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
3651 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
3652 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003653 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654 // For paranoia, make sure we have correctly
3655 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003656 if (doResume) {
3657 resumeTopActivityLocked(null);
3658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 if (onlyIfNeeded) {
3660 // We don't need to start a new activity, and
3661 // the client said not to do anything if that
3662 // is the case, so this is it!
3663 return START_RETURN_INTENT_TO_CALLER;
3664 }
3665 deliverNewIntentLocked(top, r.intent);
3666 return START_DELIVERED_TO_TOP;
3667 }
3668 }
3669 }
3670 }
3671
3672 } else {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003673 if (r.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 sendActivityResultLocked(-1,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003675 r.resultTo, r.resultWho, r.requestCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 Activity.RESULT_CANCELED, null);
3677 }
3678 return START_CLASS_NOT_FOUND;
3679 }
3680
3681 boolean newTask = false;
3682
3683 // Should this be considered a new task?
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003684 if (r.resultTo == null && !addingToTask
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3686 // todo: should do better management of integers.
3687 mCurTask++;
3688 if (mCurTask <= 0) {
3689 mCurTask = 1;
3690 }
3691 r.task = new TaskRecord(mCurTask, r.info, intent,
3692 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003693 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 + " in new task " + r.task);
3695 newTask = true;
Josh Bartel7f208742010-02-25 11:01:44 -06003696 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697
3698 } else if (sourceRecord != null) {
3699 if (!addingToTask &&
3700 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3701 // In this case, we are adding the activity to an existing
3702 // task, but the caller has asked to clear that task if the
3703 // activity is already running.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003704 HistoryRecord top = performClearTaskLocked(
Dianne Hackbornaa52f9a2009-08-25 16:01:15 -07003705 sourceRecord.task.taskId, r, launchFlags, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 if (top != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003707 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 deliverNewIntentLocked(top, r.intent);
3709 // For paranoia, make sure we have correctly
3710 // resumed the top activity.
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003711 if (doResume) {
3712 resumeTopActivityLocked(null);
3713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714 return START_DELIVERED_TO_TOP;
3715 }
3716 } else if (!addingToTask &&
3717 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3718 // In this case, we are launching an activity in our own task
3719 // that may already be running somewhere in the history, and
3720 // we want to shuffle it to the front of the stack if so.
3721 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3722 if (where >= 0) {
3723 HistoryRecord top = moveActivityToFrontLocked(where);
Doug Zongker2bec3d42009-12-04 12:52:44 -08003724 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003725 deliverNewIntentLocked(top, r.intent);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003726 if (doResume) {
3727 resumeTopActivityLocked(null);
3728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 return START_DELIVERED_TO_TOP;
3730 }
3731 }
3732 // An existing activity is starting this new activity, so we want
3733 // to keep the new one in the same task as the one that is starting
3734 // it.
3735 r.task = sourceRecord.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003736 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 + " in existing task " + r.task);
3738
3739 } else {
3740 // This not being started from an existing activity, and not part
3741 // of a new task... just put it in the top task, though these days
3742 // this case should never happen.
3743 final int N = mHistory.size();
3744 HistoryRecord prev =
3745 N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
3746 r.task = prev != null
3747 ? prev.task
3748 : new TaskRecord(mCurTask, r.info, intent,
3749 (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003750 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 + " in new guessed " + r.task);
3752 }
3753 if (newTask) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003754 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08003756 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003757 startActivityLocked(r, newTask, doResume);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003758 return START_SUCCESS;
3759 }
3760
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003761 void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
3762 long thisTime, long totalTime) {
3763 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3764 WaitResult w = mWaitingActivityLaunched.get(i);
3765 w.timeout = timeout;
3766 if (r != null) {
3767 w.who = new ComponentName(r.info.packageName, r.info.name);
3768 }
3769 w.thisTime = thisTime;
3770 w.totalTime = totalTime;
3771 }
3772 notify();
3773 }
3774
3775 void reportActivityVisibleLocked(HistoryRecord r) {
3776 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3777 WaitResult w = mWaitingActivityVisible.get(i);
3778 w.timeout = false;
3779 if (r != null) {
3780 w.who = new ComponentName(r.info.packageName, r.info.name);
3781 }
3782 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3783 w.thisTime = w.totalTime;
3784 }
3785 notify();
3786 }
3787
3788 private final int startActivityMayWait(IApplicationThread caller,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003789 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3790 int grantedMode, IBinder resultTo,
3791 String resultWho, int requestCode, boolean onlyIfNeeded,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003792 boolean debug, WaitResult outResult, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 // Refuse possible leaked file descriptors
3794 if (intent != null && intent.hasFileDescriptors()) {
3795 throw new IllegalArgumentException("File descriptors passed in Intent");
3796 }
3797
Dianne Hackborn860755f2010-06-03 18:47:52 -07003798 boolean componentSpecified = intent.getComponent() != null;
The Android Open Source Project4df24232009-03-05 14:34:35 -08003799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 // Don't modify the client's object!
3801 intent = new Intent(intent);
3802
3803 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 ActivityInfo aInfo;
3805 try {
3806 ResolveInfo rInfo =
3807 ActivityThread.getPackageManager().resolveIntent(
3808 intent, resolvedType,
3809 PackageManager.MATCH_DEFAULT_ONLY
Dianne Hackborn1655be42009-05-08 14:29:01 -07003810 | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 aInfo = rInfo != null ? rInfo.activityInfo : null;
3812 } catch (RemoteException e) {
3813 aInfo = null;
3814 }
3815
3816 if (aInfo != null) {
3817 // Store the found target back into the intent, because now that
3818 // we have it we never want to do this again. For example, if the
3819 // user navigates back to this point in the history, we should
3820 // always restart the exact same activity.
3821 intent.setComponent(new ComponentName(
3822 aInfo.applicationInfo.packageName, aInfo.name));
3823
3824 // Don't debug things in the system process
3825 if (debug) {
3826 if (!aInfo.processName.equals("system")) {
3827 setDebugApp(aInfo.processName, true, false);
3828 }
3829 }
3830 }
3831
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003832 synchronized (this) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003833 int callingPid;
3834 int callingUid;
3835 if (caller == null) {
3836 callingPid = Binder.getCallingPid();
3837 callingUid = Binder.getCallingUid();
3838 } else {
3839 callingPid = callingUid = -1;
3840 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003841
3842 mConfigWillChange = config != null && mConfiguration.diff(config) != 0;
Dianne Hackborne2522462010-03-29 18:41:30 -07003843 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3844 "Starting activity when config will change = " + mConfigWillChange);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003847
Dianne Hackborn860755f2010-06-03 18:47:52 -07003848 if (aInfo != null &&
3849 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_HEAVY_WEIGHT) != 0) {
3850 // This may be a heavy-weight process! Check to see if we already
3851 // have another, different heavy-weight process running.
3852 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3853 if (mHeavyWeightProcess != null &&
3854 (mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3855 !mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3856 int realCallingPid = callingPid;
3857 int realCallingUid = callingUid;
3858 if (caller != null) {
3859 ProcessRecord callerApp = getRecordForAppLocked(caller);
3860 if (callerApp != null) {
3861 realCallingPid = callerApp.pid;
3862 realCallingUid = callerApp.info.uid;
3863 } else {
3864 Slog.w(TAG, "Unable to find app for caller " + caller
3865 + " (pid=" + realCallingPid + ") when starting: "
3866 + intent.toString());
3867 return START_PERMISSION_DENIED;
3868 }
3869 }
3870
3871 IIntentSender target = getIntentSenderLocked(
3872 IActivityManager.INTENT_SENDER_ACTIVITY, "android",
3873 realCallingUid, null, null, 0, intent,
3874 resolvedType, PendingIntent.FLAG_CANCEL_CURRENT
3875 | PendingIntent.FLAG_ONE_SHOT);
3876
3877 Intent newIntent = new Intent();
3878 if (requestCode >= 0) {
3879 // Caller is requesting a result.
3880 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3881 }
3882 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3883 new IntentSender(target));
3884 if (mHeavyWeightProcess.activities.size() > 0) {
3885 HistoryRecord hist = mHeavyWeightProcess.activities.get(0);
3886 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3887 hist.packageName);
3888 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3889 hist.task.taskId);
3890 }
3891 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3892 aInfo.packageName);
3893 newIntent.setFlags(intent.getFlags());
3894 newIntent.setClassName("android",
3895 HeavyWeightSwitcherActivity.class.getName());
3896 intent = newIntent;
3897 resolvedType = null;
3898 caller = null;
3899 callingUid = Binder.getCallingUid();
3900 callingPid = Binder.getCallingPid();
3901 componentSpecified = true;
3902 try {
3903 ResolveInfo rInfo =
3904 ActivityThread.getPackageManager().resolveIntent(
3905 intent, null,
3906 PackageManager.MATCH_DEFAULT_ONLY
3907 | STOCK_PM_FLAGS);
3908 aInfo = rInfo != null ? rInfo.activityInfo : null;
3909 } catch (RemoteException e) {
3910 aInfo = null;
3911 }
3912 }
3913 }
3914 }
3915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 int res = startActivityLocked(caller, intent, resolvedType,
3917 grantedUriPermissions, grantedMode, aInfo,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08003918 resultTo, resultWho, requestCode, callingPid, callingUid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08003919 onlyIfNeeded, componentSpecified);
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003920
Dianne Hackborne2522462010-03-29 18:41:30 -07003921 if (mConfigWillChange) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003922 // If the caller also wants to switch to a new configuration,
3923 // do so now. This allows a clean switch, as we are waiting
3924 // for the current activity to pause (so we will not destroy
3925 // it), and have not yet started the next activity.
3926 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3927 "updateConfiguration()");
Dianne Hackborne2522462010-03-29 18:41:30 -07003928 mConfigWillChange = false;
3929 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3930 "Updating to new configuration after starting activity.");
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003931 updateConfigurationLocked(config, null);
3932 }
Dianne Hackbornd49258f2010-03-26 00:44:29 -07003933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 Binder.restoreCallingIdentity(origId);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003935
3936 if (outResult != null) {
3937 outResult.result = res;
3938 if (res == IActivityManager.START_SUCCESS) {
3939 mWaitingActivityLaunched.add(outResult);
3940 do {
3941 try {
3942 wait();
3943 } catch (InterruptedException e) {
3944 }
3945 } while (!outResult.timeout && outResult.who == null);
3946 } else if (res == IActivityManager.START_TASK_TO_FRONT) {
3947 HistoryRecord r = this.topRunningActivityLocked(null);
3948 if (r.nowVisible) {
3949 outResult.timeout = false;
3950 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3951 outResult.totalTime = 0;
3952 outResult.thisTime = 0;
3953 } else {
3954 outResult.thisTime = SystemClock.uptimeMillis();
3955 mWaitingActivityVisible.add(outResult);
3956 do {
3957 try {
3958 wait();
3959 } catch (InterruptedException e) {
3960 }
3961 } while (!outResult.timeout && outResult.who == null);
3962 }
3963 }
3964 }
3965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 return res;
3967 }
3968 }
3969
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003970 public final int startActivity(IApplicationThread caller,
3971 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3972 int grantedMode, IBinder resultTo,
3973 String resultWho, int requestCode, boolean onlyIfNeeded,
3974 boolean debug) {
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003975 return startActivityMayWait(caller, intent, resolvedType,
3976 grantedUriPermissions, grantedMode, resultTo, resultWho,
3977 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003978 }
3979
3980 public final WaitResult startActivityAndWait(IApplicationThread caller,
3981 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3982 int grantedMode, IBinder resultTo,
3983 String resultWho, int requestCode, boolean onlyIfNeeded,
3984 boolean debug) {
3985 WaitResult res = new WaitResult();
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003986 startActivityMayWait(caller, intent, resolvedType,
3987 grantedUriPermissions, grantedMode, resultTo, resultWho,
3988 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08003989 return res;
3990 }
3991
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07003992 public final int startActivityWithConfig(IApplicationThread caller,
3993 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
3994 int grantedMode, IBinder resultTo,
3995 String resultWho, int requestCode, boolean onlyIfNeeded,
3996 boolean debug, Configuration config) {
3997 return startActivityMayWait(caller, intent, resolvedType,
3998 grantedUriPermissions, grantedMode, resultTo, resultWho,
3999 requestCode, onlyIfNeeded, debug, null, config);
4000 }
4001
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08004002 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07004003 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004004 IBinder resultTo, String resultWho, int requestCode,
4005 int flagsMask, int flagsValues) {
4006 // Refuse possible leaked file descriptors
4007 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
4008 throw new IllegalArgumentException("File descriptors passed in Intent");
4009 }
4010
4011 IIntentSender sender = intent.getTarget();
4012 if (!(sender instanceof PendingIntentRecord)) {
4013 throw new IllegalArgumentException("Bad PendingIntent object");
4014 }
4015
4016 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07004017
4018 synchronized (this) {
4019 // If this is coming from the currently resumed activity, it is
4020 // effectively saying that app switches are allowed at this point.
4021 if (mResumedActivity != null
4022 && mResumedActivity.info.applicationInfo.uid ==
4023 Binder.getCallingUid()) {
4024 mAppSwitchesAllowedTime = 0;
4025 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07004026 }
4027
4028 return pir.sendInner(0, fillInIntent, resolvedType,
4029 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
4030 }
4031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 public boolean startNextMatchingActivity(IBinder callingActivity,
4033 Intent intent) {
4034 // Refuse possible leaked file descriptors
4035 if (intent != null && intent.hasFileDescriptors() == true) {
4036 throw new IllegalArgumentException("File descriptors passed in Intent");
4037 }
4038
4039 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004040 int index = indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041 if (index < 0) {
4042 return false;
4043 }
4044 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4045 if (r.app == null || r.app.thread == null) {
4046 // The caller is not running... d'oh!
4047 return false;
4048 }
4049 intent = new Intent(intent);
4050 // The caller is not allowed to change the data.
4051 intent.setDataAndType(r.intent.getData(), r.intent.getType());
4052 // And we are resetting to find the next component...
4053 intent.setComponent(null);
4054
4055 ActivityInfo aInfo = null;
4056 try {
4057 List<ResolveInfo> resolves =
4058 ActivityThread.getPackageManager().queryIntentActivities(
4059 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004060 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061
4062 // Look for the original activity in the list...
4063 final int N = resolves != null ? resolves.size() : 0;
4064 for (int i=0; i<N; i++) {
4065 ResolveInfo rInfo = resolves.get(i);
4066 if (rInfo.activityInfo.packageName.equals(r.packageName)
4067 && rInfo.activityInfo.name.equals(r.info.name)) {
4068 // We found the current one... the next matching is
4069 // after it.
4070 i++;
4071 if (i<N) {
4072 aInfo = resolves.get(i).activityInfo;
4073 }
4074 break;
4075 }
4076 }
4077 } catch (RemoteException e) {
4078 }
4079
4080 if (aInfo == null) {
4081 // Nobody who is next!
4082 return false;
4083 }
4084
4085 intent.setComponent(new ComponentName(
4086 aInfo.applicationInfo.packageName, aInfo.name));
4087 intent.setFlags(intent.getFlags()&~(
4088 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
4089 Intent.FLAG_ACTIVITY_CLEAR_TOP|
4090 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
4091 Intent.FLAG_ACTIVITY_NEW_TASK));
4092
4093 // Okay now we need to start the new activity, replacing the
4094 // currently running activity. This is a little tricky because
4095 // we want to start the new one as if the current one is finished,
4096 // but not finish the current one first so that there is no flicker.
4097 // And thus...
4098 final boolean wasFinishing = r.finishing;
4099 r.finishing = true;
4100
4101 // Propagate reply information over to the new activity.
4102 final HistoryRecord resultTo = r.resultTo;
4103 final String resultWho = r.resultWho;
4104 final int requestCode = r.requestCode;
4105 r.resultTo = null;
4106 if (resultTo != null) {
4107 resultTo.removeResultsLocked(r, resultWho, requestCode);
4108 }
4109
4110 final long origId = Binder.clearCallingIdentity();
4111 // XXX we are not dealing with propagating grantedUriPermissions...
4112 // those are not yet exposed to user code, so there is no need.
4113 int res = startActivityLocked(r.app.thread, intent,
4114 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004115 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 Binder.restoreCallingIdentity(origId);
4117
4118 r.finishing = wasFinishing;
4119 if (res != START_SUCCESS) {
4120 return false;
4121 }
4122 return true;
4123 }
4124 }
4125
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004126 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 Intent intent, String resolvedType, IBinder resultTo,
4128 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07004129
4130 // This is so super not safe, that only the system (or okay root)
4131 // can do it.
4132 final int callingUid = Binder.getCallingUid();
4133 if (callingUid != 0 && callingUid != Process.myUid()) {
4134 throw new SecurityException(
4135 "startActivityInPackage only available to the system");
4136 }
4137
The Android Open Source Project4df24232009-03-05 14:34:35 -08004138 final boolean componentSpecified = intent.getComponent() != null;
4139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004140 // Don't modify the client's object!
4141 intent = new Intent(intent);
4142
4143 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144 ActivityInfo aInfo;
4145 try {
4146 ResolveInfo rInfo =
4147 ActivityThread.getPackageManager().resolveIntent(
4148 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004149 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 aInfo = rInfo != null ? rInfo.activityInfo : null;
4151 } catch (RemoteException e) {
4152 aInfo = null;
4153 }
4154
4155 if (aInfo != null) {
4156 // Store the found target back into the intent, because now that
4157 // we have it we never want to do this again. For example, if the
4158 // user navigates back to this point in the history, we should
4159 // always restart the exact same activity.
4160 intent.setComponent(new ComponentName(
4161 aInfo.applicationInfo.packageName, aInfo.name));
4162 }
4163
4164 synchronized(this) {
4165 return startActivityLocked(null, intent, resolvedType,
4166 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08004167 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 }
4169 }
4170
Josh Bartel7f208742010-02-25 11:01:44 -06004171 private final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 // Remove any existing entries that are the same kind of task.
4173 int N = mRecentTasks.size();
4174 for (int i=0; i<N; i++) {
4175 TaskRecord tr = mRecentTasks.get(i);
4176 if ((task.affinity != null && task.affinity.equals(tr.affinity))
4177 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
4178 mRecentTasks.remove(i);
4179 i--;
4180 N--;
4181 if (task.intent == null) {
4182 // If the new recent task we are adding is not fully
4183 // specified, then replace it with the existing recent task.
4184 task = tr;
4185 }
4186 }
4187 }
4188 if (N >= MAX_RECENT_TASKS) {
4189 mRecentTasks.remove(N-1);
4190 }
4191 mRecentTasks.add(0, task);
4192 }
4193
4194 public void setRequestedOrientation(IBinder token,
4195 int requestedOrientation) {
4196 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004197 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004198 if (index < 0) {
4199 return;
4200 }
4201 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4202 final long origId = Binder.clearCallingIdentity();
4203 mWindowManager.setAppOrientation(r, requestedOrientation);
4204 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07004205 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004206 r.mayFreezeScreenLocked(r.app) ? r : null);
4207 if (config != null) {
4208 r.frozenBeforeDestroy = true;
4209 if (!updateConfigurationLocked(config, r)) {
4210 resumeTopActivityLocked(null);
4211 }
4212 }
4213 Binder.restoreCallingIdentity(origId);
4214 }
4215 }
4216
4217 public int getRequestedOrientation(IBinder token) {
4218 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004219 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004220 if (index < 0) {
4221 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4222 }
4223 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4224 return mWindowManager.getAppOrientation(r);
4225 }
4226 }
4227
4228 private final void stopActivityLocked(HistoryRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004229 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
4231 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
4232 if (!r.finishing) {
4233 requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
4234 "no-history");
4235 }
4236 } else if (r.app != null && r.app.thread != null) {
4237 if (mFocusedActivity == r) {
4238 setFocusedActivityLocked(topRunningActivityLocked(null));
4239 }
4240 r.resumeKeyDispatchingLocked();
4241 try {
4242 r.stopped = false;
4243 r.state = ActivityState.STOPPING;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004244 if (DEBUG_VISBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 TAG, "Stopping visible=" + r.visible + " for " + r);
4246 if (!r.visible) {
4247 mWindowManager.setAppVisibility(r, false);
4248 }
4249 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
4250 } catch (Exception e) {
4251 // Maybe just ignore exceptions here... if the process
4252 // has crashed, our death notification will clean things
4253 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004254 Slog.w(TAG, "Exception thrown during pause", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004255 // Just in case, assume it to be stopped.
4256 r.stopped = true;
4257 r.state = ActivityState.STOPPED;
4258 if (r.configDestroy) {
4259 destroyActivityLocked(r, true);
4260 }
4261 }
4262 }
4263 }
4264
4265 /**
4266 * @return Returns true if the activity is being finished, false if for
4267 * some reason it is being left as-is.
4268 */
4269 private final boolean requestFinishActivityLocked(IBinder token, int resultCode,
4270 Intent resultData, String reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004271 if (DEBUG_RESULTS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 TAG, "Finishing activity: token=" + token
4273 + ", result=" + resultCode + ", data=" + resultData);
4274
Dianne Hackborn75b03852009-06-12 15:43:26 -07004275 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004276 if (index < 0) {
4277 return false;
4278 }
4279 HistoryRecord r = (HistoryRecord)mHistory.get(index);
4280
4281 // Is this the last activity left?
4282 boolean lastActivity = true;
4283 for (int i=mHistory.size()-1; i>=0; i--) {
4284 HistoryRecord p = (HistoryRecord)mHistory.get(i);
4285 if (!p.finishing && p != r) {
4286 lastActivity = false;
4287 break;
4288 }
4289 }
4290
4291 // If this is the last activity, but it is the home activity, then
4292 // just don't finish it.
4293 if (lastActivity) {
4294 if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
4295 return false;
4296 }
4297 }
4298
4299 finishActivityLocked(r, index, resultCode, resultData, reason);
4300 return true;
4301 }
4302
4303 /**
4304 * @return Returns true if this activity has been removed from the history
4305 * list, or false if it is still in the list and will be removed later.
4306 */
4307 private final boolean finishActivityLocked(HistoryRecord r, int index,
4308 int resultCode, Intent resultData, String reason) {
4309 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004310 Slog.w(TAG, "Duplicate finish request for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 return false;
4312 }
4313
4314 r.finishing = true;
Doug Zongker2bec3d42009-12-04 12:52:44 -08004315 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316 System.identityHashCode(r),
4317 r.task.taskId, r.shortComponentName, reason);
4318 r.task.numActivities--;
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004319 if (index < (mHistory.size()-1)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
4321 if (next.task == r.task) {
Dianne Hackbornb67fa452010-04-14 18:01:43 -07004322 if (r.frontOfTask) {
4323 // The next activity is now the front of the task.
4324 next.frontOfTask = true;
4325 }
4326 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
4327 // If the caller asked that this activity (and all above it)
4328 // be cleared when the task is reset, don't lose that information,
4329 // but propagate it up to the next activity.
4330 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004332 }
4333 }
4334
4335 r.pauseKeyDispatchingLocked();
4336 if (mFocusedActivity == r) {
4337 setFocusedActivityLocked(topRunningActivityLocked(null));
4338 }
4339
4340 // send the result
4341 HistoryRecord resultTo = r.resultTo;
4342 if (resultTo != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004343 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
Chris Tate8a7dc172009-03-24 20:11:42 -07004344 + " who=" + r.resultWho + " req=" + r.requestCode
4345 + " res=" + resultCode + " data=" + resultData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 if (r.info.applicationInfo.uid > 0) {
4347 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
4348 r.packageName, resultData, r);
4349 }
4350 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
4351 resultData);
4352 r.resultTo = null;
4353 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004354 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355
4356 // Make sure this HistoryRecord is not holding on to other resources,
4357 // because clients have remote IPC references to this object so we
4358 // can't assume that will go away and want to avoid circular IPC refs.
4359 r.results = null;
4360 r.pendingResults = null;
4361 r.newIntents = null;
4362 r.icicle = null;
4363
4364 if (mPendingThumbnails.size() > 0) {
4365 // There are clients waiting to receive thumbnails so, in case
4366 // this is an activity that someone is waiting for, add it
4367 // to the pending list so we can correctly update the clients.
4368 mCancelledThumbnails.add(r);
4369 }
4370
4371 if (mResumedActivity == r) {
4372 boolean endTask = index <= 0
4373 || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004374 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004375 "Prepare close transition: finishing " + r);
4376 mWindowManager.prepareAppTransition(endTask
4377 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE
4378 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE);
4379
4380 // Tell window manager to prepare for this one to be removed.
4381 mWindowManager.setAppVisibility(r, false);
4382
4383 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004384 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
4385 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004386 startPausingLocked(false, false);
4387 }
4388
4389 } else if (r.state != ActivityState.PAUSING) {
4390 // If the activity is PAUSING, we will complete the finish once
4391 // it is done pausing; else we can just directly finish it here.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004392 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393 return finishCurrentActivityLocked(r, index,
4394 FINISH_AFTER_PAUSE) == null;
4395 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004396 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 }
4398
4399 return false;
4400 }
4401
4402 private static final int FINISH_IMMEDIATELY = 0;
4403 private static final int FINISH_AFTER_PAUSE = 1;
4404 private static final int FINISH_AFTER_VISIBLE = 2;
4405
4406 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4407 int mode) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004408 final int index = indexOfTokenLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004409 if (index < 0) {
4410 return null;
4411 }
4412
4413 return finishCurrentActivityLocked(r, index, mode);
4414 }
4415
4416 private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
4417 int index, int mode) {
4418 // First things first: if this activity is currently visible,
4419 // and the resumed activity is not yet visible, then hold off on
4420 // finishing until the resumed one becomes visible.
4421 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
4422 if (!mStoppingActivities.contains(r)) {
4423 mStoppingActivities.add(r);
4424 if (mStoppingActivities.size() > 3) {
4425 // If we already have a few activities waiting to stop,
4426 // then give up on things going idle and start clearing
4427 // them out.
4428 Message msg = Message.obtain();
4429 msg.what = ActivityManagerService.IDLE_NOW_MSG;
4430 mHandler.sendMessage(msg);
4431 }
4432 }
4433 r.state = ActivityState.STOPPING;
4434 updateOomAdjLocked();
4435 return r;
4436 }
4437
4438 // make sure the record is cleaned out of other places.
4439 mStoppingActivities.remove(r);
4440 mWaitingVisibleActivities.remove(r);
4441 if (mResumedActivity == r) {
4442 mResumedActivity = null;
4443 }
4444 final ActivityState prevState = r.state;
4445 r.state = ActivityState.FINISHING;
4446
4447 if (mode == FINISH_IMMEDIATELY
4448 || prevState == ActivityState.STOPPED
4449 || prevState == ActivityState.INITIALIZING) {
4450 // If this activity is already stopped, we can just finish
4451 // it right now.
4452 return destroyActivityLocked(r, true) ? null : r;
4453 } else {
4454 // Need to go through the full pause cycle to get this
4455 // activity into the stopped state and then finish it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004456 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 mFinishingActivities.add(r);
4458 resumeTopActivityLocked(null);
4459 }
4460 return r;
4461 }
4462
4463 /**
4464 * This is the internal entry point for handling Activity.finish().
4465 *
4466 * @param token The Binder token referencing the Activity we want to finish.
4467 * @param resultCode Result code, if any, from this Activity.
4468 * @param resultData Result data (Intent), if any, from this Activity.
4469 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11004470 * @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 -08004471 */
4472 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
4473 // Refuse possible leaked file descriptors
4474 if (resultData != null && resultData.hasFileDescriptors() == true) {
4475 throw new IllegalArgumentException("File descriptors passed in Intent");
4476 }
4477
4478 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004479 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 // Find the first activity that is not finishing.
4481 HistoryRecord next = topRunningActivityLocked(token, 0);
4482 if (next != null) {
4483 // ask watcher if this is allowed
4484 boolean resumeOK = true;
4485 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004486 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004487 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004488 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 }
4490
4491 if (!resumeOK) {
4492 return false;
4493 }
4494 }
4495 }
4496 final long origId = Binder.clearCallingIdentity();
4497 boolean res = requestFinishActivityLocked(token, resultCode,
4498 resultData, "app-request");
4499 Binder.restoreCallingIdentity(origId);
4500 return res;
4501 }
4502 }
4503
Dianne Hackborn860755f2010-06-03 18:47:52 -07004504 public final void finishHeavyWeightApp() {
4505 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
4506 != PackageManager.PERMISSION_GRANTED) {
4507 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
4508 + Binder.getCallingPid()
4509 + ", uid=" + Binder.getCallingUid()
4510 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
4511 Slog.w(TAG, msg);
4512 throw new SecurityException(msg);
4513 }
4514
4515 synchronized(this) {
4516 if (mHeavyWeightProcess == null) {
4517 return;
4518 }
4519
4520 ArrayList<HistoryRecord> activities = new ArrayList<HistoryRecord>(
4521 mHeavyWeightProcess.activities);
4522 for (int i=0; i<activities.size(); i++) {
4523 HistoryRecord r = activities.get(i);
4524 if (!r.finishing) {
4525 int index = indexOfTokenLocked(r);
4526 if (index >= 0) {
4527 finishActivityLocked(r, index, Activity.RESULT_CANCELED,
4528 null, "finish-heavy");
4529 }
4530 }
4531 }
4532
4533 mHeavyWeightProcess = null;
4534 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4535 }
4536 }
4537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004538 void sendActivityResultLocked(int callingUid, HistoryRecord r,
4539 String resultWho, int requestCode, int resultCode, Intent data) {
4540
4541 if (callingUid > 0) {
4542 grantUriPermissionFromIntentLocked(callingUid, r.packageName,
4543 data, r);
4544 }
4545
Joe Onorato8a9b2202010-02-26 18:56:32 -08004546 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
The Android Open Source Project10592532009-03-18 17:39:46 -07004547 + " : who=" + resultWho + " req=" + requestCode
4548 + " res=" + resultCode + " data=" + data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004549 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
4550 try {
4551 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
4552 list.add(new ResultInfo(resultWho, requestCode,
4553 resultCode, data));
4554 r.app.thread.scheduleSendResult(r, list);
4555 return;
4556 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004557 Slog.w(TAG, "Exception thrown sending result to " + r, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004558 }
4559 }
4560
4561 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
4562 }
4563
4564 public final void finishSubActivity(IBinder token, String resultWho,
4565 int requestCode) {
4566 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07004567 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 if (index < 0) {
4569 return;
4570 }
4571 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4572
4573 final long origId = Binder.clearCallingIdentity();
4574
4575 int i;
4576 for (i=mHistory.size()-1; i>=0; i--) {
4577 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4578 if (r.resultTo == self && r.requestCode == requestCode) {
4579 if ((r.resultWho == null && resultWho == null) ||
4580 (r.resultWho != null && r.resultWho.equals(resultWho))) {
4581 finishActivityLocked(r, i,
4582 Activity.RESULT_CANCELED, null, "request-sub");
4583 }
4584 }
4585 }
4586
4587 Binder.restoreCallingIdentity(origId);
4588 }
4589 }
4590
Dianne Hackborn061d58a2010-03-12 15:07:06 -08004591 public boolean willActivityBeVisible(IBinder token) {
4592 synchronized(this) {
4593 int i;
4594 for (i=mHistory.size()-1; i>=0; i--) {
4595 HistoryRecord r = (HistoryRecord)mHistory.get(i);
4596 if (r == token) {
4597 return true;
4598 }
4599 if (r.fullscreen && !r.finishing) {
4600 return false;
4601 }
4602 }
4603 return true;
4604 }
4605 }
4606
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07004607 public void overridePendingTransition(IBinder token, String packageName,
4608 int enterAnim, int exitAnim) {
4609 synchronized(this) {
4610 int index = indexOfTokenLocked(token);
4611 if (index < 0) {
4612 return;
4613 }
4614 HistoryRecord self = (HistoryRecord)mHistory.get(index);
4615
4616 final long origId = Binder.clearCallingIdentity();
4617
4618 if (self.state == ActivityState.RESUMED
4619 || self.state == ActivityState.PAUSING) {
4620 mWindowManager.overridePendingAppTransition(packageName,
4621 enterAnim, exitAnim);
4622 }
4623
4624 Binder.restoreCallingIdentity(origId);
4625 }
4626 }
4627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004628 /**
4629 * Perform clean-up of service connections in an activity record.
4630 */
4631 private final void cleanUpActivityServicesLocked(HistoryRecord r) {
4632 // Throw away any services that have been bound by this activity.
4633 if (r.connections != null) {
4634 Iterator<ConnectionRecord> it = r.connections.iterator();
4635 while (it.hasNext()) {
4636 ConnectionRecord c = it.next();
4637 removeConnectionLocked(c, null, r);
4638 }
4639 r.connections = null;
4640 }
4641 }
4642
4643 /**
4644 * Perform the common clean-up of an activity record. This is called both
4645 * as part of destroyActivityLocked() (when destroying the client-side
4646 * representation) and cleaning things up as a result of its hosting
4647 * processing going away, in which case there is no remaining client-side
4648 * state to destroy so only the cleanup here is needed.
4649 */
4650 private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
4651 if (mResumedActivity == r) {
4652 mResumedActivity = null;
4653 }
4654 if (mFocusedActivity == r) {
4655 mFocusedActivity = null;
4656 }
4657
4658 r.configDestroy = false;
4659 r.frozenBeforeDestroy = false;
4660
4661 // Make sure this record is no longer in the pending finishes list.
4662 // This could happen, for example, if we are trimming activities
4663 // down to the max limit while they are still waiting to finish.
4664 mFinishingActivities.remove(r);
4665 mWaitingVisibleActivities.remove(r);
4666
4667 // Remove any pending results.
4668 if (r.finishing && r.pendingResults != null) {
4669 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4670 PendingIntentRecord rec = apr.get();
4671 if (rec != null) {
4672 cancelIntentSenderLocked(rec, false);
4673 }
4674 }
4675 r.pendingResults = null;
4676 }
4677
4678 if (cleanServices) {
4679 cleanUpActivityServicesLocked(r);
4680 }
4681
4682 if (mPendingThumbnails.size() > 0) {
4683 // There are clients waiting to receive thumbnails so, in case
4684 // this is an activity that someone is waiting for, add it
4685 // to the pending list so we can correctly update the clients.
4686 mCancelledThumbnails.add(r);
4687 }
4688
4689 // Get rid of any pending idle timeouts.
4690 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4691 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4692 }
4693
4694 private final void removeActivityFromHistoryLocked(HistoryRecord r) {
4695 if (r.state != ActivityState.DESTROYED) {
4696 mHistory.remove(r);
4697 r.inHistory = false;
4698 r.state = ActivityState.DESTROYED;
4699 mWindowManager.removeAppToken(r);
4700 if (VALIDATE_TOKENS) {
4701 mWindowManager.validateAppTokens(mHistory);
4702 }
4703 cleanUpActivityServicesLocked(r);
4704 removeActivityUriPermissionsLocked(r);
4705 }
4706 }
4707
4708 /**
4709 * Destroy the current CLIENT SIDE instance of an activity. This may be
4710 * called both when actually finishing an activity, or when performing
4711 * a configuration switch where we destroy the current client-side object
4712 * but then create a new client-side object for this same HistoryRecord.
4713 */
4714 private final boolean destroyActivityLocked(HistoryRecord r,
4715 boolean removeFromApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004716 if (DEBUG_SWITCH) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 TAG, "Removing activity: token=" + r
4718 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
Doug Zongker2bec3d42009-12-04 12:52:44 -08004719 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 System.identityHashCode(r),
4721 r.task.taskId, r.shortComponentName);
4722
4723 boolean removedFromHistory = false;
4724
4725 cleanUpActivityLocked(r, false);
4726
Dianne Hackborn03abb812010-01-04 18:43:19 -08004727 final boolean hadApp = r.app != null;
4728
4729 if (hadApp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730 if (removeFromApp) {
4731 int idx = r.app.activities.indexOf(r);
4732 if (idx >= 0) {
4733 r.app.activities.remove(idx);
4734 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004735 if (mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4736 mHeavyWeightProcess = null;
4737 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
4738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 if (r.persistent) {
4740 decPersistentCountLocked(r.app);
4741 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004742 if (r.app.activities.size() == 0) {
4743 // No longer have activities, so update location in
4744 // LRU list.
4745 updateLruProcessLocked(r.app, true, false);
4746 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 }
4748
4749 boolean skipDestroy = false;
4750
4751 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004752 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004753 r.app.thread.scheduleDestroyActivity(r, r.finishing,
4754 r.configChangeFlags);
4755 } catch (Exception e) {
4756 // We can just ignore exceptions here... if the process
4757 // has crashed, our death notification will clean things
4758 // up.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004759 //Slog.w(TAG, "Exception thrown during finish", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004760 if (r.finishing) {
4761 removeActivityFromHistoryLocked(r);
4762 removedFromHistory = true;
4763 skipDestroy = true;
4764 }
4765 }
4766
4767 r.app = null;
4768 r.nowVisible = false;
4769
4770 if (r.finishing && !skipDestroy) {
4771 r.state = ActivityState.DESTROYING;
4772 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4773 msg.obj = r;
4774 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4775 } else {
4776 r.state = ActivityState.DESTROYED;
4777 }
4778 } else {
4779 // remove this record from the history.
4780 if (r.finishing) {
4781 removeActivityFromHistoryLocked(r);
4782 removedFromHistory = true;
4783 } else {
4784 r.state = ActivityState.DESTROYED;
4785 }
4786 }
4787
4788 r.configChangeFlags = 0;
4789
Dianne Hackborn03abb812010-01-04 18:43:19 -08004790 if (!mLRUActivities.remove(r) && hadApp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004791 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792 }
4793
4794 return removedFromHistory;
4795 }
4796
Dianne Hackborn03abb812010-01-04 18:43:19 -08004797 private static void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004798 int i = list.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004799 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 TAG, "Removing app " + app + " from list " + list
4801 + " with " + i + " entries");
4802 while (i > 0) {
4803 i--;
4804 HistoryRecord r = (HistoryRecord)list.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004805 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4807 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004808 if (localLOGV) Slog.v(TAG, "Removing this entry!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 list.remove(i);
4810 }
4811 }
4812 }
4813
4814 /**
4815 * Main function for removing an existing process from the activity manager
4816 * as a result of that process going away. Clears out all connections
4817 * to the process.
4818 */
4819 private final void handleAppDiedLocked(ProcessRecord app,
4820 boolean restarting) {
4821 cleanUpApplicationRecordLocked(app, restarting, -1);
4822 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004823 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824 }
4825
4826 // Just in case...
4827 if (mPausingActivity != null && mPausingActivity.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004828 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + mPausingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004829 mPausingActivity = null;
4830 }
4831 if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4832 mLastPausedActivity = null;
4833 }
4834
4835 // Remove this application's activities from active lists.
4836 removeHistoryRecordsForAppLocked(mLRUActivities, app);
4837 removeHistoryRecordsForAppLocked(mStoppingActivities, app);
4838 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
4839 removeHistoryRecordsForAppLocked(mFinishingActivities, app);
4840
4841 boolean atTop = true;
4842 boolean hasVisibleActivities = false;
4843
4844 // Clean out the history list.
4845 int i = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004846 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 TAG, "Removing app " + app + " from history with " + i + " entries");
4848 while (i > 0) {
4849 i--;
4850 HistoryRecord r = (HistoryRecord)mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004851 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004852 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4853 if (r.app == app) {
4854 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004855 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004856 TAG, "Removing this entry! frozen=" + r.haveState
4857 + " finishing=" + r.finishing);
4858 mHistory.remove(i);
4859
4860 r.inHistory = false;
4861 mWindowManager.removeAppToken(r);
4862 if (VALIDATE_TOKENS) {
4863 mWindowManager.validateAppTokens(mHistory);
4864 }
4865 removeActivityUriPermissionsLocked(r);
4866
4867 } else {
4868 // We have the current state for this activity, so
4869 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004870 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004871 TAG, "Keeping entry, setting app to null");
4872 if (r.visible) {
4873 hasVisibleActivities = true;
4874 }
4875 r.app = null;
4876 r.nowVisible = false;
4877 if (!r.haveState) {
4878 r.icicle = null;
4879 }
4880 }
4881
4882 cleanUpActivityLocked(r, true);
4883 r.state = ActivityState.STOPPED;
4884 }
4885 atTop = false;
4886 }
4887
4888 app.activities.clear();
4889
4890 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004891 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892 + " running instrumentation " + app.instrumentationClass);
4893 Bundle info = new Bundle();
4894 info.putString("shortMsg", "Process crashed.");
4895 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
4896 }
4897
4898 if (!restarting) {
4899 if (!resumeTopActivityLocked(null)) {
4900 // If there was nothing to resume, and we are not already
4901 // restarting this process, but there is a visible activity that
4902 // is hosted by the process... then make sure all visible
4903 // activities are running, taking care of restarting this
4904 // process.
4905 if (hasVisibleActivities) {
4906 ensureActivitiesVisibleLocked(null, 0);
4907 }
4908 }
4909 }
4910 }
4911
4912 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
4913 IBinder threadBinder = thread.asBinder();
4914
4915 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004916 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4917 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
4919 return i;
4920 }
4921 }
4922 return -1;
4923 }
4924
4925 private final ProcessRecord getRecordForAppLocked(
4926 IApplicationThread thread) {
4927 if (thread == null) {
4928 return null;
4929 }
4930
4931 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004932 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 }
4934
4935 private final void appDiedLocked(ProcessRecord app, int pid,
4936 IApplicationThread thread) {
4937
4938 mProcDeaths[0]++;
4939
Magnus Edlund7bb25812010-02-24 15:45:06 +01004940 // Clean up already done if the process has been re-started.
4941 if (app.pid == pid && app.thread != null &&
4942 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07004943 if (!app.killedBackground) {
4944 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
4945 + ") has died.");
4946 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08004947 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004948 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 TAG, "Dying app: " + app + ", pid: " + pid
4950 + ", thread: " + thread.asBinder());
4951 boolean doLowMem = app.instrumentationClass == null;
4952 handleAppDiedLocked(app, false);
4953
4954 if (doLowMem) {
4955 // If there are no longer any background processes running,
4956 // and the app that died was not running instrumentation,
4957 // then tell everyone we are now low on memory.
4958 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004959 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4960 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
4962 haveBg = true;
4963 break;
4964 }
4965 }
4966
4967 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004968 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004969 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004970 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08004971 for (int i=mLruProcesses.size()-1; i>=0; i--) {
4972 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07004973 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004974 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
4975 // The low memory report is overriding any current
4976 // state for a GC request. Make sure to do
4977 // visible/foreground processes first.
4978 if (rec.setAdj <= VISIBLE_APP_ADJ) {
4979 rec.lastRequestedGc = 0;
4980 } else {
4981 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004983 rec.reportLowMemory = true;
4984 rec.lastLowMemory = now;
4985 mProcessesToGc.remove(rec);
4986 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004987 }
4988 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07004989 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 }
4991 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01004992 } else if (app.pid != pid) {
4993 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004994 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01004995 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08004996 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08004997 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004998 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 + thread.asBinder());
5000 }
5001 }
5002
Dan Egnor42471dd2010-01-07 17:25:22 -08005003 /**
5004 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07005005 * @param clearTraces causes the dump file to be erased prior to the new
5006 * traces being written, if true; when false, the new traces will be
5007 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08005008 * @param pids of dalvik VM processes to dump stack traces for
5009 * @return file containing stack traces, or null if no dump file is configured
5010 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07005011 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005012 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
5013 if (tracesPath == null || tracesPath.length() == 0) {
5014 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005015 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005016
5017 File tracesFile = new File(tracesPath);
5018 try {
5019 File tracesDir = tracesFile.getParentFile();
5020 if (!tracesDir.exists()) tracesFile.mkdirs();
5021 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
5022
Christopher Tate6ee412d2010-05-28 12:01:56 -07005023 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08005024 tracesFile.createNewFile();
5025 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
5026 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005027 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005028 return null;
5029 }
5030
5031 // Use a FileObserver to detect when traces finish writing.
5032 // The order of traces is considered important to maintain for legibility.
5033 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
5034 public synchronized void onEvent(int event, String path) { notify(); }
5035 };
5036
5037 try {
5038 observer.startWatching();
5039 int num = pids.size();
5040 for (int i = 0; i < num; i++) {
5041 synchronized (observer) {
5042 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
5043 observer.wait(200); // Wait for write-close, give up after 200msec
5044 }
5045 }
5046 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08005047 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08005048 } finally {
5049 observer.stopWatching();
5050 }
5051
5052 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 }
5054
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005055 final void appNotResponding(ProcessRecord app, HistoryRecord activity,
Dan Egnor42471dd2010-01-07 17:25:22 -08005056 HistoryRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005057 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005058
5059 synchronized (this) {
5060 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
5061 if (mShuttingDown) {
5062 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
5063 return;
5064 } else if (app.notResponding) {
5065 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
5066 return;
5067 } else if (app.crashing) {
5068 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
5069 return;
5070 }
5071
5072 // In case we come through here for the same app before completing
5073 // this one, mark as anring now so we will bail out.
5074 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08005075
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005076 // Log the ANR to the event log.
5077 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
5078 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08005079
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005080 // Dump thread traces as quickly as we can, starting with "interesting" processes.
5081 pids.add(app.pid);
5082
5083 int parentPid = app.pid;
5084 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
5085 if (parentPid != app.pid) pids.add(parentPid);
5086
5087 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08005088
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005089 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
5090 ProcessRecord r = mLruProcesses.get(i);
5091 if (r != null && r.thread != null) {
5092 int pid = r.pid;
5093 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
5094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005095 }
5096 }
5097
Christopher Tate6ee412d2010-05-28 12:01:56 -07005098 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08005099
5100 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005101 StringBuilder info = mStringBuilder;
5102 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08005103 info.append("ANR in ").append(app.processName);
5104 if (activity != null && activity.shortComponentName != null) {
5105 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07005106 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08005107 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005108 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005109 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005111 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08005112 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114
Dan Egnor42471dd2010-01-07 17:25:22 -08005115 String cpuInfo = null;
5116 if (MONITOR_CPU_USAGE) {
5117 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005118 synchronized (mProcessStatsThread) {
5119 cpuInfo = mProcessStats.printCurrentState();
5120 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005121 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005122 }
5123
Joe Onorato8a9b2202010-02-26 18:56:32 -08005124 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08005125 if (tracesFile == null) {
5126 // There is no trace file, so dump (only) the alleged culprit's threads to the log
5127 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
5128 }
5129
5130 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
5131
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005132 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005133 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08005134 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
5135 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005136 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005137 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
5138 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 }
5140 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005141 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005142 }
5143 }
5144
Dan Egnor42471dd2010-01-07 17:25:22 -08005145 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
5146 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
5147 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07005148
5149 synchronized (this) {
5150 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
5151 Process.killProcess(app.pid);
5152 return;
5153 }
5154
5155 // Set the app's notResponding state, and look up the errorReportReceiver
5156 makeAppNotRespondingLocked(app,
5157 activity != null ? activity.shortComponentName : null,
5158 annotation != null ? "ANR " + annotation : "ANR",
5159 info.toString());
5160
5161 // Bring up the infamous App Not Responding dialog
5162 Message msg = Message.obtain();
5163 HashMap map = new HashMap();
5164 msg.what = SHOW_NOT_RESPONDING_MSG;
5165 msg.obj = map;
5166 map.put("app", app);
5167 if (activity != null) {
5168 map.put("activity", activity);
5169 }
5170
5171 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08005172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005173 }
5174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 private final void decPersistentCountLocked(ProcessRecord app)
5176 {
5177 app.persistentActivities--;
5178 if (app.persistentActivities > 0) {
5179 // Still more of 'em...
5180 return;
5181 }
5182 if (app.persistent) {
5183 // Ah, but the application itself is persistent. Whatever!
5184 return;
5185 }
5186
5187 // App is no longer persistent... make sure it and the ones
5188 // following it in the LRU list have the correc oom_adj.
5189 updateOomAdjLocked();
5190 }
5191
5192 public void setPersistent(IBinder token, boolean isPersistent) {
5193 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
5194 != PackageManager.PERMISSION_GRANTED) {
5195 String msg = "Permission Denial: setPersistent() from pid="
5196 + Binder.getCallingPid()
5197 + ", uid=" + Binder.getCallingUid()
5198 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005199 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 throw new SecurityException(msg);
5201 }
5202
5203 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07005204 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005205 if (index < 0) {
5206 return;
5207 }
5208 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5209 ProcessRecord app = r.app;
5210
Joe Onorato8a9b2202010-02-26 18:56:32 -08005211 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005212 TAG, "Setting persistence " + isPersistent + ": " + r);
5213
5214 if (isPersistent) {
5215 if (r.persistent) {
5216 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005217 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 return;
5219 }
5220 r.persistent = true;
5221 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005222 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 if (app.persistentActivities > 1) {
5224 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005225 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005226 return;
5227 }
5228 if (app.persistent) {
5229 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005230 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231 return;
5232 }
5233
5234 // App is now persistent... make sure it and the ones
5235 // following it now have the correct oom_adj.
5236 final long origId = Binder.clearCallingIdentity();
5237 updateOomAdjLocked();
5238 Binder.restoreCallingIdentity(origId);
5239
5240 } else {
5241 if (!r.persistent) {
5242 // Okay okay, I heard you already!
5243 return;
5244 }
5245 r.persistent = false;
5246 final long origId = Binder.clearCallingIdentity();
5247 decPersistentCountLocked(app);
5248 Binder.restoreCallingIdentity(origId);
5249
5250 }
5251 }
5252 }
5253
5254 public boolean clearApplicationUserData(final String packageName,
5255 final IPackageDataObserver observer) {
5256 int uid = Binder.getCallingUid();
5257 int pid = Binder.getCallingPid();
5258 long callingId = Binder.clearCallingIdentity();
5259 try {
5260 IPackageManager pm = ActivityThread.getPackageManager();
5261 int pkgUid = -1;
5262 synchronized(this) {
5263 try {
5264 pkgUid = pm.getPackageUid(packageName);
5265 } catch (RemoteException e) {
5266 }
5267 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005268 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 return false;
5270 }
5271 if (uid == pkgUid || checkComponentPermission(
5272 android.Manifest.permission.CLEAR_APP_USER_DATA,
5273 pid, uid, -1)
5274 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005275 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 } else {
5277 throw new SecurityException(pid+" does not have permission:"+
5278 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
5279 "for process:"+packageName);
5280 }
5281 }
5282
5283 try {
5284 //clear application user data
5285 pm.clearApplicationUserData(packageName, observer);
5286 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
5287 Uri.fromParts("package", packageName, null));
5288 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06005289 synchronized (this) {
5290 broadcastIntentLocked(null, null, intent,
5291 null, null, 0, null, null, null,
5292 false, false, MY_PID, Process.SYSTEM_UID);
5293 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 } catch (RemoteException e) {
5295 }
5296 } finally {
5297 Binder.restoreCallingIdentity(callingId);
5298 }
5299 return true;
5300 }
5301
Dianne Hackborn03abb812010-01-04 18:43:19 -08005302 public void killBackgroundProcesses(final String packageName) {
5303 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
5304 != PackageManager.PERMISSION_GRANTED &&
5305 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
5306 != PackageManager.PERMISSION_GRANTED) {
5307 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005308 + Binder.getCallingPid()
5309 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08005310 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005311 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 throw new SecurityException(msg);
5313 }
5314
5315 long callingId = Binder.clearCallingIdentity();
5316 try {
5317 IPackageManager pm = ActivityThread.getPackageManager();
5318 int pkgUid = -1;
5319 synchronized(this) {
5320 try {
5321 pkgUid = pm.getPackageUid(packageName);
5322 } catch (RemoteException e) {
5323 }
5324 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005325 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 return;
5327 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005328 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005329 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005330 }
5331 } finally {
5332 Binder.restoreCallingIdentity(callingId);
5333 }
5334 }
5335
5336 public void forceStopPackage(final String packageName) {
5337 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
5338 != PackageManager.PERMISSION_GRANTED) {
5339 String msg = "Permission Denial: forceStopPackage() from pid="
5340 + Binder.getCallingPid()
5341 + ", uid=" + Binder.getCallingUid()
5342 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005343 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005344 throw new SecurityException(msg);
5345 }
5346
5347 long callingId = Binder.clearCallingIdentity();
5348 try {
5349 IPackageManager pm = ActivityThread.getPackageManager();
5350 int pkgUid = -1;
5351 synchronized(this) {
5352 try {
5353 pkgUid = pm.getPackageUid(packageName);
5354 } catch (RemoteException e) {
5355 }
5356 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005357 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005358 return;
5359 }
5360 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005361 }
5362 } finally {
5363 Binder.restoreCallingIdentity(callingId);
5364 }
5365 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005366
5367 /*
5368 * The pkg name and uid have to be specified.
5369 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
5370 */
5371 public void killApplicationWithUid(String pkg, int uid) {
5372 if (pkg == null) {
5373 return;
5374 }
5375 // Make sure the uid is valid.
5376 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005377 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005378 return;
5379 }
5380 int callerUid = Binder.getCallingUid();
5381 // Only the system server can kill an application
5382 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07005383 // Post an aysnc message to kill the application
5384 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
5385 msg.arg1 = uid;
5386 msg.arg2 = 0;
5387 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07005388 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005389 } else {
5390 throw new SecurityException(callerUid + " cannot kill pkg: " +
5391 pkg);
5392 }
5393 }
5394
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005395 public void closeSystemDialogs(String reason) {
5396 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
5397 if (reason != null) {
5398 intent.putExtra("reason", reason);
5399 }
5400
5401 final int uid = Binder.getCallingUid();
5402 final long origId = Binder.clearCallingIdentity();
5403 synchronized (this) {
5404 int i = mWatchers.beginBroadcast();
5405 while (i > 0) {
5406 i--;
5407 IActivityWatcher w = mWatchers.getBroadcastItem(i);
5408 if (w != null) {
5409 try {
5410 w.closingSystemDialogs(reason);
5411 } catch (RemoteException e) {
5412 }
5413 }
5414 }
5415 mWatchers.finishBroadcast();
5416
Dianne Hackbornffa42482009-09-23 22:20:11 -07005417 mWindowManager.closeSystemDialogs(reason);
5418
5419 for (i=mHistory.size()-1; i>=0; i--) {
5420 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5421 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
5422 finishActivityLocked(r, i,
5423 Activity.RESULT_CANCELED, null, "close-sys");
5424 }
5425 }
5426
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07005427 broadcastIntentLocked(null, null, intent, null,
5428 null, 0, null, null, null, false, false, -1, uid);
5429 }
5430 Binder.restoreCallingIdentity(origId);
5431 }
5432
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005433 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005434 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005435 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
5436 for (int i=pids.length-1; i>=0; i--) {
5437 infos[i] = new Debug.MemoryInfo();
5438 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005439 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07005440 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07005441 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07005442
5443 public void killApplicationProcess(String processName, int uid) {
5444 if (processName == null) {
5445 return;
5446 }
5447
5448 int callerUid = Binder.getCallingUid();
5449 // Only the system server can kill an application
5450 if (callerUid == Process.SYSTEM_UID) {
5451 synchronized (this) {
5452 ProcessRecord app = getProcessRecordLocked(processName, uid);
5453 if (app != null) {
5454 try {
5455 app.thread.scheduleSuicide();
5456 } catch (RemoteException e) {
5457 // If the other end already died, then our work here is done.
5458 }
5459 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005460 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07005461 + processName + " / " + uid);
5462 }
5463 }
5464 } else {
5465 throw new SecurityException(callerUid + " cannot kill app process: " +
5466 processName);
5467 }
5468 }
5469
Dianne Hackborn03abb812010-01-04 18:43:19 -08005470 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005471 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
5473 Uri.fromParts("package", packageName, null));
5474 intent.putExtra(Intent.EXTRA_UID, uid);
5475 broadcastIntentLocked(null, null, intent,
5476 null, null, 0, null, null, null,
5477 false, false, MY_PID, Process.SYSTEM_UID);
5478 }
5479
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005480 private final boolean killPackageProcessesLocked(String packageName, int uid,
5481 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08005482 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005483
Dianne Hackborn03abb812010-01-04 18:43:19 -08005484 // Remove all processes this package may have touched: all with the
5485 // same UID (except for the system or root user), and all whose name
5486 // matches the package name.
5487 final String procNamePrefix = packageName + ":";
5488 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
5489 final int NA = apps.size();
5490 for (int ia=0; ia<NA; ia++) {
5491 ProcessRecord app = apps.valueAt(ia);
5492 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005493 if (doit) {
5494 procs.add(app);
5495 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005496 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
5497 || app.processName.equals(packageName)
5498 || app.processName.startsWith(procNamePrefix)) {
5499 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005500 if (!doit) {
5501 return true;
5502 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08005503 app.removed = true;
5504 procs.add(app);
5505 }
5506 }
5507 }
5508 }
5509
5510 int N = procs.size();
5511 for (int i=0; i<N; i++) {
5512 removeProcessLocked(procs.get(i), callerWillRestart);
5513 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005514 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08005515 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005516
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005517 private final boolean forceStopPackageLocked(String name, int uid,
5518 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 int i, N;
5520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 if (uid < 0) {
5522 try {
5523 uid = ActivityThread.getPackageManager().getPackageUid(name);
5524 } catch (RemoteException e) {
5525 }
5526 }
5527
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005528 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005529 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08005530
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005531 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
5532 while (badApps.hasNext()) {
5533 SparseArray<Long> ba = badApps.next();
5534 if (ba.get(uid) != null) {
5535 badApps.remove();
5536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005537 }
5538 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005539
5540 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
5541 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005542
5543 for (i=mHistory.size()-1; i>=0; i--) {
5544 HistoryRecord r = (HistoryRecord)mHistory.get(i);
5545 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005546 if (!doit) {
5547 return true;
5548 }
5549 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005550 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 if (r.app != null) {
5552 r.app.removed = true;
5553 }
5554 r.app = null;
5555 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
5556 }
5557 }
5558
5559 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5560 for (ServiceRecord service : mServices.values()) {
5561 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005562 if (!doit) {
5563 return true;
5564 }
5565 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005566 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 if (service.app != null) {
5568 service.app.removed = true;
5569 }
5570 service.app = null;
5571 services.add(service);
5572 }
5573 }
5574
5575 N = services.size();
5576 for (i=0; i<N; i++) {
5577 bringDownServiceLocked(services.get(i), true);
5578 }
5579
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005580 if (doit) {
5581 if (purgeCache) {
5582 AttributeCache ac = AttributeCache.instance();
5583 if (ac != null) {
5584 ac.removePackage(name);
5585 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005586 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005587 resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005588 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005589
5590 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005591 }
5592
5593 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
5594 final String name = app.processName;
5595 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005596 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 TAG, "Force removing process " + app + " (" + name
5598 + "/" + uid + ")");
5599
5600 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005601 if (mHeavyWeightProcess == app) {
5602 mHeavyWeightProcess = null;
5603 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5604 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005605 boolean needRestart = false;
5606 if (app.pid > 0 && app.pid != MY_PID) {
5607 int pid = app.pid;
5608 synchronized (mPidsSelfLocked) {
5609 mPidsSelfLocked.remove(pid);
5610 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5611 }
5612 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005613 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005614 Process.killProcess(pid);
5615
5616 if (app.persistent) {
5617 if (!callerWillRestart) {
5618 addAppLocked(app.info);
5619 } else {
5620 needRestart = true;
5621 }
5622 }
5623 } else {
5624 mRemovedProcesses.add(app);
5625 }
5626
5627 return needRestart;
5628 }
5629
5630 private final void processStartTimedOutLocked(ProcessRecord app) {
5631 final int pid = app.pid;
5632 boolean gone = false;
5633 synchronized (mPidsSelfLocked) {
5634 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
5635 if (knownApp != null && knownApp.thread == null) {
5636 mPidsSelfLocked.remove(pid);
5637 gone = true;
5638 }
5639 }
5640
5641 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005642 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005643 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005644 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005645 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005646 if (mHeavyWeightProcess == app) {
5647 mHeavyWeightProcess = null;
5648 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
5649 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005650 // Take care of any launching providers waiting for this process.
5651 checkAppInLaunchingProvidersLocked(app, true);
5652 // Take care of any services that are waiting for the process.
5653 for (int i=0; i<mPendingServices.size(); i++) {
5654 ServiceRecord sr = mPendingServices.get(i);
5655 if (app.info.uid == sr.appInfo.uid
5656 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005657 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005658 mPendingServices.remove(i);
5659 i--;
5660 bringDownServiceLocked(sr, true);
5661 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005662 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005663 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07005664 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005665 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07005666 try {
5667 IBackupManager bm = IBackupManager.Stub.asInterface(
5668 ServiceManager.getService(Context.BACKUP_SERVICE));
5669 bm.agentDisconnected(app.info.packageName);
5670 } catch (RemoteException e) {
5671 // Can't happen; the backup manager is local
5672 }
5673 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005674 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005675 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08005676 mPendingBroadcast = null;
5677 scheduleBroadcastsLocked();
5678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005680 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005681 }
5682 }
5683
5684 private final boolean attachApplicationLocked(IApplicationThread thread,
5685 int pid) {
5686
5687 // Find the application record that is being attached... either via
5688 // the pid if we are running in multiple processes, or just pull the
5689 // next app record if we are emulating process with anonymous threads.
5690 ProcessRecord app;
5691 if (pid != MY_PID && pid >= 0) {
5692 synchronized (mPidsSelfLocked) {
5693 app = mPidsSelfLocked.get(pid);
5694 }
5695 } else if (mStartingProcesses.size() > 0) {
5696 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07005697 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005698 } else {
5699 app = null;
5700 }
5701
5702 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005703 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005704 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005705 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005706 if (pid > 0 && pid != MY_PID) {
5707 Process.killProcess(pid);
5708 } else {
5709 try {
5710 thread.scheduleExit();
5711 } catch (Exception e) {
5712 // Ignore exceptions.
5713 }
5714 }
5715 return false;
5716 }
5717
5718 // If this application record is still attached to a previous
5719 // process, clean it up now.
5720 if (app.thread != null) {
5721 handleAppDiedLocked(app, true);
5722 }
5723
5724 // Tell the process all about itself.
5725
Joe Onorato8a9b2202010-02-26 18:56:32 -08005726 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005727 TAG, "Binding process pid " + pid + " to record " + app);
5728
5729 String processName = app.processName;
5730 try {
5731 thread.asBinder().linkToDeath(new AppDeathRecipient(
5732 app, pid, thread), 0);
5733 } catch (RemoteException e) {
5734 app.resetPackageList();
5735 startProcessLocked(app, "link fail", processName);
5736 return false;
5737 }
5738
Doug Zongker2bec3d42009-12-04 12:52:44 -08005739 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005740
5741 app.thread = thread;
5742 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08005743 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
5744 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005745 app.forcingToForeground = null;
5746 app.foregroundServices = false;
5747 app.debugging = false;
5748
5749 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
5750
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005751 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
5752 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005753
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005754 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005755 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005756 }
5757
Joe Onorato8a9b2202010-02-26 18:56:32 -08005758 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005759 TAG, "New app record " + app
5760 + " thread=" + thread.asBinder() + " pid=" + pid);
5761 try {
5762 int testMode = IApplicationThread.DEBUG_OFF;
5763 if (mDebugApp != null && mDebugApp.equals(processName)) {
5764 testMode = mWaitForDebugger
5765 ? IApplicationThread.DEBUG_WAIT
5766 : IApplicationThread.DEBUG_ON;
5767 app.debugging = true;
5768 if (mDebugTransient) {
5769 mDebugApp = mOrigDebugApp;
5770 mWaitForDebugger = mOrigWaitForDebugger;
5771 }
5772 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005773
Christopher Tate181fafa2009-05-14 11:12:14 -07005774 // If the app is being launched for restore or full backup, set it up specially
5775 boolean isRestrictedBackupMode = false;
5776 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
5777 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
5778 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
5779 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005780
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07005781 ensurePackageDexOpt(app.instrumentationInfo != null
5782 ? app.instrumentationInfo.packageName
5783 : app.info.packageName);
5784 if (app.instrumentationClass != null) {
5785 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005786 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005787 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07005788 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07005789 thread.bindApplication(processName, app.instrumentationInfo != null
5790 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 app.instrumentationClass, app.instrumentationProfileFile,
5792 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005793 isRestrictedBackupMode || !normalMode,
5794 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005795 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07005796 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005797 } catch (Exception e) {
5798 // todo: Yikes! What should we do? For now we will try to
5799 // start another process, but that could easily get us in
5800 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08005801 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005802
5803 app.resetPackageList();
5804 startProcessLocked(app, "bind fail", processName);
5805 return false;
5806 }
5807
5808 // Remove this record from the list of starting applications.
5809 mPersistentStartingProcesses.remove(app);
5810 mProcessesOnHold.remove(app);
5811
5812 boolean badApp = false;
5813 boolean didSomething = false;
5814
5815 // See if the top visible activity is waiting to run in this process...
5816 HistoryRecord hr = topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07005817 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
5819 && processName.equals(hr.processName)) {
5820 try {
5821 if (realStartActivityLocked(hr, app, true, true)) {
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 activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005826 + hr.intent.getComponent().flattenToShortString(), e);
5827 badApp = true;
5828 }
5829 } else {
5830 ensureActivitiesVisibleLocked(hr, null, processName, 0);
5831 }
5832 }
5833
5834 // Find any services that should be running in this process...
5835 if (!badApp && mPendingServices.size() > 0) {
5836 ServiceRecord sr = null;
5837 try {
5838 for (int i=0; i<mPendingServices.size(); i++) {
5839 sr = mPendingServices.get(i);
5840 if (app.info.uid != sr.appInfo.uid
5841 || !processName.equals(sr.processName)) {
5842 continue;
5843 }
5844
5845 mPendingServices.remove(i);
5846 i--;
5847 realStartServiceLocked(sr, app);
5848 didSomething = true;
5849 }
5850 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005851 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005852 + sr.shortName, e);
5853 badApp = true;
5854 }
5855 }
5856
5857 // Check if the next broadcast receiver is in this process...
5858 BroadcastRecord br = mPendingBroadcast;
5859 if (!badApp && br != null && br.curApp == app) {
5860 try {
5861 mPendingBroadcast = null;
5862 processCurBroadcastLocked(br, app);
5863 didSomething = true;
5864 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005865 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 + br.curComponent.flattenToShortString(), e);
5867 badApp = true;
5868 logBroadcastReceiverDiscard(br);
5869 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
5870 br.resultExtras, br.resultAbort, true);
5871 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01005872 // We need to reset the state if we fails to start the receiver.
5873 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005874 }
5875 }
5876
Christopher Tate181fafa2009-05-14 11:12:14 -07005877 // Check whether the next backup agent is in this process...
5878 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005879 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005880 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07005881 try {
5882 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
5883 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005884 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07005885 e.printStackTrace();
5886 }
5887 }
5888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005889 if (badApp) {
5890 // todo: Also need to kill application to deal with all
5891 // kinds of exceptions.
5892 handleAppDiedLocked(app, false);
5893 return false;
5894 }
5895
5896 if (!didSomething) {
5897 updateOomAdjLocked();
5898 }
5899
5900 return true;
5901 }
5902
5903 public final void attachApplication(IApplicationThread thread) {
5904 synchronized (this) {
5905 int callingPid = Binder.getCallingPid();
5906 final long origId = Binder.clearCallingIdentity();
5907 attachApplicationLocked(thread, callingPid);
5908 Binder.restoreCallingIdentity(origId);
5909 }
5910 }
5911
Dianne Hackborne88846e2009-09-30 21:34:25 -07005912 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005913 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne88846e2009-09-30 21:34:25 -07005914 activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 Binder.restoreCallingIdentity(origId);
5916 }
5917
5918 final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
5919 boolean remove) {
5920 int N = mStoppingActivities.size();
5921 if (N <= 0) return null;
5922
5923 ArrayList<HistoryRecord> stops = null;
5924
5925 final boolean nowVisible = mResumedActivity != null
5926 && mResumedActivity.nowVisible
5927 && !mResumedActivity.waitingVisible;
5928 for (int i=0; i<N; i++) {
5929 HistoryRecord s = mStoppingActivities.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005930 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 + nowVisible + " waitingVisible=" + s.waitingVisible
5932 + " finishing=" + s.finishing);
5933 if (s.waitingVisible && nowVisible) {
5934 mWaitingVisibleActivities.remove(s);
5935 s.waitingVisible = false;
5936 if (s.finishing) {
5937 // If this activity is finishing, it is sitting on top of
5938 // everyone else but we now know it is no longer needed...
5939 // so get rid of it. Otherwise, we need to go through the
5940 // normal flow and hide it once we determine that it is
5941 // hidden by the activities in front of it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005942 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943 mWindowManager.setAppVisibility(s, false);
5944 }
5945 }
5946 if (!s.waitingVisible && remove) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005947 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005948 if (stops == null) {
5949 stops = new ArrayList<HistoryRecord>();
5950 }
5951 stops.add(s);
5952 mStoppingActivities.remove(i);
5953 N--;
5954 i--;
5955 }
5956 }
5957
5958 return stops;
5959 }
5960
5961 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08005962 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005963 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 mWindowManager.enableScreenAfterBoot();
5965 }
5966
Dianne Hackborne88846e2009-09-30 21:34:25 -07005967 final void activityIdleInternal(IBinder token, boolean fromTimeout,
5968 Configuration config) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005969 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970
5971 ArrayList<HistoryRecord> stops = null;
5972 ArrayList<HistoryRecord> finishes = null;
5973 ArrayList<HistoryRecord> thumbnails = null;
5974 int NS = 0;
5975 int NF = 0;
5976 int NT = 0;
5977 IApplicationThread sendThumbnail = null;
5978 boolean booting = false;
5979 boolean enableScreen = false;
5980
5981 synchronized (this) {
5982 if (token != null) {
5983 mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
5984 }
5985
5986 // Get the activity record.
Dianne Hackborn75b03852009-06-12 15:43:26 -07005987 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005988 if (index >= 0) {
5989 HistoryRecord r = (HistoryRecord)mHistory.get(index);
5990
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08005991 if (fromTimeout) {
5992 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
5993 }
5994
Dianne Hackborne88846e2009-09-30 21:34:25 -07005995 // This is a hack to semi-deal with a race condition
5996 // in the client where it can be constructed with a
5997 // newer configuration from when we asked it to launch.
5998 // We'll update with whatever configuration it now says
5999 // it used to launch.
6000 if (config != null) {
6001 r.configuration = config;
6002 }
6003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006004 // No longer need to keep the device awake.
6005 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
6006 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
6007 mLaunchingActivity.release();
6008 }
6009
6010 // We are now idle. If someone is waiting for a thumbnail from
6011 // us, we can now deliver.
6012 r.idle = true;
6013 scheduleAppGcsLocked();
6014 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
6015 sendThumbnail = r.app.thread;
6016 r.thumbnailNeeded = false;
6017 }
6018
6019 // If this activity is fullscreen, set up to hide those under it.
6020
Joe Onorato8a9b2202010-02-26 18:56:32 -08006021 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 ensureActivitiesVisibleLocked(null, 0);
6023
Joe Onorato8a9b2202010-02-26 18:56:32 -08006024 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 if (!mBooted && !fromTimeout) {
6026 mBooted = true;
6027 enableScreen = true;
6028 }
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08006029
6030 } else if (fromTimeout) {
6031 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 }
6033
6034 // Atomically retrieve all of the other things to do.
6035 stops = processStoppingActivitiesLocked(true);
6036 NS = stops != null ? stops.size() : 0;
6037 if ((NF=mFinishingActivities.size()) > 0) {
6038 finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
6039 mFinishingActivities.clear();
6040 }
6041 if ((NT=mCancelledThumbnails.size()) > 0) {
6042 thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
6043 mCancelledThumbnails.clear();
6044 }
6045
6046 booting = mBooting;
6047 mBooting = false;
6048 }
6049
6050 int i;
6051
6052 // Send thumbnail if requested.
6053 if (sendThumbnail != null) {
6054 try {
6055 sendThumbnail.requestThumbnail(token);
6056 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006057 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006058 sendPendingThumbnail(null, token, null, null, true);
6059 }
6060 }
6061
6062 // Stop any activities that are scheduled to do so but have been
6063 // waiting for the next one to start.
6064 for (i=0; i<NS; i++) {
6065 HistoryRecord r = (HistoryRecord)stops.get(i);
6066 synchronized (this) {
6067 if (r.finishing) {
6068 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
6069 } else {
6070 stopActivityLocked(r);
6071 }
6072 }
6073 }
6074
6075 // Finish any activities that are scheduled to do so but have been
6076 // waiting for the next one to start.
6077 for (i=0; i<NF; i++) {
6078 HistoryRecord r = (HistoryRecord)finishes.get(i);
6079 synchronized (this) {
6080 destroyActivityLocked(r, true);
6081 }
6082 }
6083
6084 // Report back to any thumbnail receivers.
6085 for (i=0; i<NT; i++) {
6086 HistoryRecord r = (HistoryRecord)thumbnails.get(i);
6087 sendPendingThumbnail(r, null, null, null, true);
6088 }
6089
6090 if (booting) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006091 finishBooting();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006092 }
6093
6094 trimApplications();
6095 //dump();
6096 //mWindowManager.dump();
6097
6098 if (enableScreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006099 enableScreenAfterBoot();
6100 }
6101 }
6102
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006103 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006104 IntentFilter pkgFilter = new IntentFilter();
6105 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
6106 pkgFilter.addDataScheme("package");
6107 mContext.registerReceiver(new BroadcastReceiver() {
6108 @Override
6109 public void onReceive(Context context, Intent intent) {
6110 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
6111 if (pkgs != null) {
6112 for (String pkg : pkgs) {
6113 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
6114 setResultCode(Activity.RESULT_OK);
6115 return;
6116 }
6117 }
6118 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006119 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006120 }, pkgFilter);
6121
6122 synchronized (this) {
6123 // Ensure that any processes we had put on hold are now started
6124 // up.
6125 final int NP = mProcessesOnHold.size();
6126 if (NP > 0) {
6127 ArrayList<ProcessRecord> procs =
6128 new ArrayList<ProcessRecord>(mProcessesOnHold);
6129 for (int ip=0; ip<NP; ip++) {
6130 this.startProcessLocked(procs.get(ip), "on-hold", null);
6131 }
6132 }
6133
6134 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6135 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006136 broadcastIntentLocked(null, null,
6137 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
6138 null, null, 0, null, null,
6139 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
6140 false, false, MY_PID, Process.SYSTEM_UID);
6141 }
6142 }
6143 }
6144
6145 final void ensureBootCompleted() {
6146 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006147 boolean enableScreen;
6148 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006149 booting = mBooting;
6150 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006151 enableScreen = !mBooted;
6152 mBooted = true;
6153 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006154
6155 if (booting) {
6156 finishBooting();
6157 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006158
6159 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006160 enableScreenAfterBoot();
6161 }
6162 }
6163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006164 public final void activityPaused(IBinder token, Bundle icicle) {
6165 // Refuse possible leaked file descriptors
6166 if (icicle != null && icicle.hasFileDescriptors()) {
6167 throw new IllegalArgumentException("File descriptors passed in Bundle");
6168 }
6169
6170 final long origId = Binder.clearCallingIdentity();
6171 activityPaused(token, icicle, false);
6172 Binder.restoreCallingIdentity(origId);
6173 }
6174
6175 final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006176 if (DEBUG_PAUSE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006177 TAG, "Activity paused: token=" + token + ", icicle=" + icicle
6178 + ", timeout=" + timeout);
6179
6180 HistoryRecord r = null;
6181
6182 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006183 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006184 if (index >= 0) {
6185 r = (HistoryRecord)mHistory.get(index);
6186 if (!timeout) {
6187 r.icicle = icicle;
6188 r.haveState = true;
6189 }
6190 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
6191 if (mPausingActivity == r) {
6192 r.state = ActivityState.PAUSED;
6193 completePauseLocked();
6194 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -08006195 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006196 System.identityHashCode(r), r.shortComponentName,
6197 mPausingActivity != null
6198 ? mPausingActivity.shortComponentName : "(none)");
6199 }
6200 }
6201 }
6202 }
6203
6204 public final void activityStopped(IBinder token, Bitmap thumbnail,
6205 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006206 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006207 TAG, "Activity stopped: token=" + token);
6208
6209 HistoryRecord r = null;
6210
6211 final long origId = Binder.clearCallingIdentity();
6212
6213 synchronized (this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006214 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 if (index >= 0) {
6216 r = (HistoryRecord)mHistory.get(index);
6217 r.thumbnail = thumbnail;
6218 r.description = description;
6219 r.stopped = true;
6220 r.state = ActivityState.STOPPED;
6221 if (!r.finishing) {
6222 if (r.configDestroy) {
6223 destroyActivityLocked(r, true);
6224 resumeTopActivityLocked(null);
6225 }
6226 }
6227 }
6228 }
6229
6230 if (r != null) {
6231 sendPendingThumbnail(r, null, null, null, false);
6232 }
6233
6234 trimApplications();
6235
6236 Binder.restoreCallingIdentity(origId);
6237 }
6238
6239 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006240 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006241 synchronized (this) {
6242 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
6243
Dianne Hackborn75b03852009-06-12 15:43:26 -07006244 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006245 if (index >= 0) {
6246 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6247 if (r.state == ActivityState.DESTROYING) {
6248 final long origId = Binder.clearCallingIdentity();
6249 removeActivityFromHistoryLocked(r);
6250 Binder.restoreCallingIdentity(origId);
6251 }
6252 }
6253 }
6254 }
6255
6256 public String getCallingPackage(IBinder token) {
6257 synchronized (this) {
6258 HistoryRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07006259 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006260 }
6261 }
6262
6263 public ComponentName getCallingActivity(IBinder token) {
6264 synchronized (this) {
6265 HistoryRecord r = getCallingRecordLocked(token);
6266 return r != null ? r.intent.getComponent() : null;
6267 }
6268 }
6269
6270 private HistoryRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006271 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006272 if (index >= 0) {
6273 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6274 if (r != null) {
6275 return r.resultTo;
6276 }
6277 }
6278 return null;
6279 }
6280
6281 public ComponentName getActivityClassForToken(IBinder token) {
6282 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006283 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006284 if (index >= 0) {
6285 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6286 return r.intent.getComponent();
6287 }
6288 return null;
6289 }
6290 }
6291
6292 public String getPackageForToken(IBinder token) {
6293 synchronized(this) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07006294 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006295 if (index >= 0) {
6296 HistoryRecord r = (HistoryRecord)mHistory.get(index);
6297 return r.packageName;
6298 }
6299 return null;
6300 }
6301 }
6302
6303 public IIntentSender getIntentSender(int type,
6304 String packageName, IBinder token, String resultWho,
6305 int requestCode, Intent intent, String resolvedType, int flags) {
6306 // Refuse possible leaked file descriptors
6307 if (intent != null && intent.hasFileDescriptors() == true) {
6308 throw new IllegalArgumentException("File descriptors passed in Intent");
6309 }
6310
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006311 if (type == INTENT_SENDER_BROADCAST) {
6312 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
6313 throw new IllegalArgumentException(
6314 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
6315 }
6316 }
6317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006318 synchronized(this) {
6319 int callingUid = Binder.getCallingUid();
6320 try {
6321 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
6322 Process.supportsProcesses()) {
6323 int uid = ActivityThread.getPackageManager()
6324 .getPackageUid(packageName);
6325 if (uid != Binder.getCallingUid()) {
6326 String msg = "Permission Denial: getIntentSender() from pid="
6327 + Binder.getCallingPid()
6328 + ", uid=" + Binder.getCallingUid()
6329 + ", (need uid=" + uid + ")"
6330 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006331 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006332 throw new SecurityException(msg);
6333 }
6334 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006335
6336 return getIntentSenderLocked(type, packageName, callingUid,
6337 token, resultWho, requestCode, intent, resolvedType, flags);
6338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006339 } catch (RemoteException e) {
6340 throw new SecurityException(e);
6341 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006342 }
6343 }
6344
6345 IIntentSender getIntentSenderLocked(int type,
6346 String packageName, int callingUid, IBinder token, String resultWho,
6347 int requestCode, Intent intent, String resolvedType, int flags) {
6348 HistoryRecord activity = null;
6349 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6350 int index = indexOfTokenLocked(token);
6351 if (index < 0) {
6352 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006353 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006354 activity = (HistoryRecord)mHistory.get(index);
6355 if (activity.finishing) {
6356 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006357 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006358 }
6359
6360 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
6361 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
6362 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
6363 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
6364 |PendingIntent.FLAG_UPDATE_CURRENT);
6365
6366 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
6367 type, packageName, activity, resultWho,
6368 requestCode, intent, resolvedType, flags);
6369 WeakReference<PendingIntentRecord> ref;
6370 ref = mIntentSenderRecords.get(key);
6371 PendingIntentRecord rec = ref != null ? ref.get() : null;
6372 if (rec != null) {
6373 if (!cancelCurrent) {
6374 if (updateCurrent) {
6375 rec.key.requestIntent.replaceExtras(intent);
6376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006377 return rec;
6378 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006379 rec.canceled = true;
6380 mIntentSenderRecords.remove(key);
6381 }
6382 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006383 return rec;
6384 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006385 rec = new PendingIntentRecord(this, key, callingUid);
6386 mIntentSenderRecords.put(key, rec.ref);
6387 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
6388 if (activity.pendingResults == null) {
6389 activity.pendingResults
6390 = new HashSet<WeakReference<PendingIntentRecord>>();
6391 }
6392 activity.pendingResults.add(rec.ref);
6393 }
6394 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006395 }
6396
6397 public void cancelIntentSender(IIntentSender sender) {
6398 if (!(sender instanceof PendingIntentRecord)) {
6399 return;
6400 }
6401 synchronized(this) {
6402 PendingIntentRecord rec = (PendingIntentRecord)sender;
6403 try {
6404 int uid = ActivityThread.getPackageManager()
6405 .getPackageUid(rec.key.packageName);
6406 if (uid != Binder.getCallingUid()) {
6407 String msg = "Permission Denial: cancelIntentSender() from pid="
6408 + Binder.getCallingPid()
6409 + ", uid=" + Binder.getCallingUid()
6410 + " is not allowed to cancel packges "
6411 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006412 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006413 throw new SecurityException(msg);
6414 }
6415 } catch (RemoteException e) {
6416 throw new SecurityException(e);
6417 }
6418 cancelIntentSenderLocked(rec, true);
6419 }
6420 }
6421
6422 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
6423 rec.canceled = true;
6424 mIntentSenderRecords.remove(rec.key);
6425 if (cleanActivity && rec.key.activity != null) {
6426 rec.key.activity.pendingResults.remove(rec.ref);
6427 }
6428 }
6429
6430 public String getPackageForIntentSender(IIntentSender pendingResult) {
6431 if (!(pendingResult instanceof PendingIntentRecord)) {
6432 return null;
6433 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07006434 try {
6435 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
6436 return res.key.packageName;
6437 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006438 }
6439 return null;
6440 }
6441
6442 public void setProcessLimit(int max) {
6443 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6444 "setProcessLimit()");
6445 mProcessLimit = max;
6446 }
6447
6448 public int getProcessLimit() {
6449 return mProcessLimit;
6450 }
6451
6452 void foregroundTokenDied(ForegroundToken token) {
6453 synchronized (ActivityManagerService.this) {
6454 synchronized (mPidsSelfLocked) {
6455 ForegroundToken cur
6456 = mForegroundProcesses.get(token.pid);
6457 if (cur != token) {
6458 return;
6459 }
6460 mForegroundProcesses.remove(token.pid);
6461 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
6462 if (pr == null) {
6463 return;
6464 }
6465 pr.forcingToForeground = null;
6466 pr.foregroundServices = false;
6467 }
6468 updateOomAdjLocked();
6469 }
6470 }
6471
6472 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
6473 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
6474 "setProcessForeground()");
6475 synchronized(this) {
6476 boolean changed = false;
6477
6478 synchronized (mPidsSelfLocked) {
6479 ProcessRecord pr = mPidsSelfLocked.get(pid);
6480 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006481 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006482 return;
6483 }
6484 ForegroundToken oldToken = mForegroundProcesses.get(pid);
6485 if (oldToken != null) {
6486 oldToken.token.unlinkToDeath(oldToken, 0);
6487 mForegroundProcesses.remove(pid);
6488 pr.forcingToForeground = null;
6489 changed = true;
6490 }
6491 if (isForeground && token != null) {
6492 ForegroundToken newToken = new ForegroundToken() {
6493 public void binderDied() {
6494 foregroundTokenDied(this);
6495 }
6496 };
6497 newToken.pid = pid;
6498 newToken.token = token;
6499 try {
6500 token.linkToDeath(newToken, 0);
6501 mForegroundProcesses.put(pid, newToken);
6502 pr.forcingToForeground = token;
6503 changed = true;
6504 } catch (RemoteException e) {
6505 // If the process died while doing this, we will later
6506 // do the cleanup with the process death link.
6507 }
6508 }
6509 }
6510
6511 if (changed) {
6512 updateOomAdjLocked();
6513 }
6514 }
6515 }
6516
6517 // =========================================================
6518 // PERMISSIONS
6519 // =========================================================
6520
6521 static class PermissionController extends IPermissionController.Stub {
6522 ActivityManagerService mActivityManagerService;
6523 PermissionController(ActivityManagerService activityManagerService) {
6524 mActivityManagerService = activityManagerService;
6525 }
6526
6527 public boolean checkPermission(String permission, int pid, int uid) {
6528 return mActivityManagerService.checkPermission(permission, pid,
6529 uid) == PackageManager.PERMISSION_GRANTED;
6530 }
6531 }
6532
6533 /**
6534 * This can be called with or without the global lock held.
6535 */
6536 int checkComponentPermission(String permission, int pid, int uid,
6537 int reqUid) {
6538 // We might be performing an operation on behalf of an indirect binder
6539 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
6540 // client identity accordingly before proceeding.
6541 Identity tlsIdentity = sCallerIdentity.get();
6542 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006543 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
6545 uid = tlsIdentity.uid;
6546 pid = tlsIdentity.pid;
6547 }
6548
6549 // Root, system server and our own process get to do everything.
6550 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
6551 !Process.supportsProcesses()) {
6552 return PackageManager.PERMISSION_GRANTED;
6553 }
6554 // If the target requires a specific UID, always fail for others.
6555 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006556 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006557 return PackageManager.PERMISSION_DENIED;
6558 }
6559 if (permission == null) {
6560 return PackageManager.PERMISSION_GRANTED;
6561 }
6562 try {
6563 return ActivityThread.getPackageManager()
6564 .checkUidPermission(permission, uid);
6565 } catch (RemoteException e) {
6566 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006567 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006568 }
6569 return PackageManager.PERMISSION_DENIED;
6570 }
6571
6572 /**
6573 * As the only public entry point for permissions checking, this method
6574 * can enforce the semantic that requesting a check on a null global
6575 * permission is automatically denied. (Internally a null permission
6576 * string is used when calling {@link #checkComponentPermission} in cases
6577 * when only uid-based security is needed.)
6578 *
6579 * This can be called with or without the global lock held.
6580 */
6581 public int checkPermission(String permission, int pid, int uid) {
6582 if (permission == null) {
6583 return PackageManager.PERMISSION_DENIED;
6584 }
6585 return checkComponentPermission(permission, pid, uid, -1);
6586 }
6587
6588 /**
6589 * Binder IPC calls go through the public entry point.
6590 * This can be called with or without the global lock held.
6591 */
6592 int checkCallingPermission(String permission) {
6593 return checkPermission(permission,
6594 Binder.getCallingPid(),
6595 Binder.getCallingUid());
6596 }
6597
6598 /**
6599 * This can be called with or without the global lock held.
6600 */
6601 void enforceCallingPermission(String permission, String func) {
6602 if (checkCallingPermission(permission)
6603 == PackageManager.PERMISSION_GRANTED) {
6604 return;
6605 }
6606
6607 String msg = "Permission Denial: " + func + " from pid="
6608 + Binder.getCallingPid()
6609 + ", uid=" + Binder.getCallingUid()
6610 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006611 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006612 throw new SecurityException(msg);
6613 }
6614
6615 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
6616 ProviderInfo pi, int uid, int modeFlags) {
6617 try {
6618 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6619 if ((pi.readPermission != null) &&
6620 (pm.checkUidPermission(pi.readPermission, uid)
6621 != PackageManager.PERMISSION_GRANTED)) {
6622 return false;
6623 }
6624 }
6625 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6626 if ((pi.writePermission != null) &&
6627 (pm.checkUidPermission(pi.writePermission, uid)
6628 != PackageManager.PERMISSION_GRANTED)) {
6629 return false;
6630 }
6631 }
6632 return true;
6633 } catch (RemoteException e) {
6634 return false;
6635 }
6636 }
6637
6638 private final boolean checkUriPermissionLocked(Uri uri, int uid,
6639 int modeFlags) {
6640 // Root gets to do everything.
6641 if (uid == 0 || !Process.supportsProcesses()) {
6642 return true;
6643 }
6644 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
6645 if (perms == null) return false;
6646 UriPermission perm = perms.get(uri);
6647 if (perm == null) return false;
6648 return (modeFlags&perm.modeFlags) == modeFlags;
6649 }
6650
6651 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
6652 // Another redirected-binder-call permissions check as in
6653 // {@link checkComponentPermission}.
6654 Identity tlsIdentity = sCallerIdentity.get();
6655 if (tlsIdentity != null) {
6656 uid = tlsIdentity.uid;
6657 pid = tlsIdentity.pid;
6658 }
6659
6660 // Our own process gets to do everything.
6661 if (pid == MY_PID) {
6662 return PackageManager.PERMISSION_GRANTED;
6663 }
6664 synchronized(this) {
6665 return checkUriPermissionLocked(uri, uid, modeFlags)
6666 ? PackageManager.PERMISSION_GRANTED
6667 : PackageManager.PERMISSION_DENIED;
6668 }
6669 }
6670
6671 private void grantUriPermissionLocked(int callingUid,
6672 String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
6673 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6674 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6675 if (modeFlags == 0) {
6676 return;
6677 }
6678
Joe Onorato8a9b2202010-02-26 18:56:32 -08006679 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006680 "Requested grant " + targetPkg + " permission to " + uri);
6681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006682 final IPackageManager pm = ActivityThread.getPackageManager();
6683
6684 // If this is not a content: uri, we can't do anything with it.
6685 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
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 for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006688 return;
6689 }
6690
6691 String name = uri.getAuthority();
6692 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006693 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006694 if (cpr != null) {
6695 pi = cpr.info;
6696 } else {
6697 try {
6698 pi = pm.resolveContentProvider(name,
6699 PackageManager.GET_URI_PERMISSION_PATTERNS);
6700 } catch (RemoteException ex) {
6701 }
6702 }
6703 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006704 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 return;
6706 }
6707
6708 int targetUid;
6709 try {
6710 targetUid = pm.getPackageUid(targetPkg);
6711 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006712 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006713 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006714 return;
6715 }
6716 } catch (RemoteException ex) {
6717 return;
6718 }
6719
6720 // First... does the target actually need this permission?
6721 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
6722 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006723 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006724 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006725 return;
6726 }
6727
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006728 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006729 if (!pi.grantUriPermissions) {
6730 throw new SecurityException("Provider " + pi.packageName
6731 + "/" + pi.name
6732 + " does not allow granting of Uri permissions (uri "
6733 + uri + ")");
6734 }
6735 if (pi.uriPermissionPatterns != null) {
6736 final int N = pi.uriPermissionPatterns.length;
6737 boolean allowed = false;
6738 for (int i=0; i<N; i++) {
6739 if (pi.uriPermissionPatterns[i] != null
6740 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
6741 allowed = true;
6742 break;
6743 }
6744 }
6745 if (!allowed) {
6746 throw new SecurityException("Provider " + pi.packageName
6747 + "/" + pi.name
6748 + " does not allow granting of permission to path of Uri "
6749 + uri);
6750 }
6751 }
6752
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006753 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006754 // this uri?
6755 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6756 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6757 throw new SecurityException("Uid " + callingUid
6758 + " does not have permission to uri " + uri);
6759 }
6760 }
6761
6762 // Okay! So here we are: the caller has the assumed permission
6763 // to the uri, and the target doesn't. Let's now give this to
6764 // the target.
6765
Joe Onorato8a9b2202010-02-26 18:56:32 -08006766 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006767 "Granting " + targetPkg + " permission to " + uri);
6768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769 HashMap<Uri, UriPermission> targetUris
6770 = mGrantedUriPermissions.get(targetUid);
6771 if (targetUris == null) {
6772 targetUris = new HashMap<Uri, UriPermission>();
6773 mGrantedUriPermissions.put(targetUid, targetUris);
6774 }
6775
6776 UriPermission perm = targetUris.get(uri);
6777 if (perm == null) {
6778 perm = new UriPermission(targetUid, uri);
6779 targetUris.put(uri, perm);
6780
6781 }
6782 perm.modeFlags |= modeFlags;
6783 if (activity == null) {
6784 perm.globalModeFlags |= modeFlags;
6785 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
6786 perm.readActivities.add(activity);
6787 if (activity.readUriPermissions == null) {
6788 activity.readUriPermissions = new HashSet<UriPermission>();
6789 }
6790 activity.readUriPermissions.add(perm);
6791 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
6792 perm.writeActivities.add(activity);
6793 if (activity.writeUriPermissions == null) {
6794 activity.writeUriPermissions = new HashSet<UriPermission>();
6795 }
6796 activity.writeUriPermissions.add(perm);
6797 }
6798 }
6799
6800 private void grantUriPermissionFromIntentLocked(int callingUid,
6801 String targetPkg, Intent intent, HistoryRecord activity) {
6802 if (intent == null) {
6803 return;
6804 }
6805 Uri data = intent.getData();
6806 if (data == null) {
6807 return;
6808 }
6809 grantUriPermissionLocked(callingUid, targetPkg, data,
6810 intent.getFlags(), activity);
6811 }
6812
6813 public void grantUriPermission(IApplicationThread caller, String targetPkg,
6814 Uri uri, int modeFlags) {
6815 synchronized(this) {
6816 final ProcessRecord r = getRecordForAppLocked(caller);
6817 if (r == null) {
6818 throw new SecurityException("Unable to find app for caller "
6819 + caller
6820 + " when granting permission to uri " + uri);
6821 }
6822 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006823 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006824 return;
6825 }
6826 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006827 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006828 return;
6829 }
6830
6831 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
6832 null);
6833 }
6834 }
6835
6836 private void removeUriPermissionIfNeededLocked(UriPermission perm) {
6837 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
6838 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
6839 HashMap<Uri, UriPermission> perms
6840 = mGrantedUriPermissions.get(perm.uid);
6841 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006842 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006843 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006844 perms.remove(perm.uri);
6845 if (perms.size() == 0) {
6846 mGrantedUriPermissions.remove(perm.uid);
6847 }
6848 }
6849 }
6850 }
6851
6852 private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
6853 if (activity.readUriPermissions != null) {
6854 for (UriPermission perm : activity.readUriPermissions) {
6855 perm.readActivities.remove(activity);
6856 if (perm.readActivities.size() == 0 && (perm.globalModeFlags
6857 &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
6858 perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
6859 removeUriPermissionIfNeededLocked(perm);
6860 }
6861 }
6862 }
6863 if (activity.writeUriPermissions != null) {
6864 for (UriPermission perm : activity.writeUriPermissions) {
6865 perm.writeActivities.remove(activity);
6866 if (perm.writeActivities.size() == 0 && (perm.globalModeFlags
6867 &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
6868 perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
6869 removeUriPermissionIfNeededLocked(perm);
6870 }
6871 }
6872 }
6873 }
6874
6875 private void revokeUriPermissionLocked(int callingUid, Uri uri,
6876 int modeFlags) {
6877 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6878 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6879 if (modeFlags == 0) {
6880 return;
6881 }
6882
Joe Onorato8a9b2202010-02-26 18:56:32 -08006883 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006884 "Revoking all granted permissions to " + uri);
6885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006886 final IPackageManager pm = ActivityThread.getPackageManager();
6887
6888 final String authority = uri.getAuthority();
6889 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006890 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891 if (cpr != null) {
6892 pi = cpr.info;
6893 } else {
6894 try {
6895 pi = pm.resolveContentProvider(authority,
6896 PackageManager.GET_URI_PERMISSION_PATTERNS);
6897 } catch (RemoteException ex) {
6898 }
6899 }
6900 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006901 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006902 return;
6903 }
6904
6905 // Does the caller have this permission on the URI?
6906 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
6907 // Right now, if you are not the original owner of the permission,
6908 // you are not allowed to revoke it.
6909 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
6910 throw new SecurityException("Uid " + callingUid
6911 + " does not have permission to uri " + uri);
6912 //}
6913 }
6914
6915 // Go through all of the permissions and remove any that match.
6916 final List<String> SEGMENTS = uri.getPathSegments();
6917 if (SEGMENTS != null) {
6918 final int NS = SEGMENTS.size();
6919 int N = mGrantedUriPermissions.size();
6920 for (int i=0; i<N; i++) {
6921 HashMap<Uri, UriPermission> perms
6922 = mGrantedUriPermissions.valueAt(i);
6923 Iterator<UriPermission> it = perms.values().iterator();
6924 toploop:
6925 while (it.hasNext()) {
6926 UriPermission perm = it.next();
6927 Uri targetUri = perm.uri;
6928 if (!authority.equals(targetUri.getAuthority())) {
6929 continue;
6930 }
6931 List<String> targetSegments = targetUri.getPathSegments();
6932 if (targetSegments == null) {
6933 continue;
6934 }
6935 if (targetSegments.size() < NS) {
6936 continue;
6937 }
6938 for (int j=0; j<NS; j++) {
6939 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
6940 continue toploop;
6941 }
6942 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006943 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006944 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006945 perm.clearModes(modeFlags);
6946 if (perm.modeFlags == 0) {
6947 it.remove();
6948 }
6949 }
6950 if (perms.size() == 0) {
6951 mGrantedUriPermissions.remove(
6952 mGrantedUriPermissions.keyAt(i));
6953 N--;
6954 i--;
6955 }
6956 }
6957 }
6958 }
6959
6960 public void revokeUriPermission(IApplicationThread caller, Uri uri,
6961 int modeFlags) {
6962 synchronized(this) {
6963 final ProcessRecord r = getRecordForAppLocked(caller);
6964 if (r == null) {
6965 throw new SecurityException("Unable to find app for caller "
6966 + caller
6967 + " when revoking permission to uri " + uri);
6968 }
6969 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006970 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006971 return;
6972 }
6973
6974 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
6975 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
6976 if (modeFlags == 0) {
6977 return;
6978 }
6979
6980 final IPackageManager pm = ActivityThread.getPackageManager();
6981
6982 final String authority = uri.getAuthority();
6983 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07006984 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006985 if (cpr != null) {
6986 pi = cpr.info;
6987 } else {
6988 try {
6989 pi = pm.resolveContentProvider(authority,
6990 PackageManager.GET_URI_PERMISSION_PATTERNS);
6991 } catch (RemoteException ex) {
6992 }
6993 }
6994 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006995 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006996 return;
6997 }
6998
6999 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
7000 }
7001 }
7002
7003 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
7004 synchronized (this) {
7005 ProcessRecord app =
7006 who != null ? getRecordForAppLocked(who) : null;
7007 if (app == null) return;
7008
7009 Message msg = Message.obtain();
7010 msg.what = WAIT_FOR_DEBUGGER_MSG;
7011 msg.obj = app;
7012 msg.arg1 = waiting ? 1 : 0;
7013 mHandler.sendMessage(msg);
7014 }
7015 }
7016
7017 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
7018 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08007019 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007020 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08007021 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007022 }
7023
7024 // =========================================================
7025 // TASK MANAGEMENT
7026 // =========================================================
7027
7028 public List getTasks(int maxNum, int flags,
7029 IThumbnailReceiver receiver) {
7030 ArrayList list = new ArrayList();
7031
7032 PendingThumbnailsRecord pending = null;
7033 IApplicationThread topThumbnail = null;
7034 HistoryRecord topRecord = null;
7035
7036 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007037 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007038 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
7039 + ", receiver=" + receiver);
7040
7041 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
7042 != PackageManager.PERMISSION_GRANTED) {
7043 if (receiver != null) {
7044 // If the caller wants to wait for pending thumbnails,
7045 // it ain't gonna get them.
7046 try {
7047 receiver.finished();
7048 } catch (RemoteException ex) {
7049 }
7050 }
7051 String msg = "Permission Denial: getTasks() from pid="
7052 + Binder.getCallingPid()
7053 + ", uid=" + Binder.getCallingUid()
7054 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007055 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007056 throw new SecurityException(msg);
7057 }
7058
7059 int pos = mHistory.size()-1;
7060 HistoryRecord next =
7061 pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
7062 HistoryRecord top = null;
7063 CharSequence topDescription = null;
7064 TaskRecord curTask = null;
7065 int numActivities = 0;
7066 int numRunning = 0;
7067 while (pos >= 0 && maxNum > 0) {
7068 final HistoryRecord r = next;
7069 pos--;
7070 next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
7071
7072 // Initialize state for next task if needed.
7073 if (top == null ||
7074 (top.state == ActivityState.INITIALIZING
7075 && top.task == r.task)) {
7076 top = r;
7077 topDescription = r.description;
7078 curTask = r.task;
7079 numActivities = numRunning = 0;
7080 }
7081
7082 // Add 'r' into the current task.
7083 numActivities++;
7084 if (r.app != null && r.app.thread != null) {
7085 numRunning++;
7086 }
7087 if (topDescription == null) {
7088 topDescription = r.description;
7089 }
7090
Joe Onorato8a9b2202010-02-26 18:56:32 -08007091 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 TAG, r.intent.getComponent().flattenToShortString()
7093 + ": task=" + r.task);
7094
7095 // If the next one is a different task, generate a new
7096 // TaskInfo entry for what we have.
7097 if (next == null || next.task != curTask) {
7098 ActivityManager.RunningTaskInfo ci
7099 = new ActivityManager.RunningTaskInfo();
7100 ci.id = curTask.taskId;
7101 ci.baseActivity = r.intent.getComponent();
7102 ci.topActivity = top.intent.getComponent();
7103 ci.thumbnail = top.thumbnail;
7104 ci.description = topDescription;
7105 ci.numActivities = numActivities;
7106 ci.numRunning = numRunning;
7107 //System.out.println(
7108 // "#" + maxNum + ": " + " descr=" + ci.description);
7109 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007110 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007111 TAG, "State=" + top.state + "Idle=" + top.idle
7112 + " app=" + top.app
7113 + " thr=" + (top.app != null ? top.app.thread : null));
7114 if (top.state == ActivityState.RESUMED
7115 || top.state == ActivityState.PAUSING) {
7116 if (top.idle && top.app != null
7117 && top.app.thread != null) {
7118 topRecord = top;
7119 topThumbnail = top.app.thread;
7120 } else {
7121 top.thumbnailNeeded = true;
7122 }
7123 }
7124 if (pending == null) {
7125 pending = new PendingThumbnailsRecord(receiver);
7126 }
7127 pending.pendingRecords.add(top);
7128 }
7129 list.add(ci);
7130 maxNum--;
7131 top = null;
7132 }
7133 }
7134
7135 if (pending != null) {
7136 mPendingThumbnails.add(pending);
7137 }
7138 }
7139
Joe Onorato8a9b2202010-02-26 18:56:32 -08007140 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007141
7142 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007143 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007144 try {
7145 topThumbnail.requestThumbnail(topRecord);
7146 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007147 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007148 sendPendingThumbnail(null, topRecord, null, null, true);
7149 }
7150 }
7151
7152 if (pending == null && receiver != null) {
7153 // In this case all thumbnails were available and the client
7154 // is being asked to be told when the remaining ones come in...
7155 // which is unusually, since the top-most currently running
7156 // activity should never have a canned thumbnail! Oh well.
7157 try {
7158 receiver.finished();
7159 } catch (RemoteException ex) {
7160 }
7161 }
7162
7163 return list;
7164 }
7165
7166 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
7167 int flags) {
7168 synchronized (this) {
7169 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
7170 "getRecentTasks()");
7171
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007172 IPackageManager pm = ActivityThread.getPackageManager();
7173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007174 final int N = mRecentTasks.size();
7175 ArrayList<ActivityManager.RecentTaskInfo> res
7176 = new ArrayList<ActivityManager.RecentTaskInfo>(
7177 maxNum < N ? maxNum : N);
7178 for (int i=0; i<N && maxNum > 0; i++) {
7179 TaskRecord tr = mRecentTasks.get(i);
7180 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
7181 || (tr.intent == null)
7182 || ((tr.intent.getFlags()
7183 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
7184 ActivityManager.RecentTaskInfo rti
7185 = new ActivityManager.RecentTaskInfo();
7186 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
7187 rti.baseIntent = new Intent(
7188 tr.intent != null ? tr.intent : tr.affinityIntent);
7189 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07007190
7191 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
7192 // Check whether this activity is currently available.
7193 try {
7194 if (rti.origActivity != null) {
7195 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
7196 continue;
7197 }
7198 } else if (rti.baseIntent != null) {
7199 if (pm.queryIntentActivities(rti.baseIntent,
7200 null, 0) == null) {
7201 continue;
7202 }
7203 }
7204 } catch (RemoteException e) {
7205 // Will never happen.
7206 }
7207 }
7208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007209 res.add(rti);
7210 maxNum--;
7211 }
7212 }
7213 return res;
7214 }
7215 }
7216
7217 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
7218 int j;
7219 TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
7220 TaskRecord jt = startTask;
7221
7222 // First look backwards
7223 for (j=startIndex-1; j>=0; j--) {
7224 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7225 if (r.task != jt) {
7226 jt = r.task;
7227 if (affinity.equals(jt.affinity)) {
7228 return j;
7229 }
7230 }
7231 }
7232
7233 // Now look forwards
7234 final int N = mHistory.size();
7235 jt = startTask;
7236 for (j=startIndex+1; j<N; j++) {
7237 HistoryRecord r = (HistoryRecord)mHistory.get(j);
7238 if (r.task != jt) {
7239 if (affinity.equals(jt.affinity)) {
7240 return j;
7241 }
7242 jt = r.task;
7243 }
7244 }
7245
7246 // Might it be at the top?
7247 if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
7248 return N-1;
7249 }
7250
7251 return -1;
7252 }
7253
7254 /**
7255 * Perform a reset of the given task, if needed as part of launching it.
7256 * Returns the new HistoryRecord at the top of the task.
7257 */
7258 private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
7259 HistoryRecord newActivity) {
7260 boolean forceReset = (newActivity.info.flags
7261 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
7262 if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
7263 if ((newActivity.info.flags
7264 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
7265 forceReset = true;
7266 }
7267 }
7268
7269 final TaskRecord task = taskTop.task;
7270
7271 // We are going to move through the history list so that we can look
7272 // at each activity 'target' with 'below' either the interesting
7273 // activity immediately below it in the stack or null.
7274 HistoryRecord target = null;
7275 int targetI = 0;
7276 int taskTopI = -1;
7277 int replyChainEnd = -1;
7278 int lastReparentPos = -1;
7279 for (int i=mHistory.size()-1; i>=-1; i--) {
7280 HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
7281
7282 if (below != null && below.finishing) {
7283 continue;
7284 }
7285 if (target == null) {
7286 target = below;
7287 targetI = i;
7288 // If we were in the middle of a reply chain before this
7289 // task, it doesn't appear like the root of the chain wants
7290 // anything interesting, so drop it.
7291 replyChainEnd = -1;
7292 continue;
7293 }
7294
7295 final int flags = target.info.flags;
7296
7297 final boolean finishOnTaskLaunch =
7298 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
7299 final boolean allowTaskReparenting =
7300 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
7301
7302 if (target.task == task) {
7303 // We are inside of the task being reset... we'll either
7304 // finish this activity, push it out for another task,
7305 // or leave it as-is. We only do this
7306 // for activities that are not the root of the task (since
7307 // if we finish the root, we may no longer have the task!).
7308 if (taskTopI < 0) {
7309 taskTopI = targetI;
7310 }
7311 if (below != null && below.task == task) {
7312 final boolean clearWhenTaskReset =
7313 (target.intent.getFlags()
7314 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
Ed Heyl73798232009-03-24 21:32:21 -07007315 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 // If this activity is sending a reply to a previous
7317 // activity, we can't do anything with it now until
7318 // we reach the start of the reply chain.
7319 // XXX note that we are assuming the result is always
7320 // to the previous activity, which is almost always
7321 // the case but we really shouldn't count on.
7322 if (replyChainEnd < 0) {
7323 replyChainEnd = targetI;
7324 }
Ed Heyl73798232009-03-24 21:32:21 -07007325 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 && target.taskAffinity != null
7327 && !target.taskAffinity.equals(task.affinity)) {
7328 // If this activity has an affinity for another
7329 // task, then we need to move it out of here. We will
7330 // move it as far out of the way as possible, to the
7331 // bottom of the activity stack. This also keeps it
7332 // correctly ordered with any activities we previously
7333 // moved.
7334 HistoryRecord p = (HistoryRecord)mHistory.get(0);
7335 if (target.taskAffinity != null
7336 && target.taskAffinity.equals(p.task.affinity)) {
7337 // If the activity currently at the bottom has the
7338 // same task affinity as the one we are moving,
7339 // then merge it into the same task.
7340 target.task = p.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007341 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342 + " out to bottom task " + p.task);
7343 } else {
7344 mCurTask++;
7345 if (mCurTask <= 0) {
7346 mCurTask = 1;
7347 }
7348 target.task = new TaskRecord(mCurTask, target.info, null,
7349 (target.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
7350 target.task.affinityIntent = target.intent;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007351 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352 + " out to new task " + target.task);
7353 }
7354 mWindowManager.setAppGroupId(target, task.taskId);
7355 if (replyChainEnd < 0) {
7356 replyChainEnd = targetI;
7357 }
7358 int dstPos = 0;
7359 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7360 p = (HistoryRecord)mHistory.get(srcPos);
7361 if (p.finishing) {
7362 continue;
7363 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007364 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365 + " out to target's task " + target.task);
7366 task.numActivities--;
7367 p.task = target.task;
7368 target.task.numActivities++;
7369 mHistory.remove(srcPos);
7370 mHistory.add(dstPos, p);
7371 mWindowManager.moveAppToken(dstPos, p);
7372 mWindowManager.setAppGroupId(p, p.task.taskId);
7373 dstPos++;
7374 if (VALIDATE_TOKENS) {
7375 mWindowManager.validateAppTokens(mHistory);
7376 }
7377 i++;
7378 }
7379 if (taskTop == p) {
7380 taskTop = below;
7381 }
7382 if (taskTopI == replyChainEnd) {
7383 taskTopI = -1;
7384 }
7385 replyChainEnd = -1;
Josh Bartel7f208742010-02-25 11:01:44 -06007386 addRecentTaskLocked(target.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007387 } else if (forceReset || finishOnTaskLaunch
7388 || clearWhenTaskReset) {
7389 // If the activity should just be removed -- either
7390 // because it asks for it, or the task should be
7391 // cleared -- then finish it and anything that is
7392 // part of its reply chain.
7393 if (clearWhenTaskReset) {
7394 // In this case, we want to finish this activity
7395 // and everything above it, so be sneaky and pretend
7396 // like these are all in the reply chain.
7397 replyChainEnd = targetI+1;
7398 while (replyChainEnd < mHistory.size() &&
7399 ((HistoryRecord)mHistory.get(
7400 replyChainEnd)).task == task) {
7401 replyChainEnd++;
7402 }
7403 replyChainEnd--;
7404 } else if (replyChainEnd < 0) {
7405 replyChainEnd = targetI;
7406 }
7407 HistoryRecord p = null;
7408 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7409 p = (HistoryRecord)mHistory.get(srcPos);
7410 if (p.finishing) {
7411 continue;
7412 }
7413 if (finishActivityLocked(p, srcPos,
7414 Activity.RESULT_CANCELED, null, "reset")) {
7415 replyChainEnd--;
7416 srcPos--;
7417 }
7418 }
7419 if (taskTop == p) {
7420 taskTop = below;
7421 }
7422 if (taskTopI == replyChainEnd) {
7423 taskTopI = -1;
7424 }
7425 replyChainEnd = -1;
7426 } else {
7427 // If we were in the middle of a chain, well the
7428 // activity that started it all doesn't want anything
7429 // special, so leave it all as-is.
7430 replyChainEnd = -1;
7431 }
7432 } else {
7433 // Reached the bottom of the task -- any reply chain
7434 // should be left as-is.
7435 replyChainEnd = -1;
7436 }
7437
7438 } else if (target.resultTo != null) {
7439 // If this activity is sending a reply to a previous
7440 // activity, we can't do anything with it now until
7441 // we reach the start of the reply chain.
7442 // XXX note that we are assuming the result is always
7443 // to the previous activity, which is almost always
7444 // the case but we really shouldn't count on.
7445 if (replyChainEnd < 0) {
7446 replyChainEnd = targetI;
7447 }
7448
7449 } else if (taskTopI >= 0 && allowTaskReparenting
7450 && task.affinity != null
7451 && task.affinity.equals(target.taskAffinity)) {
7452 // We are inside of another task... if this activity has
7453 // an affinity for our task, then either remove it if we are
7454 // clearing or move it over to our task. Note that
7455 // we currently punt on the case where we are resetting a
7456 // task that is not at the top but who has activities above
7457 // with an affinity to it... this is really not a normal
7458 // case, and we will need to later pull that task to the front
7459 // and usually at that point we will do the reset and pick
7460 // up those remaining activities. (This only happens if
7461 // someone starts an activity in a new task from an activity
7462 // in a task that is not currently on top.)
7463 if (forceReset || finishOnTaskLaunch) {
7464 if (replyChainEnd < 0) {
7465 replyChainEnd = targetI;
7466 }
7467 HistoryRecord p = null;
7468 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
7469 p = (HistoryRecord)mHistory.get(srcPos);
7470 if (p.finishing) {
7471 continue;
7472 }
7473 if (finishActivityLocked(p, srcPos,
7474 Activity.RESULT_CANCELED, null, "reset")) {
7475 taskTopI--;
7476 lastReparentPos--;
7477 replyChainEnd--;
7478 srcPos--;
7479 }
7480 }
7481 replyChainEnd = -1;
7482 } else {
7483 if (replyChainEnd < 0) {
7484 replyChainEnd = targetI;
7485 }
7486 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
7487 HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
7488 if (p.finishing) {
7489 continue;
7490 }
7491 if (lastReparentPos < 0) {
7492 lastReparentPos = taskTopI;
7493 taskTop = p;
7494 } else {
7495 lastReparentPos--;
7496 }
7497 mHistory.remove(srcPos);
7498 p.task.numActivities--;
7499 p.task = task;
7500 mHistory.add(lastReparentPos, p);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007501 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007502 + " in to resetting task " + task);
7503 task.numActivities++;
7504 mWindowManager.moveAppToken(lastReparentPos, p);
7505 mWindowManager.setAppGroupId(p, p.task.taskId);
7506 if (VALIDATE_TOKENS) {
7507 mWindowManager.validateAppTokens(mHistory);
7508 }
7509 }
7510 replyChainEnd = -1;
7511
7512 // Now we've moved it in to place... but what if this is
7513 // a singleTop activity and we have put it on top of another
7514 // instance of the same activity? Then we drop the instance
7515 // below so it remains singleTop.
7516 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
7517 for (int j=lastReparentPos-1; j>=0; j--) {
7518 HistoryRecord p = (HistoryRecord)mHistory.get(j);
7519 if (p.finishing) {
7520 continue;
7521 }
7522 if (p.intent.getComponent().equals(target.intent.getComponent())) {
7523 if (finishActivityLocked(p, j,
7524 Activity.RESULT_CANCELED, null, "replace")) {
7525 taskTopI--;
7526 lastReparentPos--;
7527 }
7528 }
7529 }
7530 }
7531 }
7532 }
7533
7534 target = below;
7535 targetI = i;
7536 }
7537
7538 return taskTop;
7539 }
7540
7541 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007542 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007543 */
7544 public void moveTaskToFront(int task) {
7545 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7546 "moveTaskToFront()");
7547
7548 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007549 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7550 Binder.getCallingUid(), "Task to front")) {
7551 return;
7552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007553 final long origId = Binder.clearCallingIdentity();
7554 try {
7555 int N = mRecentTasks.size();
7556 for (int i=0; i<N; i++) {
7557 TaskRecord tr = mRecentTasks.get(i);
7558 if (tr.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007559 moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007560 return;
7561 }
7562 }
7563 for (int i=mHistory.size()-1; i>=0; i--) {
7564 HistoryRecord hr = (HistoryRecord)mHistory.get(i);
7565 if (hr.task.taskId == task) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007566 moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007567 return;
7568 }
7569 }
7570 } finally {
7571 Binder.restoreCallingIdentity(origId);
7572 }
7573 }
7574 }
7575
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007576 private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007577 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007578
7579 final int task = tr.taskId;
7580 int top = mHistory.size()-1;
7581
7582 if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
7583 // nothing to do!
7584 return;
7585 }
7586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007587 ArrayList moved = new ArrayList();
7588
7589 // Applying the affinities may have removed entries from the history,
7590 // so get the size again.
7591 top = mHistory.size()-1;
7592 int pos = top;
7593
7594 // Shift all activities with this task up to the top
7595 // of the stack, keeping them in the same internal order.
7596 while (pos >= 0) {
7597 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007598 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7600 boolean first = true;
7601 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007602 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 mHistory.remove(pos);
7604 mHistory.add(top, r);
7605 moved.add(0, r);
7606 top--;
7607 if (first) {
Josh Bartel7f208742010-02-25 11:01:44 -06007608 addRecentTaskLocked(r.task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007609 first = false;
7610 }
7611 }
7612 pos--;
7613 }
7614
Joe Onorato8a9b2202010-02-26 18:56:32 -08007615 if (DEBUG_TRANSITION) Slog.v(TAG,
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007616 "Prepare to front transition: task=" + tr);
7617 if (reason != null &&
7618 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7619 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7620 HistoryRecord r = topRunningActivityLocked(null);
7621 if (r != null) {
7622 mNoAnimActivities.add(r);
7623 }
7624 } else {
7625 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT);
7626 }
7627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007628 mWindowManager.moveAppTokensToTop(moved);
7629 if (VALIDATE_TOKENS) {
7630 mWindowManager.validateAppTokens(mHistory);
7631 }
7632
Josh Bartel7f208742010-02-25 11:01:44 -06007633 finishTaskMoveLocked(task);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007634 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007635 }
7636
Josh Bartel7f208742010-02-25 11:01:44 -06007637 private final void finishTaskMoveLocked(int task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007638 resumeTopActivityLocked(null);
7639 }
7640
7641 public void moveTaskToBack(int task) {
7642 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7643 "moveTaskToBack()");
7644
7645 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007646 if (mResumedActivity != null && mResumedActivity.task.taskId == task) {
7647 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7648 Binder.getCallingUid(), "Task to back")) {
7649 return;
7650 }
7651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007653 moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007654 Binder.restoreCallingIdentity(origId);
7655 }
7656 }
7657
7658 /**
7659 * Moves an activity, and all of the other activities within the same task, to the bottom
7660 * of the history stack. The activity's order within the task is unchanged.
7661 *
7662 * @param token A reference to the activity we wish to move
7663 * @param nonRoot If false then this only works if the activity is the root
7664 * of a task; if true it will work for any activity in a task.
7665 * @return Returns true if the move completed, false if not.
7666 */
7667 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
7668 synchronized(this) {
7669 final long origId = Binder.clearCallingIdentity();
7670 int taskId = getTaskForActivityLocked(token, !nonRoot);
7671 if (taskId >= 0) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007672 return moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 }
7674 Binder.restoreCallingIdentity(origId);
7675 }
7676 return false;
7677 }
7678
7679 /**
7680 * Worker method for rearranging history stack. Implements the function of moving all
7681 * activities for a specific task (gathering them if disjoint) into a single group at the
7682 * bottom of the stack.
7683 *
7684 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
7685 * to premeptively cancel the move.
7686 *
7687 * @param task The taskId to collect and move to the bottom.
7688 * @return Returns true if the move completed, false if not.
7689 */
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007690 private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007691 Slog.i(TAG, "moveTaskToBack: " + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692
7693 // If we have a watcher, preflight the move before committing to it. First check
7694 // for *other* available tasks, but if none are available, then try again allowing the
7695 // current task to be selected.
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007696 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 HistoryRecord next = topRunningActivityLocked(null, task);
7698 if (next == null) {
7699 next = topRunningActivityLocked(null, 0);
7700 }
7701 if (next != null) {
7702 // ask watcher if this is allowed
7703 boolean moveOK = true;
7704 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007705 moveOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007707 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007708 }
7709 if (!moveOK) {
7710 return false;
7711 }
7712 }
7713 }
7714
7715 ArrayList moved = new ArrayList();
7716
Joe Onorato8a9b2202010-02-26 18:56:32 -08007717 if (DEBUG_TRANSITION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718 "Prepare to back transition: task=" + task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007719
7720 final int N = mHistory.size();
7721 int bottom = 0;
7722 int pos = 0;
7723
7724 // Shift all activities with this task down to the bottom
7725 // of the stack, keeping them in the same internal order.
7726 while (pos < N) {
7727 HistoryRecord r = (HistoryRecord)mHistory.get(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007728 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729 TAG, "At " + pos + " ckp " + r.task + ": " + r);
7730 if (r.task.taskId == task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007731 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007732 mHistory.remove(pos);
7733 mHistory.add(bottom, r);
7734 moved.add(r);
7735 bottom++;
7736 }
7737 pos++;
7738 }
7739
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007740 if (reason != null &&
7741 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
7742 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
7743 HistoryRecord r = topRunningActivityLocked(null);
7744 if (r != null) {
7745 mNoAnimActivities.add(r);
7746 }
7747 } else {
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08007748 mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_TASK_TO_BACK);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 mWindowManager.moveAppTokensToBottom(moved);
7751 if (VALIDATE_TOKENS) {
7752 mWindowManager.validateAppTokens(mHistory);
7753 }
7754
Josh Bartel7f208742010-02-25 11:01:44 -06007755 finishTaskMoveLocked(task);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007756 return true;
7757 }
7758
7759 public void moveTaskBackwards(int task) {
7760 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
7761 "moveTaskBackwards()");
7762
7763 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07007764 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
7765 Binder.getCallingUid(), "Task backwards")) {
7766 return;
7767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007768 final long origId = Binder.clearCallingIdentity();
7769 moveTaskBackwardsLocked(task);
7770 Binder.restoreCallingIdentity(origId);
7771 }
7772 }
7773
7774 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007775 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007776 }
7777
7778 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
7779 synchronized(this) {
7780 return getTaskForActivityLocked(token, onlyRoot);
7781 }
7782 }
7783
7784 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
7785 final int N = mHistory.size();
7786 TaskRecord lastTask = null;
7787 for (int i=0; i<N; i++) {
7788 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7789 if (r == token) {
7790 if (!onlyRoot || lastTask != r.task) {
7791 return r.task.taskId;
7792 }
7793 return -1;
7794 }
7795 lastTask = r.task;
7796 }
7797
7798 return -1;
7799 }
7800
7801 /**
7802 * Returns the top activity in any existing task matching the given
7803 * Intent. Returns null if no such task is found.
7804 */
7805 private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
7806 ComponentName cls = intent.getComponent();
7807 if (info.targetActivity != null) {
7808 cls = new ComponentName(info.packageName, info.targetActivity);
7809 }
7810
7811 TaskRecord cp = null;
7812
7813 final int N = mHistory.size();
7814 for (int i=(N-1); i>=0; i--) {
7815 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7816 if (!r.finishing && r.task != cp
7817 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
7818 cp = r.task;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007819 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007820 // + "/aff=" + r.task.affinity + " to new cls="
7821 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
7822 if (r.task.affinity != null) {
7823 if (r.task.affinity.equals(info.taskAffinity)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007824 //Slog.i(TAG, "Found matching affinity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 return r;
7826 }
7827 } else if (r.task.intent != null
7828 && r.task.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007829 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007830 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007831 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007832 return r;
7833 } else if (r.task.affinityIntent != null
7834 && r.task.affinityIntent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007835 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007836 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007837 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 return r;
7839 }
7840 }
7841 }
7842
7843 return null;
7844 }
7845
7846 /**
7847 * Returns the first activity (starting from the top of the stack) that
7848 * is the same as the given activity. Returns null if no such activity
7849 * is found.
7850 */
7851 private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
7852 ComponentName cls = intent.getComponent();
7853 if (info.targetActivity != null) {
7854 cls = new ComponentName(info.packageName, info.targetActivity);
7855 }
7856
7857 final int N = mHistory.size();
7858 for (int i=(N-1); i>=0; i--) {
7859 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7860 if (!r.finishing) {
7861 if (r.intent.getComponent().equals(cls)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007862 //Slog.i(TAG, "Found matching class!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 //dump();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007864 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865 return r;
7866 }
7867 }
7868 }
7869
7870 return null;
7871 }
7872
7873 public void finishOtherInstances(IBinder token, ComponentName className) {
7874 synchronized(this) {
7875 final long origId = Binder.clearCallingIdentity();
7876
7877 int N = mHistory.size();
7878 TaskRecord lastTask = null;
7879 for (int i=0; i<N; i++) {
7880 HistoryRecord r = (HistoryRecord)mHistory.get(i);
7881 if (r.realActivity.equals(className)
7882 && r != token && lastTask != r.task) {
7883 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
7884 null, "others")) {
7885 i--;
7886 N--;
7887 }
7888 }
7889 lastTask = r.task;
7890 }
7891
7892 Binder.restoreCallingIdentity(origId);
7893 }
7894 }
7895
7896 // =========================================================
7897 // THUMBNAILS
7898 // =========================================================
7899
7900 public void reportThumbnail(IBinder token,
7901 Bitmap thumbnail, CharSequence description) {
7902 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
7903 final long origId = Binder.clearCallingIdentity();
7904 sendPendingThumbnail(null, token, thumbnail, description, true);
7905 Binder.restoreCallingIdentity(origId);
7906 }
7907
7908 final void sendPendingThumbnail(HistoryRecord r, IBinder token,
7909 Bitmap thumbnail, CharSequence description, boolean always) {
7910 TaskRecord task = null;
7911 ArrayList receivers = null;
7912
7913 //System.out.println("Send pending thumbnail: " + r);
7914
7915 synchronized(this) {
7916 if (r == null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -07007917 int index = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007918 if (index < 0) {
7919 return;
7920 }
7921 r = (HistoryRecord)mHistory.get(index);
7922 }
7923 if (thumbnail == null) {
7924 thumbnail = r.thumbnail;
7925 description = r.description;
7926 }
7927 if (thumbnail == null && !always) {
7928 // If there is no thumbnail, and this entry is not actually
7929 // going away, then abort for now and pick up the next
7930 // thumbnail we get.
7931 return;
7932 }
7933 task = r.task;
7934
7935 int N = mPendingThumbnails.size();
7936 int i=0;
7937 while (i<N) {
7938 PendingThumbnailsRecord pr =
7939 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
7940 //System.out.println("Looking in " + pr.pendingRecords);
7941 if (pr.pendingRecords.remove(r)) {
7942 if (receivers == null) {
7943 receivers = new ArrayList();
7944 }
7945 receivers.add(pr);
7946 if (pr.pendingRecords.size() == 0) {
7947 pr.finished = true;
7948 mPendingThumbnails.remove(i);
7949 N--;
7950 continue;
7951 }
7952 }
7953 i++;
7954 }
7955 }
7956
7957 if (receivers != null) {
7958 final int N = receivers.size();
7959 for (int i=0; i<N; i++) {
7960 try {
7961 PendingThumbnailsRecord pr =
7962 (PendingThumbnailsRecord)receivers.get(i);
7963 pr.receiver.newThumbnail(
7964 task != null ? task.taskId : -1, thumbnail, description);
7965 if (pr.finished) {
7966 pr.receiver.finished();
7967 }
7968 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007969 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007970 }
7971 }
7972 }
7973 }
7974
7975 // =========================================================
7976 // CONTENT PROVIDERS
7977 // =========================================================
7978
7979 private final List generateApplicationProvidersLocked(ProcessRecord app) {
7980 List providers = null;
7981 try {
7982 providers = ActivityThread.getPackageManager().
7983 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07007984 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007985 } catch (RemoteException ex) {
7986 }
7987 if (providers != null) {
7988 final int N = providers.size();
7989 for (int i=0; i<N; i++) {
7990 ProviderInfo cpi =
7991 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007992 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007993 if (cpr == null) {
7994 cpr = new ContentProviderRecord(cpi, app.info);
7995 mProvidersByClass.put(cpi.name, cpr);
7996 }
7997 app.pubProviders.put(cpi.name, cpr);
7998 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07007999 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008000 }
8001 }
8002 return providers;
8003 }
8004
8005 private final String checkContentProviderPermissionLocked(
8006 ProviderInfo cpi, ProcessRecord r, int mode) {
8007 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
8008 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
8009 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
8010 cpi.exported ? -1 : cpi.applicationInfo.uid)
8011 == PackageManager.PERMISSION_GRANTED
8012 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8013 return null;
8014 }
8015 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
8016 cpi.exported ? -1 : cpi.applicationInfo.uid)
8017 == PackageManager.PERMISSION_GRANTED) {
8018 return null;
8019 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07008020
8021 PathPermission[] pps = cpi.pathPermissions;
8022 if (pps != null) {
8023 int i = pps.length;
8024 while (i > 0) {
8025 i--;
8026 PathPermission pp = pps[i];
8027 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
8028 cpi.exported ? -1 : cpi.applicationInfo.uid)
8029 == PackageManager.PERMISSION_GRANTED
8030 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
8031 return null;
8032 }
8033 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
8034 cpi.exported ? -1 : cpi.applicationInfo.uid)
8035 == PackageManager.PERMISSION_GRANTED) {
8036 return null;
8037 }
8038 }
8039 }
8040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 String msg = "Permission Denial: opening provider " + cpi.name
8042 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
8043 + ", uid=" + callingUid + ") requires "
8044 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008045 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008046 return msg;
8047 }
8048
8049 private final ContentProviderHolder getContentProviderImpl(
8050 IApplicationThread caller, String name) {
8051 ContentProviderRecord cpr;
8052 ProviderInfo cpi = null;
8053
8054 synchronized(this) {
8055 ProcessRecord r = null;
8056 if (caller != null) {
8057 r = getRecordForAppLocked(caller);
8058 if (r == null) {
8059 throw new SecurityException(
8060 "Unable to find app for caller " + caller
8061 + " (pid=" + Binder.getCallingPid()
8062 + ") when getting content provider " + name);
8063 }
8064 }
8065
8066 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07008067 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008068 if (cpr != null) {
8069 cpi = cpr.info;
8070 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8071 return new ContentProviderHolder(cpi,
8072 cpi.readPermission != null
8073 ? cpi.readPermission : cpi.writePermission);
8074 }
8075
8076 if (r != null && cpr.canRunHere(r)) {
8077 // This provider has been published or is in the process
8078 // of being published... but it is also allowed to run
8079 // in the caller's process, so don't make a connection
8080 // and just let the caller instantiate its own instance.
8081 if (cpr.provider != null) {
8082 // don't give caller the provider object, it needs
8083 // to make its own.
8084 cpr = new ContentProviderRecord(cpr);
8085 }
8086 return cpr;
8087 }
8088
8089 final long origId = Binder.clearCallingIdentity();
8090
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008091 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008092 // return it right away.
8093 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008094 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008095 "Adding provider requested by "
8096 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008097 + cpr.info.processName);
8098 Integer cnt = r.conProviders.get(cpr);
8099 if (cnt == null) {
8100 r.conProviders.put(cpr, new Integer(1));
8101 } else {
8102 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008104 cpr.clients.add(r);
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07008105 if (cpr.app != null && r.setAdj >= VISIBLE_APP_ADJ) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07008106 // If this is a visible app accessing the provider,
8107 // make sure to count it as being accessed and thus
8108 // back up on the LRU list. This is good because
8109 // content providers are often expensive to start.
8110 updateLruProcessLocked(cpr.app, false, true);
8111 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07008112 } else {
8113 cpr.externals++;
8114 }
8115
8116 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117 updateOomAdjLocked(cpr.app);
8118 }
8119
8120 Binder.restoreCallingIdentity(origId);
8121
8122 } else {
8123 try {
8124 cpi = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07008125 resolveContentProvider(name,
8126 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008127 } catch (RemoteException ex) {
8128 }
8129 if (cpi == null) {
8130 return null;
8131 }
8132
8133 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
8134 return new ContentProviderHolder(cpi,
8135 cpi.readPermission != null
8136 ? cpi.readPermission : cpi.writePermission);
8137 }
8138
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008139 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
8140 && !cpi.processName.equals("system")) {
8141 // If this content provider does not run in the system
8142 // process, and the system is not yet ready to run other
8143 // processes, then fail fast instead of hanging.
8144 throw new IllegalArgumentException(
8145 "Attempt to launch content provider before system ready");
8146 }
8147
Dianne Hackborn860755f2010-06-03 18:47:52 -07008148 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008149 final boolean firstClass = cpr == null;
8150 if (firstClass) {
8151 try {
8152 ApplicationInfo ai =
8153 ActivityThread.getPackageManager().
8154 getApplicationInfo(
8155 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07008156 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008157 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008158 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159 + cpi.name);
8160 return null;
8161 }
8162 cpr = new ContentProviderRecord(cpi, ai);
8163 } catch (RemoteException ex) {
8164 // pm is in same process, this will never happen.
8165 }
8166 }
8167
8168 if (r != null && cpr.canRunHere(r)) {
8169 // If this is a multiprocess provider, then just return its
8170 // info and allow the caller to instantiate it. Only do
8171 // this if the provider is the same user as the caller's
8172 // process, or can run as root (so can be in any process).
8173 return cpr;
8174 }
8175
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008176 if (DEBUG_PROVIDER) {
8177 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08008178 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008179 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008180 }
8181
8182 // This is single process, and our app is now connecting to it.
8183 // See if we are already in the process of launching this
8184 // provider.
8185 final int N = mLaunchingProviders.size();
8186 int i;
8187 for (i=0; i<N; i++) {
8188 if (mLaunchingProviders.get(i) == cpr) {
8189 break;
8190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008191 }
8192
8193 // If the provider is not already being launched, then get it
8194 // started.
8195 if (i >= N) {
8196 final long origId = Binder.clearCallingIdentity();
8197 ProcessRecord proc = startProcessLocked(cpi.processName,
8198 cpr.appInfo, false, 0, "content provider",
8199 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008200 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008201 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008202 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008203 + cpi.applicationInfo.packageName + "/"
8204 + cpi.applicationInfo.uid + " for provider "
8205 + name + ": process is bad");
8206 return null;
8207 }
8208 cpr.launchingApp = proc;
8209 mLaunchingProviders.add(cpr);
8210 Binder.restoreCallingIdentity(origId);
8211 }
8212
8213 // Make sure the provider is published (the same provider class
8214 // may be published under multiple names).
8215 if (firstClass) {
8216 mProvidersByClass.put(cpi.name, cpr);
8217 }
8218 mProvidersByName.put(name, cpr);
8219
8220 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008221 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008222 "Adding provider requested by "
8223 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008224 + cpr.info.processName);
8225 Integer cnt = r.conProviders.get(cpr);
8226 if (cnt == null) {
8227 r.conProviders.put(cpr, new Integer(1));
8228 } else {
8229 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
8230 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008231 cpr.clients.add(r);
8232 } else {
8233 cpr.externals++;
8234 }
8235 }
8236 }
8237
8238 // Wait for the provider to be published...
8239 synchronized (cpr) {
8240 while (cpr.provider == null) {
8241 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008242 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008243 + cpi.applicationInfo.packageName + "/"
8244 + cpi.applicationInfo.uid + " for provider "
8245 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008246 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 cpi.applicationInfo.packageName,
8248 cpi.applicationInfo.uid, name);
8249 return null;
8250 }
8251 try {
8252 cpr.wait();
8253 } catch (InterruptedException ex) {
8254 }
8255 }
8256 }
8257 return cpr;
8258 }
8259
8260 public final ContentProviderHolder getContentProvider(
8261 IApplicationThread caller, String name) {
8262 if (caller == null) {
8263 String msg = "null IApplicationThread when getting content provider "
8264 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008265 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 throw new SecurityException(msg);
8267 }
8268
8269 return getContentProviderImpl(caller, name);
8270 }
8271
8272 private ContentProviderHolder getContentProviderExternal(String name) {
8273 return getContentProviderImpl(null, name);
8274 }
8275
8276 /**
8277 * Drop a content provider from a ProcessRecord's bookkeeping
8278 * @param cpr
8279 */
8280 public void removeContentProvider(IApplicationThread caller, String name) {
8281 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008282 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008283 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008284 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008285 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008286 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008287 return;
8288 }
8289 final ProcessRecord r = getRecordForAppLocked(caller);
8290 if (r == null) {
8291 throw new SecurityException(
8292 "Unable to find app for caller " + caller +
8293 " when removing content provider " + name);
8294 }
8295 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008296 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008297 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008298 + r.info.processName + " from process "
8299 + localCpr.appInfo.processName);
8300 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008301 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08008302 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008303 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008304 return;
8305 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008306 Integer cnt = r.conProviders.get(localCpr);
8307 if (cnt == null || cnt.intValue() <= 1) {
8308 localCpr.clients.remove(r);
8309 r.conProviders.remove(localCpr);
8310 } else {
8311 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
8312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008313 }
8314 updateOomAdjLocked();
8315 }
8316 }
8317
8318 private void removeContentProviderExternal(String name) {
8319 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008320 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008321 if(cpr == null) {
8322 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08008323 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008324 return;
8325 }
8326
8327 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07008328 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008329 localCpr.externals--;
8330 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008331 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008332 }
8333 updateOomAdjLocked();
8334 }
8335 }
8336
8337 public final void publishContentProviders(IApplicationThread caller,
8338 List<ContentProviderHolder> providers) {
8339 if (providers == null) {
8340 return;
8341 }
8342
8343 synchronized(this) {
8344 final ProcessRecord r = getRecordForAppLocked(caller);
8345 if (r == null) {
8346 throw new SecurityException(
8347 "Unable to find app for caller " + caller
8348 + " (pid=" + Binder.getCallingPid()
8349 + ") when publishing content providers");
8350 }
8351
8352 final long origId = Binder.clearCallingIdentity();
8353
8354 final int N = providers.size();
8355 for (int i=0; i<N; i++) {
8356 ContentProviderHolder src = providers.get(i);
8357 if (src == null || src.info == null || src.provider == null) {
8358 continue;
8359 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07008360 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008361 if (dst != null) {
8362 mProvidersByClass.put(dst.info.name, dst);
8363 String names[] = dst.info.authority.split(";");
8364 for (int j = 0; j < names.length; j++) {
8365 mProvidersByName.put(names[j], dst);
8366 }
8367
8368 int NL = mLaunchingProviders.size();
8369 int j;
8370 for (j=0; j<NL; j++) {
8371 if (mLaunchingProviders.get(j) == dst) {
8372 mLaunchingProviders.remove(j);
8373 j--;
8374 NL--;
8375 }
8376 }
8377 synchronized (dst) {
8378 dst.provider = src.provider;
8379 dst.app = r;
8380 dst.notifyAll();
8381 }
8382 updateOomAdjLocked(r);
8383 }
8384 }
8385
8386 Binder.restoreCallingIdentity(origId);
8387 }
8388 }
8389
8390 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008391 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06008392 synchronized (mSelf) {
8393 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
8394 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08008395 if (providers != null) {
8396 for (int i=providers.size()-1; i>=0; i--) {
8397 ProviderInfo pi = (ProviderInfo)providers.get(i);
8398 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8399 Slog.w(TAG, "Not installing system proc provider " + pi.name
8400 + ": not system .apk");
8401 providers.remove(i);
8402 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08008403 }
8404 }
8405 }
Josh Bartel2ecce342010-02-25 10:55:48 -06008406 if (providers != null) {
8407 mSystemThread.installSystemProviders(providers);
8408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008409 }
8410
8411 // =========================================================
8412 // GLOBAL MANAGEMENT
8413 // =========================================================
8414
8415 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
8416 ApplicationInfo info, String customProcess) {
8417 String proc = customProcess != null ? customProcess : info.processName;
8418 BatteryStatsImpl.Uid.Proc ps = null;
8419 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8420 synchronized (stats) {
8421 ps = stats.getProcessStatsLocked(info.uid, proc);
8422 }
8423 return new ProcessRecord(ps, thread, info, proc);
8424 }
8425
8426 final ProcessRecord addAppLocked(ApplicationInfo info) {
8427 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
8428
8429 if (app == null) {
8430 app = newProcessRecordLocked(null, info, null);
8431 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008432 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008433 }
8434
8435 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
8436 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
8437 app.persistent = true;
8438 app.maxAdj = CORE_SERVER_ADJ;
8439 }
8440 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
8441 mPersistentStartingProcesses.add(app);
8442 startProcessLocked(app, "added application", app.processName);
8443 }
8444
8445 return app;
8446 }
8447
8448 public void unhandledBack() {
8449 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
8450 "unhandledBack()");
8451
8452 synchronized(this) {
8453 int count = mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008454 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008455 TAG, "Performing unhandledBack(): stack size = " + count);
8456 if (count > 1) {
8457 final long origId = Binder.clearCallingIdentity();
8458 finishActivityLocked((HistoryRecord)mHistory.get(count-1),
8459 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
8460 Binder.restoreCallingIdentity(origId);
8461 }
8462 }
8463 }
8464
8465 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
8466 String name = uri.getAuthority();
8467 ContentProviderHolder cph = getContentProviderExternal(name);
8468 ParcelFileDescriptor pfd = null;
8469 if (cph != null) {
8470 // We record the binder invoker's uid in thread-local storage before
8471 // going to the content provider to open the file. Later, in the code
8472 // that handles all permissions checks, we look for this uid and use
8473 // that rather than the Activity Manager's own uid. The effect is that
8474 // we do the check against the caller's permissions even though it looks
8475 // to the content provider like the Activity Manager itself is making
8476 // the request.
8477 sCallerIdentity.set(new Identity(
8478 Binder.getCallingPid(), Binder.getCallingUid()));
8479 try {
8480 pfd = cph.provider.openFile(uri, "r");
8481 } catch (FileNotFoundException e) {
8482 // do nothing; pfd will be returned null
8483 } finally {
8484 // Ensure that whatever happens, we clean up the identity state
8485 sCallerIdentity.remove();
8486 }
8487
8488 // We've got the fd now, so we're done with the provider.
8489 removeContentProviderExternal(name);
8490 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008491 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008492 }
8493 return pfd;
8494 }
8495
8496 public void goingToSleep() {
8497 synchronized(this) {
8498 mSleeping = true;
8499 mWindowManager.setEventDispatching(false);
8500
8501 if (mResumedActivity != null) {
8502 pauseIfSleepingLocked();
8503 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008504 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008505 }
8506 }
8507 }
8508
Dianne Hackborn55280a92009-05-07 15:53:46 -07008509 public boolean shutdown(int timeout) {
8510 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
8511 != PackageManager.PERMISSION_GRANTED) {
8512 throw new SecurityException("Requires permission "
8513 + android.Manifest.permission.SHUTDOWN);
8514 }
8515
8516 boolean timedout = false;
8517
8518 synchronized(this) {
8519 mShuttingDown = true;
8520 mWindowManager.setEventDispatching(false);
8521
8522 if (mResumedActivity != null) {
8523 pauseIfSleepingLocked();
8524 final long endTime = System.currentTimeMillis() + timeout;
8525 while (mResumedActivity != null || mPausingActivity != null) {
8526 long delay = endTime - System.currentTimeMillis();
8527 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008528 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07008529 timedout = true;
8530 break;
8531 }
8532 try {
8533 this.wait();
8534 } catch (InterruptedException e) {
8535 }
8536 }
8537 }
8538 }
8539
8540 mUsageStatsService.shutdown();
8541 mBatteryStatsService.shutdown();
8542
8543 return timedout;
8544 }
8545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008546 void pauseIfSleepingLocked() {
Dianne Hackborn55280a92009-05-07 15:53:46 -07008547 if (mSleeping || mShuttingDown) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008548 if (!mGoingToSleep.isHeld()) {
8549 mGoingToSleep.acquire();
8550 if (mLaunchingActivity.isHeld()) {
8551 mLaunchingActivity.release();
8552 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
8553 }
8554 }
8555
8556 // If we are not currently pausing an activity, get the current
8557 // one to pause. If we are pausing one, we will just let that stuff
8558 // run and release the wake lock when all done.
8559 if (mPausingActivity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008560 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
8561 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008562 startPausingLocked(false, true);
8563 }
8564 }
8565 }
8566
8567 public void wakingUp() {
8568 synchronized(this) {
8569 if (mGoingToSleep.isHeld()) {
8570 mGoingToSleep.release();
8571 }
8572 mWindowManager.setEventDispatching(true);
8573 mSleeping = false;
8574 resumeTopActivityLocked(null);
8575 }
8576 }
8577
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008578 public void stopAppSwitches() {
8579 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8580 != PackageManager.PERMISSION_GRANTED) {
8581 throw new SecurityException("Requires permission "
8582 + android.Manifest.permission.STOP_APP_SWITCHES);
8583 }
8584
8585 synchronized(this) {
8586 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
8587 + APP_SWITCH_DELAY_TIME;
8588 mDidAppSwitch = false;
8589 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8590 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
8591 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
8592 }
8593 }
8594
8595 public void resumeAppSwitches() {
8596 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
8597 != PackageManager.PERMISSION_GRANTED) {
8598 throw new SecurityException("Requires permission "
8599 + android.Manifest.permission.STOP_APP_SWITCHES);
8600 }
8601
8602 synchronized(this) {
8603 // Note that we don't execute any pending app switches... we will
8604 // let those wait until either the timeout, or the next start
8605 // activity request.
8606 mAppSwitchesAllowedTime = 0;
8607 }
8608 }
8609
8610 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
8611 String name) {
8612 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
8613 return true;
8614 }
8615
8616 final int perm = checkComponentPermission(
8617 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
8618 callingUid, -1);
8619 if (perm == PackageManager.PERMISSION_GRANTED) {
8620 return true;
8621 }
8622
Joe Onorato8a9b2202010-02-26 18:56:32 -08008623 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07008624 return false;
8625 }
8626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008627 public void setDebugApp(String packageName, boolean waitForDebugger,
8628 boolean persistent) {
8629 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
8630 "setDebugApp()");
8631
8632 // Note that this is not really thread safe if there are multiple
8633 // callers into it at the same time, but that's not a situation we
8634 // care about.
8635 if (persistent) {
8636 final ContentResolver resolver = mContext.getContentResolver();
8637 Settings.System.putString(
8638 resolver, Settings.System.DEBUG_APP,
8639 packageName);
8640 Settings.System.putInt(
8641 resolver, Settings.System.WAIT_FOR_DEBUGGER,
8642 waitForDebugger ? 1 : 0);
8643 }
8644
8645 synchronized (this) {
8646 if (!persistent) {
8647 mOrigDebugApp = mDebugApp;
8648 mOrigWaitForDebugger = mWaitForDebugger;
8649 }
8650 mDebugApp = packageName;
8651 mWaitForDebugger = waitForDebugger;
8652 mDebugTransient = !persistent;
8653 if (packageName != null) {
8654 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08008655 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008656 Binder.restoreCallingIdentity(origId);
8657 }
8658 }
8659 }
8660
8661 public void setAlwaysFinish(boolean enabled) {
8662 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
8663 "setAlwaysFinish()");
8664
8665 Settings.System.putInt(
8666 mContext.getContentResolver(),
8667 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
8668
8669 synchronized (this) {
8670 mAlwaysFinishActivities = enabled;
8671 }
8672 }
8673
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008674 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008675 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008676 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008677 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008678 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008679 }
8680 }
8681
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08008682 public boolean isUserAMonkey() {
8683 // For now the fact that there is a controller implies
8684 // we have a monkey.
8685 synchronized (this) {
8686 return mController != null;
8687 }
8688 }
8689
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008690 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008691 synchronized (this) {
8692 mWatchers.register(watcher);
8693 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008694 }
8695
8696 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06008697 synchronized (this) {
8698 mWatchers.unregister(watcher);
8699 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07008700 }
8701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008702 public final void enterSafeMode() {
8703 synchronized(this) {
8704 // It only makes sense to do this before the system is ready
8705 // and started launching other packages.
8706 if (!mSystemReady) {
8707 try {
8708 ActivityThread.getPackageManager().enterSafeMode();
8709 } catch (RemoteException e) {
8710 }
8711
8712 View v = LayoutInflater.from(mContext).inflate(
8713 com.android.internal.R.layout.safe_mode, null);
8714 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
8715 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
8716 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
8717 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
8718 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
8719 lp.format = v.getBackground().getOpacity();
8720 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
8721 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
8722 ((WindowManager)mContext.getSystemService(
8723 Context.WINDOW_SERVICE)).addView(v, lp);
8724 }
8725 }
8726 }
8727
8728 public void noteWakeupAlarm(IIntentSender sender) {
8729 if (!(sender instanceof PendingIntentRecord)) {
8730 return;
8731 }
8732 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8733 synchronized (stats) {
8734 if (mBatteryStatsService.isOnBattery()) {
8735 mBatteryStatsService.enforceCallingPermission();
8736 PendingIntentRecord rec = (PendingIntentRecord)sender;
8737 int MY_UID = Binder.getCallingUid();
8738 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
8739 BatteryStatsImpl.Uid.Pkg pkg =
8740 stats.getPackageStatsLocked(uid, rec.key.packageName);
8741 pkg.incWakeupsLocked();
8742 }
8743 }
8744 }
8745
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008746 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008747 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008748 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008750 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008751 // XXX Note: don't acquire main activity lock here, because the window
8752 // manager calls in with its locks held.
8753
8754 boolean killed = false;
8755 synchronized (mPidsSelfLocked) {
8756 int[] types = new int[pids.length];
8757 int worstType = 0;
8758 for (int i=0; i<pids.length; i++) {
8759 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8760 if (proc != null) {
8761 int type = proc.setAdj;
8762 types[i] = type;
8763 if (type > worstType) {
8764 worstType = type;
8765 }
8766 }
8767 }
8768
8769 // If the worse oom_adj is somewhere in the hidden proc LRU range,
8770 // then constrain it so we will kill all hidden procs.
8771 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
8772 worstType = HIDDEN_APP_MIN_ADJ;
8773 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008774 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008775 for (int i=0; i<pids.length; i++) {
8776 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
8777 if (proc == null) {
8778 continue;
8779 }
8780 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008781 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008782 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07008783 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
8784 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008785 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07008786 proc.killedBackground = true;
8787 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 }
8789 }
8790 }
8791 return killed;
8792 }
8793
8794 public void reportPss(IApplicationThread caller, int pss) {
8795 Watchdog.PssRequestor req;
8796 String name;
8797 ProcessRecord callerApp;
8798 synchronized (this) {
8799 if (caller == null) {
8800 return;
8801 }
8802 callerApp = getRecordForAppLocked(caller);
8803 if (callerApp == null) {
8804 return;
8805 }
8806 callerApp.lastPss = pss;
8807 req = callerApp;
8808 name = callerApp.processName;
8809 }
8810 Watchdog.getInstance().reportPss(req, name, pss);
8811 if (!callerApp.persistent) {
8812 removeRequestedPss(callerApp);
8813 }
8814 }
8815
8816 public void requestPss(Runnable completeCallback) {
8817 ArrayList<ProcessRecord> procs;
8818 synchronized (this) {
8819 mRequestPssCallback = completeCallback;
8820 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008821 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8822 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008823 if (!proc.persistent) {
8824 mRequestPssList.add(proc);
8825 }
8826 }
8827 procs = new ArrayList<ProcessRecord>(mRequestPssList);
8828 }
8829
8830 int oldPri = Process.getThreadPriority(Process.myTid());
8831 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8832 for (int i=procs.size()-1; i>=0; i--) {
8833 ProcessRecord proc = procs.get(i);
8834 proc.lastPss = 0;
8835 proc.requestPss();
8836 }
8837 Process.setThreadPriority(oldPri);
8838 }
8839
8840 void removeRequestedPss(ProcessRecord proc) {
8841 Runnable callback = null;
8842 synchronized (this) {
8843 if (mRequestPssList.remove(proc)) {
8844 if (mRequestPssList.size() == 0) {
8845 callback = mRequestPssCallback;
8846 mRequestPssCallback = null;
8847 }
8848 }
8849 }
8850
8851 if (callback != null) {
8852 callback.run();
8853 }
8854 }
8855
8856 public void collectPss(Watchdog.PssStats stats) {
8857 stats.mEmptyPss = 0;
8858 stats.mEmptyCount = 0;
8859 stats.mBackgroundPss = 0;
8860 stats.mBackgroundCount = 0;
8861 stats.mServicePss = 0;
8862 stats.mServiceCount = 0;
8863 stats.mVisiblePss = 0;
8864 stats.mVisibleCount = 0;
8865 stats.mForegroundPss = 0;
8866 stats.mForegroundCount = 0;
8867 stats.mNoPssCount = 0;
8868 synchronized (this) {
8869 int i;
8870 int NPD = mProcDeaths.length < stats.mProcDeaths.length
8871 ? mProcDeaths.length : stats.mProcDeaths.length;
8872 int aggr = 0;
8873 for (i=0; i<NPD; i++) {
8874 aggr += mProcDeaths[i];
8875 stats.mProcDeaths[i] = aggr;
8876 }
8877 while (i<stats.mProcDeaths.length) {
8878 stats.mProcDeaths[i] = 0;
8879 i++;
8880 }
8881
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008882 for (i=mLruProcesses.size()-1; i>=0; i--) {
8883 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008884 if (proc.persistent) {
8885 continue;
8886 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008887 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008888 if (proc.lastPss == 0) {
8889 stats.mNoPssCount++;
8890 continue;
8891 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008892 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
8893 if (proc.empty) {
8894 stats.mEmptyPss += proc.lastPss;
8895 stats.mEmptyCount++;
8896 } else {
8897 stats.mBackgroundPss += proc.lastPss;
8898 stats.mBackgroundCount++;
8899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008900 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
8901 stats.mVisiblePss += proc.lastPss;
8902 stats.mVisibleCount++;
8903 } else {
8904 stats.mForegroundPss += proc.lastPss;
8905 stats.mForegroundCount++;
8906 }
8907 }
8908 }
8909 }
8910
8911 public final void startRunning(String pkg, String cls, String action,
8912 String data) {
8913 synchronized(this) {
8914 if (mStartRunning) {
8915 return;
8916 }
8917 mStartRunning = true;
8918 mTopComponent = pkg != null && cls != null
8919 ? new ComponentName(pkg, cls) : null;
8920 mTopAction = action != null ? action : Intent.ACTION_MAIN;
8921 mTopData = data;
8922 if (!mSystemReady) {
8923 return;
8924 }
8925 }
8926
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008927 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 }
8929
8930 private void retrieveSettings() {
8931 final ContentResolver resolver = mContext.getContentResolver();
8932 String debugApp = Settings.System.getString(
8933 resolver, Settings.System.DEBUG_APP);
8934 boolean waitForDebugger = Settings.System.getInt(
8935 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
8936 boolean alwaysFinishActivities = Settings.System.getInt(
8937 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
8938
8939 Configuration configuration = new Configuration();
8940 Settings.System.getConfiguration(resolver, configuration);
8941
8942 synchronized (this) {
8943 mDebugApp = mOrigDebugApp = debugApp;
8944 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
8945 mAlwaysFinishActivities = alwaysFinishActivities;
8946 // This happens before any activities are started, so we can
8947 // change mConfiguration in-place.
8948 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008949 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008950 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008951 }
8952 }
8953
8954 public boolean testIsSystemReady() {
8955 // no need to synchronize(this) just to read & return the value
8956 return mSystemReady;
8957 }
8958
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008959 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008960 // In the simulator, startRunning will never have been called, which
8961 // normally sets a few crucial variables. Do it here instead.
8962 if (!Process.supportsProcesses()) {
8963 mStartRunning = true;
8964 mTopAction = Intent.ACTION_MAIN;
8965 }
8966
8967 synchronized(this) {
8968 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07008969 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970 return;
8971 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008972
8973 // Check to see if there are any update receivers to run.
8974 if (!mDidUpdate) {
8975 if (mWaitingUpdate) {
8976 return;
8977 }
8978 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
8979 List<ResolveInfo> ris = null;
8980 try {
8981 ris = ActivityThread.getPackageManager().queryIntentReceivers(
8982 intent, null, 0);
8983 } catch (RemoteException e) {
8984 }
8985 if (ris != null) {
8986 for (int i=ris.size()-1; i>=0; i--) {
8987 if ((ris.get(i).activityInfo.applicationInfo.flags
8988 &ApplicationInfo.FLAG_SYSTEM) == 0) {
8989 ris.remove(i);
8990 }
8991 }
8992 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
8993 for (int i=0; i<ris.size(); i++) {
8994 ActivityInfo ai = ris.get(i).activityInfo;
8995 intent.setComponent(new ComponentName(ai.packageName, ai.name));
8996 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08008997 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07008998 finisher = new IIntentReceiver.Stub() {
8999 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07009000 String data, Bundle extras, boolean ordered,
9001 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009002 throws RemoteException {
9003 synchronized (ActivityManagerService.this) {
9004 mDidUpdate = true;
9005 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009006 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009007 }
9008 };
9009 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009010 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009011 broadcastIntentLocked(null, null, intent, null, finisher,
9012 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08009013 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009014 mWaitingUpdate = true;
9015 }
9016 }
9017 }
9018 if (mWaitingUpdate) {
9019 return;
9020 }
9021 mDidUpdate = true;
9022 }
9023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009024 mSystemReady = true;
9025 if (!mStartRunning) {
9026 return;
9027 }
9028 }
9029
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009030 ArrayList<ProcessRecord> procsToKill = null;
9031 synchronized(mPidsSelfLocked) {
9032 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
9033 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
9034 if (!isAllowedWhileBooting(proc.info)){
9035 if (procsToKill == null) {
9036 procsToKill = new ArrayList<ProcessRecord>();
9037 }
9038 procsToKill.add(proc);
9039 }
9040 }
9041 }
9042
9043 if (procsToKill != null) {
9044 synchronized(this) {
9045 for (int i=procsToKill.size()-1; i>=0; i--) {
9046 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009047 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009048 removeProcessLocked(proc, true);
9049 }
9050 }
9051 }
9052
Joe Onorato8a9b2202010-02-26 18:56:32 -08009053 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009054 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 SystemClock.uptimeMillis());
9056
9057 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009058 // Make sure we have no pre-ready processes sitting around.
9059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009060 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
9061 ResolveInfo ri = mContext.getPackageManager()
9062 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07009063 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009064 CharSequence errorMsg = null;
9065 if (ri != null) {
9066 ActivityInfo ai = ri.activityInfo;
9067 ApplicationInfo app = ai.applicationInfo;
9068 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
9069 mTopAction = Intent.ACTION_FACTORY_TEST;
9070 mTopData = null;
9071 mTopComponent = new ComponentName(app.packageName,
9072 ai.name);
9073 } else {
9074 errorMsg = mContext.getResources().getText(
9075 com.android.internal.R.string.factorytest_not_system);
9076 }
9077 } else {
9078 errorMsg = mContext.getResources().getText(
9079 com.android.internal.R.string.factorytest_no_action);
9080 }
9081 if (errorMsg != null) {
9082 mTopAction = null;
9083 mTopData = null;
9084 mTopComponent = null;
9085 Message msg = Message.obtain();
9086 msg.what = SHOW_FACTORY_ERROR_MSG;
9087 msg.getData().putCharSequence("msg", errorMsg);
9088 mHandler.sendMessage(msg);
9089 }
9090 }
9091 }
9092
9093 retrieveSettings();
9094
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07009095 if (goingCallback != null) goingCallback.run();
9096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009097 synchronized (this) {
9098 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
9099 try {
9100 List apps = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009101 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102 if (apps != null) {
9103 int N = apps.size();
9104 int i;
9105 for (i=0; i<N; i++) {
9106 ApplicationInfo info
9107 = (ApplicationInfo)apps.get(i);
9108 if (info != null &&
9109 !info.packageName.equals("android")) {
9110 addAppLocked(info);
9111 }
9112 }
9113 }
9114 } catch (RemoteException ex) {
9115 // pm is in same process, this will never happen.
9116 }
9117 }
9118
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009119 // Start up initial activity.
9120 mBooting = true;
9121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009122 try {
9123 if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
9124 Message msg = Message.obtain();
9125 msg.what = SHOW_UID_ERROR_MSG;
9126 mHandler.sendMessage(msg);
9127 }
9128 } catch (RemoteException e) {
9129 }
9130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009131 resumeTopActivityLocked(null);
9132 }
9133 }
9134
Dan Egnorb7f03672009-12-09 16:22:32 -08009135 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009136 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009137 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009138 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009139 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009140 startAppProblemLocked(app);
9141 app.stopFreezingAllLocked();
9142 return handleAppCrashLocked(app);
9143 }
9144
Dan Egnorb7f03672009-12-09 16:22:32 -08009145 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009146 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08009148 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08009149 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
9150 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009151 startAppProblemLocked(app);
9152 app.stopFreezingAllLocked();
9153 }
9154
9155 /**
9156 * Generate a process error record, suitable for attachment to a ProcessRecord.
9157 *
9158 * @param app The ProcessRecord in which the error occurred.
9159 * @param condition Crashing, Application Not Responding, etc. Values are defined in
9160 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08009161 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009162 * @param shortMsg Short message describing the crash.
9163 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08009164 * @param stackTrace Full crash stack trace, may be null.
9165 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009166 * @return Returns a fully-formed AppErrorStateInfo record.
9167 */
9168 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08009169 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08009171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009172 report.condition = condition;
9173 report.processName = app.processName;
9174 report.pid = app.pid;
9175 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08009176 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 report.shortMsg = shortMsg;
9178 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08009179 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009180
9181 return report;
9182 }
9183
Dan Egnor42471dd2010-01-07 17:25:22 -08009184 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009185 synchronized (this) {
9186 app.crashing = false;
9187 app.crashingReport = null;
9188 app.notResponding = false;
9189 app.notRespondingReport = null;
9190 if (app.anrDialog == fromDialog) {
9191 app.anrDialog = null;
9192 }
9193 if (app.waitDialog == fromDialog) {
9194 app.waitDialog = null;
9195 }
9196 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08009197 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07009198 Slog.i(ActivityManagerService.TAG, "Killing "
9199 + app.processName + " (pid=" + app.pid + "): user's request");
9200 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
9201 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009202 Process.killProcess(app.pid);
9203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009204 }
9205 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009206
Dan Egnorb7f03672009-12-09 16:22:32 -08009207 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009208 long now = SystemClock.uptimeMillis();
9209
9210 Long crashTime = mProcessCrashTimes.get(app.info.processName,
9211 app.info.uid);
9212 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
9213 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08009214 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009216 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217 app.info.processName, app.info.uid);
9218 killServicesLocked(app, false);
9219 for (int i=mHistory.size()-1; i>=0; i--) {
9220 HistoryRecord r = (HistoryRecord)mHistory.get(i);
9221 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009222 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009223 + r.intent.getComponent().flattenToShortString());
9224 finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
9225 }
9226 }
9227 if (!app.persistent) {
9228 // We don't want to start this process again until the user
9229 // explicitly does so... but for persistent process, we really
9230 // need to keep it running. If a persistent process is actually
9231 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08009232 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009233 app.info.processName);
9234 mBadProcesses.put(app.info.processName, app.info.uid, now);
9235 app.bad = true;
9236 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
9237 app.removed = true;
9238 removeProcessLocked(app, false);
9239 return false;
9240 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07009241 } else {
9242 HistoryRecord r = topRunningActivityLocked(null);
9243 if (r.app == app) {
9244 // If the top running activity is from this crashing
9245 // process, then terminate it to avoid getting in a loop.
9246 Slog.w(TAG, " Force finishing activity "
9247 + r.intent.getComponent().flattenToShortString());
9248 int index = indexOfTokenLocked(r);
9249 finishActivityLocked(r, index,
9250 Activity.RESULT_CANCELED, null, "crashed");
9251 // Also terminate an activities below it that aren't yet
9252 // stopped, to avoid a situation where one will get
9253 // re-start our crashing activity once it gets resumed again.
9254 index--;
9255 if (index >= 0) {
9256 r = (HistoryRecord)mHistory.get(index);
9257 if (r.state == ActivityState.RESUMED
9258 || r.state == ActivityState.PAUSING
9259 || r.state == ActivityState.PAUSED) {
9260 if (!r.isHomeActivity) {
9261 Slog.w(TAG, " Force finishing activity "
9262 + r.intent.getComponent().flattenToShortString());
9263 finishActivityLocked(r, index,
9264 Activity.RESULT_CANCELED, null, "crashed");
9265 }
9266 }
9267 }
9268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009269 }
9270
9271 // Bump up the crash count of any services currently running in the proc.
9272 if (app.services.size() != 0) {
9273 // Any services running in the application need to be placed
9274 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009275 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009276 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009277 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 sr.crashCount++;
9279 }
9280 }
9281
9282 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
9283 return true;
9284 }
9285
9286 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009287 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
9288 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009289 skipCurrentReceiverLocked(app);
9290 }
9291
9292 void skipCurrentReceiverLocked(ProcessRecord app) {
9293 boolean reschedule = false;
9294 BroadcastRecord r = app.curReceiver;
9295 if (r != null) {
9296 // The current broadcast is waiting for this app's receiver
9297 // to be finished. Looks like that's not going to happen, so
9298 // let the broadcast continue.
9299 logBroadcastReceiverDiscard(r);
9300 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9301 r.resultExtras, r.resultAbort, true);
9302 reschedule = true;
9303 }
9304 r = mPendingBroadcast;
9305 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009306 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009307 "skip & discard pending app " + r);
9308 logBroadcastReceiverDiscard(r);
9309 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
9310 r.resultExtras, r.resultAbort, true);
9311 reschedule = true;
9312 }
9313 if (reschedule) {
9314 scheduleBroadcastsLocked();
9315 }
9316 }
9317
Dan Egnor60d87622009-12-16 16:32:58 -08009318 /**
9319 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
9320 * The application process will exit immediately after this call returns.
9321 * @param app object of the crashing app, null for the system server
9322 * @param crashInfo describing the exception
9323 */
9324 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9325 ProcessRecord r = findAppProcess(app);
9326
9327 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
9328 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009329 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009330 crashInfo.exceptionClassName,
9331 crashInfo.exceptionMessage,
9332 crashInfo.throwFileName,
9333 crashInfo.throwLineNumber);
9334
Dan Egnor42471dd2010-01-07 17:25:22 -08009335 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009336
9337 crashApplication(r, crashInfo);
9338 }
9339
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07009340 public void handleApplicationStrictModeViolation(
9341 IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
9342 ProcessRecord r = findAppProcess(app);
9343 // TODO: implement
9344 Log.w(TAG, "handleApplicationStrictModeViolation.");
9345
9346 AppErrorResult result = new AppErrorResult();
9347 synchronized (this) {
9348 final long origId = Binder.clearCallingIdentity();
9349
9350 Message msg = Message.obtain();
9351 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
9352 HashMap<String, Object> data = new HashMap<String, Object>();
9353 data.put("result", result);
9354 data.put("app", r);
9355 msg.obj = data;
9356 mHandler.sendMessage(msg);
9357
9358 Binder.restoreCallingIdentity(origId);
9359 }
9360 int res = result.get();
9361 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
9362 }
9363
Dan Egnor60d87622009-12-16 16:32:58 -08009364 /**
9365 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
9366 * @param app object of the crashing app, null for the system server
9367 * @param tag reported by the caller
9368 * @param crashInfo describing the context of the error
9369 * @return true if the process should exit immediately (WTF is fatal)
9370 */
9371 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08009372 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08009373 ProcessRecord r = findAppProcess(app);
9374
9375 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
9376 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08009377 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08009378 tag, crashInfo.exceptionMessage);
9379
Dan Egnor42471dd2010-01-07 17:25:22 -08009380 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08009381
Doug Zongker43866e02010-01-07 12:09:54 -08009382 if (Settings.Secure.getInt(mContext.getContentResolver(),
9383 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08009384 crashApplication(r, crashInfo);
9385 return true;
9386 } else {
9387 return false;
9388 }
9389 }
9390
9391 /**
9392 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
9393 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
9394 */
9395 private ProcessRecord findAppProcess(IBinder app) {
9396 if (app == null) {
9397 return null;
9398 }
9399
9400 synchronized (this) {
9401 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
9402 final int NA = apps.size();
9403 for (int ia=0; ia<NA; ia++) {
9404 ProcessRecord p = apps.valueAt(ia);
9405 if (p.thread != null && p.thread.asBinder() == app) {
9406 return p;
9407 }
9408 }
9409 }
9410
Joe Onorato8a9b2202010-02-26 18:56:32 -08009411 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08009412 return null;
9413 }
9414 }
9415
9416 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08009417 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08009418 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08009419 * @param process which caused the error, null means the system server
9420 * @param activity which triggered the error, null if unknown
9421 * @param parent activity related to the error, null if unknown
9422 * @param subject line related to the error, null if absent
9423 * @param report in long form describing the error, null if absent
9424 * @param logFile to include in the report, null if none
9425 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08009426 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009427 public void addErrorToDropBox(String eventType,
Dan Egnora455d192010-03-12 08:52:28 -08009428 ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
9429 final String report, final File logFile,
9430 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08009431 // NOTE -- this must never acquire the ActivityManagerService lock,
9432 // otherwise the watchdog may be prevented from resetting the system.
9433
Dan Egnora455d192010-03-12 08:52:28 -08009434 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08009435 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08009436 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08009437 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08009438 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009439 } else {
Dan Egnora455d192010-03-12 08:52:28 -08009440 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08009441 }
9442
Dan Egnora455d192010-03-12 08:52:28 -08009443 final String dropboxTag = prefix + eventType;
9444 final DropBoxManager dbox = (DropBoxManager)
9445 mContext.getSystemService(Context.DROPBOX_SERVICE);
9446
9447 // Exit early if the dropbox isn't configured to accept this report type.
9448 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
9449
9450 final StringBuilder sb = new StringBuilder(1024);
9451 if (process == null || process.pid == MY_PID) {
9452 sb.append("Process: system_server\n");
9453 } else {
9454 sb.append("Process: ").append(process.processName).append("\n");
9455 }
9456 if (process != null) {
9457 int flags = process.info.flags;
9458 IPackageManager pm = ActivityThread.getPackageManager();
9459 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
9460 for (String pkg : process.pkgList) {
9461 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08009462 try {
Dan Egnora455d192010-03-12 08:52:28 -08009463 PackageInfo pi = pm.getPackageInfo(pkg, 0);
9464 if (pi != null) {
9465 sb.append(" v").append(pi.versionCode);
9466 if (pi.versionName != null) {
9467 sb.append(" (").append(pi.versionName).append(")");
9468 }
9469 }
9470 } catch (RemoteException e) {
9471 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08009472 }
Dan Egnora455d192010-03-12 08:52:28 -08009473 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08009474 }
Dan Egnora455d192010-03-12 08:52:28 -08009475 }
9476 if (activity != null) {
9477 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
9478 }
9479 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
9480 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
9481 }
9482 if (parent != null && parent != activity) {
9483 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
9484 }
9485 if (subject != null) {
9486 sb.append("Subject: ").append(subject).append("\n");
9487 }
9488 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
9489 sb.append("\n");
9490
9491 // Do the rest in a worker thread to avoid blocking the caller on I/O
9492 // (After this point, we shouldn't access AMS internal data structures.)
9493 Thread worker = new Thread("Error dump: " + dropboxTag) {
9494 @Override
9495 public void run() {
9496 if (report != null) {
9497 sb.append(report);
9498 }
9499 if (logFile != null) {
9500 try {
9501 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
9502 } catch (IOException e) {
9503 Slog.e(TAG, "Error reading " + logFile, e);
9504 }
9505 }
9506 if (crashInfo != null && crashInfo.stackTrace != null) {
9507 sb.append(crashInfo.stackTrace);
9508 }
9509
9510 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
9511 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
9512 if (lines > 0) {
9513 sb.append("\n");
9514
9515 // Merge several logcat streams, and take the last N lines
9516 InputStreamReader input = null;
9517 try {
9518 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
9519 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
9520 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
9521
9522 try { logcat.getOutputStream().close(); } catch (IOException e) {}
9523 try { logcat.getErrorStream().close(); } catch (IOException e) {}
9524 input = new InputStreamReader(logcat.getInputStream());
9525
9526 int num;
9527 char[] buf = new char[8192];
9528 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
9529 } catch (IOException e) {
9530 Slog.e(TAG, "Error running logcat", e);
9531 } finally {
9532 if (input != null) try { input.close(); } catch (IOException e) {}
9533 }
9534 }
9535
9536 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08009537 }
Dan Egnora455d192010-03-12 08:52:28 -08009538 };
9539
9540 if (process == null || process.pid == MY_PID) {
9541 worker.run(); // We may be about to die -- need to run this synchronously
9542 } else {
9543 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08009544 }
9545 }
9546
9547 /**
9548 * Bring up the "unexpected error" dialog box for a crashing app.
9549 * Deal with edge cases (intercepts from instrumented applications,
9550 * ActivityController, error intent receivers, that sort of thing).
9551 * @param r the application crashing
9552 * @param crashInfo describing the failure
9553 */
9554 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009555 long timeMillis = System.currentTimeMillis();
9556 String shortMsg = crashInfo.exceptionClassName;
9557 String longMsg = crashInfo.exceptionMessage;
9558 String stackTrace = crashInfo.stackTrace;
9559 if (shortMsg != null && longMsg != null) {
9560 longMsg = shortMsg + ": " + longMsg;
9561 } else if (shortMsg != null) {
9562 longMsg = shortMsg;
9563 }
9564
Dan Egnor60d87622009-12-16 16:32:58 -08009565 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009566 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009567 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009568 try {
9569 String name = r != null ? r.processName : null;
9570 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08009571 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08009572 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009573 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009574 + " at watcher's request");
9575 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08009576 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577 }
9578 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07009579 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009580 }
9581 }
9582
9583 final long origId = Binder.clearCallingIdentity();
9584
9585 // If this process is running instrumentation, finish it.
9586 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009587 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009588 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08009589 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
9590 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009591 Bundle info = new Bundle();
9592 info.putString("shortMsg", shortMsg);
9593 info.putString("longMsg", longMsg);
9594 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
9595 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009596 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009597 }
9598
Dan Egnor60d87622009-12-16 16:32:58 -08009599 // If we can't identify the process or it's already exceeded its crash quota,
9600 // quit right away without showing a crash dialog.
9601 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009602 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08009603 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009604 }
9605
9606 Message msg = Message.obtain();
9607 msg.what = SHOW_ERROR_MSG;
9608 HashMap data = new HashMap();
9609 data.put("result", result);
9610 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009611 msg.obj = data;
9612 mHandler.sendMessage(msg);
9613
9614 Binder.restoreCallingIdentity(origId);
9615 }
9616
9617 int res = result.get();
9618
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009619 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009620 synchronized (this) {
9621 if (r != null) {
9622 mProcessCrashTimes.put(r.info.processName, r.info.uid,
9623 SystemClock.uptimeMillis());
9624 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009625 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08009626 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009627 }
9628 }
9629
9630 if (appErrorIntent != null) {
9631 try {
9632 mContext.startActivity(appErrorIntent);
9633 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009634 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009637 }
Dan Egnorb7f03672009-12-09 16:22:32 -08009638
9639 Intent createAppErrorIntentLocked(ProcessRecord r,
9640 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
9641 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009642 if (report == null) {
9643 return null;
9644 }
9645 Intent result = new Intent(Intent.ACTION_APP_ERROR);
9646 result.setComponent(r.errorReportReceiver);
9647 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
9648 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9649 return result;
9650 }
9651
Dan Egnorb7f03672009-12-09 16:22:32 -08009652 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
9653 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009654 if (r.errorReportReceiver == null) {
9655 return null;
9656 }
9657
9658 if (!r.crashing && !r.notResponding) {
9659 return null;
9660 }
9661
Dan Egnorb7f03672009-12-09 16:22:32 -08009662 ApplicationErrorReport report = new ApplicationErrorReport();
9663 report.packageName = r.info.packageName;
9664 report.installerPackageName = r.errorReportReceiver.getPackageName();
9665 report.processName = r.processName;
9666 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01009667 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009668
Dan Egnorb7f03672009-12-09 16:22:32 -08009669 if (r.crashing) {
9670 report.type = ApplicationErrorReport.TYPE_CRASH;
9671 report.crashInfo = crashInfo;
9672 } else if (r.notResponding) {
9673 report.type = ApplicationErrorReport.TYPE_ANR;
9674 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009675
Dan Egnorb7f03672009-12-09 16:22:32 -08009676 report.anrInfo.activity = r.notRespondingReport.tag;
9677 report.anrInfo.cause = r.notRespondingReport.shortMsg;
9678 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009679 }
9680
Dan Egnorb7f03672009-12-09 16:22:32 -08009681 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02009682 }
9683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009684 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
9685 // assume our apps are happy - lazy create the list
9686 List<ActivityManager.ProcessErrorStateInfo> errList = null;
9687
9688 synchronized (this) {
9689
9690 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009691 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9692 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009693 if ((app.thread != null) && (app.crashing || app.notResponding)) {
9694 // This one's in trouble, so we'll generate a report for it
9695 // crashes are higher priority (in case there's a crash *and* an anr)
9696 ActivityManager.ProcessErrorStateInfo report = null;
9697 if (app.crashing) {
9698 report = app.crashingReport;
9699 } else if (app.notResponding) {
9700 report = app.notRespondingReport;
9701 }
9702
9703 if (report != null) {
9704 if (errList == null) {
9705 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
9706 }
9707 errList.add(report);
9708 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009709 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009710 " crashing = " + app.crashing +
9711 " notResponding = " + app.notResponding);
9712 }
9713 }
9714 }
9715 }
9716
9717 return errList;
9718 }
9719
9720 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
9721 // Lazy instantiation of list
9722 List<ActivityManager.RunningAppProcessInfo> runList = null;
9723 synchronized (this) {
9724 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009725 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9726 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009727 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
9728 // Generate process state info for running application
9729 ActivityManager.RunningAppProcessInfo currApp =
9730 new ActivityManager.RunningAppProcessInfo(app.processName,
9731 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07009732 currApp.uid = app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009733 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009734 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009735 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
9736 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
9737 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08009738 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
9739 } else if (adj >= HOME_APP_ADJ) {
9740 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
9741 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009742 } else if (adj >= SECONDARY_SERVER_ADJ) {
9743 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
9744 } else if (adj >= VISIBLE_APP_ADJ) {
9745 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009746 } else if (app == mHeavyWeightProcess) {
9747 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009748 } else {
9749 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
9750 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009751 currApp.importanceReasonCode = app.adjTypeCode;
9752 if (app.adjSource instanceof ProcessRecord) {
9753 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
9754 } else if (app.adjSource instanceof HistoryRecord) {
9755 HistoryRecord r = (HistoryRecord)app.adjSource;
9756 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
9757 }
9758 if (app.adjTarget instanceof ComponentName) {
9759 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
9760 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009761 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 // + " lru=" + currApp.lru);
9763 if (runList == null) {
9764 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
9765 }
9766 runList.add(currApp);
9767 }
9768 }
9769 }
9770 return runList;
9771 }
9772
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009773 public List<ApplicationInfo> getRunningExternalApplications() {
9774 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
9775 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
9776 if (runningApps != null && runningApps.size() > 0) {
9777 Set<String> extList = new HashSet<String>();
9778 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
9779 if (app.pkgList != null) {
9780 for (String pkg : app.pkgList) {
9781 extList.add(pkg);
9782 }
9783 }
9784 }
9785 IPackageManager pm = ActivityThread.getPackageManager();
9786 for (String pkg : extList) {
9787 try {
9788 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
9789 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
9790 retList.add(info);
9791 }
9792 } catch (RemoteException e) {
9793 }
9794 }
9795 }
9796 return retList;
9797 }
9798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009799 @Override
9800 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009801 if (checkCallingPermission(android.Manifest.permission.DUMP)
9802 != PackageManager.PERMISSION_GRANTED) {
9803 pw.println("Permission Denial: can't dump ActivityManager from from pid="
9804 + Binder.getCallingPid()
9805 + ", uid=" + Binder.getCallingUid()
9806 + " without permission "
9807 + android.Manifest.permission.DUMP);
9808 return;
9809 }
9810
9811 boolean dumpAll = false;
9812
9813 int opti = 0;
9814 while (opti < args.length) {
9815 String opt = args[opti];
9816 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9817 break;
9818 }
9819 opti++;
9820 if ("-a".equals(opt)) {
9821 dumpAll = true;
9822 } else if ("-h".equals(opt)) {
9823 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009824 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009825 pw.println(" cmd may be one of:");
9826 pw.println(" activities: activity stack state");
9827 pw.println(" broadcasts: broadcast state");
9828 pw.println(" intents: pending intent state");
9829 pw.println(" processes: process state");
9830 pw.println(" providers: content provider state");
9831 pw.println(" services: service state");
9832 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009834 } else {
9835 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009836 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009837 }
9838
9839 // Is the caller requesting to dump a particular piece of data?
9840 if (opti < args.length) {
9841 String cmd = args[opti];
9842 opti++;
9843 if ("activities".equals(cmd) || "a".equals(cmd)) {
9844 synchronized (this) {
9845 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009846 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009847 return;
9848 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
9849 synchronized (this) {
9850 dumpBroadcastsLocked(fd, pw, args, opti, true);
9851 }
9852 return;
9853 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
9854 synchronized (this) {
9855 dumpPendingIntentsLocked(fd, pw, args, opti, true);
9856 }
9857 return;
9858 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
9859 synchronized (this) {
9860 dumpProcessesLocked(fd, pw, args, opti, true);
9861 }
9862 return;
9863 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
9864 synchronized (this) {
9865 dumpProvidersLocked(fd, pw, args, opti, true);
9866 }
9867 return;
9868 } else if ("service".equals(cmd)) {
9869 dumpService(fd, pw, args, opti, true);
9870 return;
9871 } else if ("services".equals(cmd) || "s".equals(cmd)) {
9872 synchronized (this) {
9873 dumpServicesLocked(fd, pw, args, opti, true);
9874 }
9875 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009876 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009877 }
9878
9879 // No piece of data specified, dump everything.
9880 synchronized (this) {
9881 boolean needSep;
9882 if (dumpAll) {
9883 pw.println("Providers in Current Activity Manager State:");
9884 }
9885 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
9886 if (needSep) {
9887 pw.println(" ");
9888 }
9889 if (dumpAll) {
9890 pw.println("-------------------------------------------------------------------------------");
9891 pw.println("Broadcasts in Current Activity Manager State:");
9892 }
9893 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
9894 if (needSep) {
9895 pw.println(" ");
9896 }
9897 if (dumpAll) {
9898 pw.println("-------------------------------------------------------------------------------");
9899 pw.println("Services in Current Activity Manager State:");
9900 }
9901 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
9902 if (needSep) {
9903 pw.println(" ");
9904 }
9905 if (dumpAll) {
9906 pw.println("-------------------------------------------------------------------------------");
9907 pw.println("PendingIntents in Current Activity Manager State:");
9908 }
9909 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
9910 if (needSep) {
9911 pw.println(" ");
9912 }
9913 if (dumpAll) {
9914 pw.println("-------------------------------------------------------------------------------");
9915 pw.println("Activities in Current Activity Manager State:");
9916 }
9917 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
9918 if (needSep) {
9919 pw.println(" ");
9920 }
9921 if (dumpAll) {
9922 pw.println("-------------------------------------------------------------------------------");
9923 pw.println("Processes in Current Activity Manager State:");
9924 }
9925 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
9926 }
9927 }
9928
9929 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9930 int opti, boolean dumpAll, boolean needHeader) {
9931 if (needHeader) {
9932 pw.println(" Activity stack:");
9933 }
9934 dumpHistoryList(pw, mHistory, " ", "Hist", true);
9935 pw.println(" ");
9936 pw.println(" Running activities (most recent first):");
9937 dumpHistoryList(pw, mLRUActivities, " ", "Run", false);
9938 if (mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009939 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009940 pw.println(" Activities waiting for another to become visible:");
9941 dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Wait", false);
9942 }
9943 if (mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009944 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009945 pw.println(" Activities waiting to stop:");
9946 dumpHistoryList(pw, mStoppingActivities, " ", "Stop", false);
9947 }
9948 if (mFinishingActivities.size() > 0) {
9949 pw.println(" ");
9950 pw.println(" Activities waiting to finish:");
9951 dumpHistoryList(pw, mFinishingActivities, " ", "Fin", false);
9952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009953
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009954 pw.println(" ");
9955 pw.println(" mPausingActivity: " + mPausingActivity);
9956 pw.println(" mResumedActivity: " + mResumedActivity);
9957 pw.println(" mFocusedActivity: " + mFocusedActivity);
9958 pw.println(" mLastPausedActivity: " + mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009959
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009960 if (dumpAll && mRecentTasks.size() > 0) {
9961 pw.println(" ");
9962 pw.println("Recent tasks in Current Activity Manager State:");
9963
9964 final int N = mRecentTasks.size();
9965 for (int i=0; i<N; i++) {
9966 TaskRecord tr = mRecentTasks.get(i);
9967 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
9968 pw.println(tr);
9969 mRecentTasks.get(i).dump(pw, " ");
9970 }
9971 }
9972
9973 pw.println(" ");
9974 pw.println(" mCurTask: " + mCurTask);
9975
9976 return true;
9977 }
9978
9979 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
9980 int opti, boolean dumpAll) {
9981 boolean needSep = false;
9982 int numPers = 0;
9983
9984 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009985 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
9986 final int NA = procs.size();
9987 for (int ia=0; ia<NA; ia++) {
9988 if (!needSep) {
9989 pw.println(" All known processes:");
9990 needSep = true;
9991 }
9992 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009993 pw.print(r.persistent ? " *PERS*" : " *APP*");
9994 pw.print(" UID "); pw.print(procs.keyAt(ia));
9995 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009996 r.dump(pw, " ");
9997 if (r.persistent) {
9998 numPers++;
9999 }
10000 }
10001 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010002 }
10003
10004 if (mLruProcesses.size() > 0) {
10005 if (needSep) pw.println(" ");
10006 needSep = true;
10007 pw.println(" Running processes (most recent first):");
10008 dumpProcessList(pw, this, mLruProcesses, " ",
10009 "App ", "PERS", true);
10010 needSep = true;
10011 }
10012
10013 synchronized (mPidsSelfLocked) {
10014 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010015 if (needSep) pw.println(" ");
10016 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010017 pw.println(" PID mappings:");
10018 for (int i=0; i<mPidsSelfLocked.size(); i++) {
10019 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
10020 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010021 }
10022 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010023 }
10024
10025 if (mForegroundProcesses.size() > 0) {
10026 if (needSep) pw.println(" ");
10027 needSep = true;
10028 pw.println(" Foreground Processes:");
10029 for (int i=0; i<mForegroundProcesses.size(); i++) {
10030 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
10031 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010033 }
10034
10035 if (mPersistentStartingProcesses.size() > 0) {
10036 if (needSep) pw.println(" ");
10037 needSep = true;
10038 pw.println(" Persisent processes that are starting:");
10039 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
10040 "Starting Norm", "Restarting PERS", false);
10041 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010042
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010043 if (mStartingProcesses.size() > 0) {
10044 if (needSep) pw.println(" ");
10045 needSep = true;
10046 pw.println(" Processes that are starting:");
10047 dumpProcessList(pw, this, mStartingProcesses, " ",
10048 "Starting Norm", "Starting PERS", false);
10049 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010050
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010051 if (mRemovedProcesses.size() > 0) {
10052 if (needSep) pw.println(" ");
10053 needSep = true;
10054 pw.println(" Processes that are being removed:");
10055 dumpProcessList(pw, this, mRemovedProcesses, " ",
10056 "Removed Norm", "Removed PERS", false);
10057 }
10058
10059 if (mProcessesOnHold.size() > 0) {
10060 if (needSep) pw.println(" ");
10061 needSep = true;
10062 pw.println(" Processes that are on old until the system is ready:");
10063 dumpProcessList(pw, this, mProcessesOnHold, " ",
10064 "OnHold Norm", "OnHold PERS", false);
10065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010067 if (mProcessesToGc.size() > 0) {
10068 if (needSep) pw.println(" ");
10069 needSep = true;
10070 pw.println(" Processes that are waiting to GC:");
10071 long now = SystemClock.uptimeMillis();
10072 for (int i=0; i<mProcessesToGc.size(); i++) {
10073 ProcessRecord proc = mProcessesToGc.get(i);
10074 pw.print(" Process "); pw.println(proc);
10075 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
10076 pw.print(", last gced=");
10077 pw.print(now-proc.lastRequestedGc);
10078 pw.print(" ms ago, last lowMem=");
10079 pw.print(now-proc.lastLowMemory);
10080 pw.println(" ms ago");
10081
10082 }
10083 }
10084
10085 if (mProcessCrashTimes.getMap().size() > 0) {
10086 if (needSep) pw.println(" ");
10087 needSep = true;
10088 pw.println(" Time since processes crashed:");
10089 long now = SystemClock.uptimeMillis();
10090 for (Map.Entry<String, SparseArray<Long>> procs
10091 : mProcessCrashTimes.getMap().entrySet()) {
10092 SparseArray<Long> uids = procs.getValue();
10093 final int N = uids.size();
10094 for (int i=0; i<N; i++) {
10095 pw.print(" Process "); pw.print(procs.getKey());
10096 pw.print(" uid "); pw.print(uids.keyAt(i));
10097 pw.print(": last crashed ");
10098 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010099 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010100 }
10101 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010103
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010104 if (mBadProcesses.getMap().size() > 0) {
10105 if (needSep) pw.println(" ");
10106 needSep = true;
10107 pw.println(" Bad processes:");
10108 for (Map.Entry<String, SparseArray<Long>> procs
10109 : mBadProcesses.getMap().entrySet()) {
10110 SparseArray<Long> uids = procs.getValue();
10111 final int N = uids.size();
10112 for (int i=0; i<N; i++) {
10113 pw.print(" Bad process "); pw.print(procs.getKey());
10114 pw.print(" uid "); pw.print(uids.keyAt(i));
10115 pw.print(": crashed at time ");
10116 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010117 }
10118 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010120
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010121 pw.println(" ");
10122 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010123 if (mHeavyWeightProcess != null) {
10124 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
10125 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010126 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackbornd49258f2010-03-26 00:44:29 -070010127 pw.println(" mConfigWillChange: " + mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010128 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
10129 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
10130 || mOrigWaitForDebugger) {
10131 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
10132 + " mDebugTransient=" + mDebugTransient
10133 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
10134 }
10135 if (mAlwaysFinishActivities || mController != null) {
10136 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
10137 + " mController=" + mController);
10138 }
10139 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010141 pw.println(" mStartRunning=" + mStartRunning
10142 + " mSystemReady=" + mSystemReady
10143 + " mBooting=" + mBooting
10144 + " mBooted=" + mBooted
10145 + " mFactoryTest=" + mFactoryTest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010146 pw.println(" mGoingToSleep=" + mGoingToSleep);
10147 pw.println(" mLaunchingActivity=" + mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -070010148 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010149 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010150
10151 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010152 }
10153
10154 /**
10155 * There are three ways to call this:
10156 * - no service specified: dump all the services
10157 * - a flattened component name that matched an existing service was specified as the
10158 * first arg: dump that one service
10159 * - the first arg isn't the flattened component name of an existing service:
10160 * dump all services whose component contains the first arg as a substring
10161 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010162 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
10163 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010164 String[] newArgs;
10165 String componentNameString;
10166 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -080010167 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010168 componentNameString = null;
10169 newArgs = EMPTY_STRING_ARRAY;
10170 r = null;
10171 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010172 componentNameString = args[opti];
10173 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010174 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
10175 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010176 newArgs = new String[args.length - opti];
10177 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010178 }
10179
10180 if (r != null) {
10181 dumpService(fd, pw, r, newArgs);
10182 } else {
10183 for (ServiceRecord r1 : mServices.values()) {
10184 if (componentNameString == null
10185 || r1.name.flattenToString().contains(componentNameString)) {
10186 dumpService(fd, pw, r1, newArgs);
10187 }
10188 }
10189 }
10190 }
10191
10192 /**
10193 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
10194 * there is a thread associated with the service.
10195 */
10196 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
10197 pw.println(" Service " + r.name.flattenToString());
10198 if (r.app != null && r.app.thread != null) {
10199 try {
10200 // flush anything that is already in the PrintWriter since the thread is going
10201 // to write to the file descriptor directly
10202 pw.flush();
10203 r.app.thread.dumpService(fd, r, args);
10204 pw.print("\n");
10205 } catch (RemoteException e) {
10206 pw.println("got a RemoteException while dumping the service");
10207 }
10208 }
10209 }
10210
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010211 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10212 int opti, boolean dumpAll) {
10213 boolean needSep = false;
10214
10215 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010216 if (mRegisteredReceivers.size() > 0) {
10217 pw.println(" ");
10218 pw.println(" Registered Receivers:");
10219 Iterator it = mRegisteredReceivers.values().iterator();
10220 while (it.hasNext()) {
10221 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010222 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010223 r.dump(pw, " ");
10224 }
10225 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010227 pw.println(" ");
10228 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010229 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010230 needSep = true;
10231 }
10232
10233 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
10234 || mPendingBroadcast != null) {
10235 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010237 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010239 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10240 pw.println(" Broadcast #" + i + ":");
10241 mParallelBroadcasts.get(i).dump(pw, " ");
10242 }
10243 if (mOrderedBroadcasts.size() > 0) {
10244 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010245 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010246 }
10247 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10248 pw.println(" Serialized Broadcast #" + i + ":");
10249 mOrderedBroadcasts.get(i).dump(pw, " ");
10250 }
10251 pw.println(" ");
10252 pw.println(" Pending broadcast:");
10253 if (mPendingBroadcast != null) {
10254 mPendingBroadcast.dump(pw, " ");
10255 } else {
10256 pw.println(" (null)");
10257 }
10258 needSep = true;
10259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010260
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010261 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -080010263 pw.println(" Historical broadcasts:");
10264 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
10265 BroadcastRecord r = mBroadcastHistory[i];
10266 if (r == null) {
10267 break;
10268 }
10269 pw.println(" Historical Broadcast #" + i + ":");
10270 r.dump(pw, " ");
10271 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010272 needSep = true;
10273 }
10274
10275 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010276 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010277 pw.println(" Sticky broadcasts:");
10278 StringBuilder sb = new StringBuilder(128);
10279 for (Map.Entry<String, ArrayList<Intent>> ent
10280 : mStickyBroadcasts.entrySet()) {
10281 pw.print(" * Sticky action "); pw.print(ent.getKey());
10282 pw.println(":");
10283 ArrayList<Intent> intents = ent.getValue();
10284 final int N = intents.size();
10285 for (int i=0; i<N; i++) {
10286 sb.setLength(0);
10287 sb.append(" Intent: ");
10288 intents.get(i).toShortString(sb, true, false);
10289 pw.println(sb.toString());
10290 Bundle bundle = intents.get(i).getExtras();
10291 if (bundle != null) {
10292 pw.print(" ");
10293 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010294 }
10295 }
10296 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010297 needSep = true;
10298 }
10299
10300 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010302 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010303 pw.println(" mHandler:");
10304 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010305 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010306 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010307
10308 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010309 }
10310
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010311 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10312 int opti, boolean dumpAll) {
10313 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010315 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010316 if (mServices.size() > 0) {
10317 pw.println(" Active services:");
10318 Iterator<ServiceRecord> it = mServices.values().iterator();
10319 while (it.hasNext()) {
10320 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010321 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010322 r.dump(pw, " ");
10323 }
10324 needSep = true;
10325 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010328 if (mPendingServices.size() > 0) {
10329 if (needSep) pw.println(" ");
10330 pw.println(" Pending services:");
10331 for (int i=0; i<mPendingServices.size(); i++) {
10332 ServiceRecord r = mPendingServices.get(i);
10333 pw.print(" * Pending "); pw.println(r);
10334 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010335 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010336 needSep = true;
10337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010339 if (mRestartingServices.size() > 0) {
10340 if (needSep) pw.println(" ");
10341 pw.println(" Restarting services:");
10342 for (int i=0; i<mRestartingServices.size(); i++) {
10343 ServiceRecord r = mRestartingServices.get(i);
10344 pw.print(" * Restarting "); pw.println(r);
10345 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010346 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010347 needSep = true;
10348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010349
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010350 if (mStoppingServices.size() > 0) {
10351 if (needSep) pw.println(" ");
10352 pw.println(" Stopping services:");
10353 for (int i=0; i<mStoppingServices.size(); i++) {
10354 ServiceRecord r = mStoppingServices.get(i);
10355 pw.print(" * Stopping "); pw.println(r);
10356 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010358 needSep = true;
10359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010360
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010361 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010362 if (mServiceConnections.size() > 0) {
10363 if (needSep) pw.println(" ");
10364 pw.println(" Connection bindings to services:");
10365 Iterator<ConnectionRecord> it
10366 = mServiceConnections.values().iterator();
10367 while (it.hasNext()) {
10368 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010369 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370 r.dump(pw, " ");
10371 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010372 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 }
10374 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010375
10376 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010377 }
10378
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010379 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10380 int opti, boolean dumpAll) {
10381 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010382
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010383 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010384 if (mProvidersByClass.size() > 0) {
10385 if (needSep) pw.println(" ");
10386 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010387 Iterator<Map.Entry<String, ContentProviderRecord>> it
10388 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010389 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010390 Map.Entry<String, ContentProviderRecord> e = it.next();
10391 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010392 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010393 r.dump(pw, " ");
10394 }
10395 needSep = true;
10396 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010397
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010398 if (mProvidersByName.size() > 0) {
10399 pw.println(" ");
10400 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -070010401 Iterator<Map.Entry<String, ContentProviderRecord>> it
10402 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010403 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010404 Map.Entry<String, ContentProviderRecord> e = it.next();
10405 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010406 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
10407 pw.println(r);
10408 }
10409 needSep = true;
10410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010411 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010412
10413 if (mLaunchingProviders.size() > 0) {
10414 if (needSep) pw.println(" ");
10415 pw.println(" Launching content providers:");
10416 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
10417 pw.print(" Launching #"); pw.print(i); pw.print(": ");
10418 pw.println(mLaunchingProviders.get(i));
10419 }
10420 needSep = true;
10421 }
10422
10423 if (mGrantedUriPermissions.size() > 0) {
10424 pw.println();
10425 pw.println("Granted Uri Permissions:");
10426 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
10427 int uid = mGrantedUriPermissions.keyAt(i);
10428 HashMap<Uri, UriPermission> perms
10429 = mGrantedUriPermissions.valueAt(i);
10430 pw.print(" * UID "); pw.print(uid);
10431 pw.println(" holds:");
10432 for (UriPermission perm : perms.values()) {
10433 pw.print(" "); pw.println(perm);
10434 perm.dump(pw, " ");
10435 }
10436 }
10437 needSep = true;
10438 }
10439
10440 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010441 }
10442
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010443 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
10444 int opti, boolean dumpAll) {
10445 boolean needSep = false;
10446
10447 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010448 if (this.mIntentSenderRecords.size() > 0) {
10449 Iterator<WeakReference<PendingIntentRecord>> it
10450 = mIntentSenderRecords.values().iterator();
10451 while (it.hasNext()) {
10452 WeakReference<PendingIntentRecord> ref = it.next();
10453 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010454 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010455 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010456 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010457 rec.dump(pw, " ");
10458 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010459 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010460 }
10461 }
10462 }
10463 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -080010464
10465 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010466 }
10467
10468 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010469 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010470 TaskRecord lastTask = null;
10471 for (int i=list.size()-1; i>=0; i--) {
10472 HistoryRecord r = (HistoryRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010473 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010474 if (lastTask != r.task) {
10475 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010476 pw.print(prefix);
10477 pw.print(full ? "* " : " ");
10478 pw.println(lastTask);
10479 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010480 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010482 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010483 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
10484 pw.print(" #"); pw.print(i); pw.print(": ");
10485 pw.println(r);
10486 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010487 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010489 }
10490 }
10491
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010492 private static String buildOomTag(String prefix, String space, int val, int base) {
10493 if (val == base) {
10494 if (space == null) return prefix;
10495 return prefix + " ";
10496 }
10497 return prefix + "+" + Integer.toString(val-base);
10498 }
10499
10500 private static final int dumpProcessList(PrintWriter pw,
10501 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010502 String prefix, String normalLabel, String persistentLabel,
10503 boolean inclOomAdj) {
10504 int numPers = 0;
10505 for (int i=list.size()-1; i>=0; i--) {
10506 ProcessRecord r = (ProcessRecord)list.get(i);
10507 if (false) {
10508 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
10509 + " #" + i + ":");
10510 r.dump(pw, prefix + " ");
10511 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010512 String oomAdj;
10513 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010514 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010515 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010516 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
10517 } else if (r.setAdj >= HOME_APP_ADJ) {
10518 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
10519 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
10520 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
10521 } else if (r.setAdj >= BACKUP_APP_ADJ) {
10522 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
10523 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
10524 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
10525 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
10526 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010527 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010528 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010529 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010530 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010531 } else {
10532 oomAdj = Integer.toString(r.setAdj);
10533 }
10534 String schedGroup;
10535 switch (r.setSchedGroup) {
10536 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
10537 schedGroup = "B";
10538 break;
10539 case Process.THREAD_GROUP_DEFAULT:
10540 schedGroup = "F";
10541 break;
10542 default:
10543 schedGroup = Integer.toString(r.setSchedGroup);
10544 break;
10545 }
10546 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010547 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010548 i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010549 if (r.adjSource != null || r.adjTarget != null) {
10550 pw.println(prefix + " " + r.adjTarget
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010551 + "<=" + r.adjSource);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010553 } else {
10554 pw.println(String.format("%s%s #%2d: %s",
10555 prefix, (r.persistent ? persistentLabel : normalLabel),
10556 i, r.toString()));
10557 }
10558 if (r.persistent) {
10559 numPers++;
10560 }
10561 }
10562 return numPers;
10563 }
10564
Dianne Hackborn472ad872010-04-07 17:31:48 -070010565 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010566 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -070010567 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 long uptime = SystemClock.uptimeMillis();
10569 long realtime = SystemClock.elapsedRealtime();
10570
10571 if (isCheckinRequest) {
10572 // short checkin version
10573 pw.println(uptime + "," + realtime);
10574 pw.flush();
10575 } else {
10576 pw.println("Applications Memory Usage (kB):");
10577 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
10578 }
10579 for (int i = list.size() - 1 ; i >= 0 ; i--) {
10580 ProcessRecord r = (ProcessRecord)list.get(i);
10581 if (r.thread != null) {
10582 if (!isCheckinRequest) {
10583 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
10584 pw.flush();
10585 }
10586 try {
10587 r.thread.asBinder().dump(fd, args);
10588 } catch (RemoteException e) {
10589 if (!isCheckinRequest) {
10590 pw.println("Got RemoteException!");
10591 pw.flush();
10592 }
10593 }
10594 }
10595 }
10596 }
10597
10598 /**
10599 * Searches array of arguments for the specified string
10600 * @param args array of argument strings
10601 * @param value value to search for
10602 * @return true if the value is contained in the array
10603 */
10604 private static boolean scanArgs(String[] args, String value) {
10605 if (args != null) {
10606 for (String arg : args) {
10607 if (value.equals(arg)) {
10608 return true;
10609 }
10610 }
10611 }
10612 return false;
10613 }
10614
Dianne Hackborn75b03852009-06-12 15:43:26 -070010615 private final int indexOfTokenLocked(IBinder token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010616 int count = mHistory.size();
10617
10618 // convert the token to an entry in the history.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010619 int index = -1;
10620 for (int i=count-1; i>=0; i--) {
10621 Object o = mHistory.get(i);
10622 if (o == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010623 index = i;
10624 break;
10625 }
10626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010627
10628 return index;
10629 }
10630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010631 private final void killServicesLocked(ProcessRecord app,
10632 boolean allowRestart) {
10633 // Report disconnected services.
10634 if (false) {
10635 // XXX we are letting the client link to the service for
10636 // death notifications.
10637 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010638 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010639 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010640 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010641 if (r.connections.size() > 0) {
10642 Iterator<ConnectionRecord> jt
10643 = r.connections.values().iterator();
10644 while (jt.hasNext()) {
10645 ConnectionRecord c = jt.next();
10646 if (c.binding.client != app) {
10647 try {
10648 //c.conn.connected(r.className, null);
10649 } catch (Exception e) {
10650 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010651 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 + r.shortName
10653 + " from app " + app.processName, e);
10654 }
10655 }
10656 }
10657 }
10658 }
10659 }
10660 }
10661
10662 // Clean up any connections this application has to other services.
10663 if (app.connections.size() > 0) {
10664 Iterator<ConnectionRecord> it = app.connections.iterator();
10665 while (it.hasNext()) {
10666 ConnectionRecord r = it.next();
10667 removeConnectionLocked(r, app, null);
10668 }
10669 }
10670 app.connections.clear();
10671
10672 if (app.services.size() != 0) {
10673 // Any services running in the application need to be placed
10674 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010675 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010676 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010677 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010678 synchronized (sr.stats.getBatteryStats()) {
10679 sr.stats.stopLaunchedLocked();
10680 }
10681 sr.app = null;
10682 sr.executeNesting = 0;
10683 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010684
10685 boolean hasClients = sr.bindings.size() > 0;
10686 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010687 Iterator<IntentBindRecord> bindings
10688 = sr.bindings.values().iterator();
10689 while (bindings.hasNext()) {
10690 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010691 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010692 + ": shouldUnbind=" + b.hasBound);
10693 b.binder = null;
10694 b.requested = b.received = b.hasBound = false;
10695 }
10696 }
10697
10698 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010699 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010700 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010701 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010702 sr.crashCount, sr.shortName, app.pid);
10703 bringDownServiceLocked(sr, true);
10704 } else if (!allowRestart) {
10705 bringDownServiceLocked(sr, true);
10706 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010707 boolean canceled = scheduleServiceRestartLocked(sr, true);
10708
10709 // Should the service remain running? Note that in the
10710 // extreme case of so many attempts to deliver a command
10711 // that it failed, that we also will stop it here.
10712 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10713 if (sr.pendingStarts.size() == 0) {
10714 sr.startRequested = false;
10715 if (!hasClients) {
10716 // Whoops, no reason to restart!
10717 bringDownServiceLocked(sr, true);
10718 }
10719 }
10720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010721 }
10722 }
10723
10724 if (!allowRestart) {
10725 app.services.clear();
10726 }
10727 }
10728
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010729 // Make sure we have no more records on the stopping list.
10730 int i = mStoppingServices.size();
10731 while (i > 0) {
10732 i--;
10733 ServiceRecord sr = mStoppingServices.get(i);
10734 if (sr.app == app) {
10735 mStoppingServices.remove(i);
10736 }
10737 }
10738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010739 app.executingServices.clear();
10740 }
10741
10742 private final void removeDyingProviderLocked(ProcessRecord proc,
10743 ContentProviderRecord cpr) {
10744 synchronized (cpr) {
10745 cpr.launchingApp = null;
10746 cpr.notifyAll();
10747 }
10748
10749 mProvidersByClass.remove(cpr.info.name);
10750 String names[] = cpr.info.authority.split(";");
10751 for (int j = 0; j < names.length; j++) {
10752 mProvidersByName.remove(names[j]);
10753 }
10754
10755 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10756 while (cit.hasNext()) {
10757 ProcessRecord capp = cit.next();
10758 if (!capp.persistent && capp.thread != null
10759 && capp.pid != 0
10760 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010761 Slog.i(TAG, "Kill " + capp.processName
10762 + " (pid " + capp.pid + "): provider " + cpr.info.name
10763 + " in dying process " + proc.processName);
10764 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
10765 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010766 Process.killProcess(capp.pid);
10767 }
10768 }
10769
10770 mLaunchingProviders.remove(cpr);
10771 }
10772
10773 /**
10774 * Main code for cleaning up a process when it has gone away. This is
10775 * called both as a result of the process dying, or directly when stopping
10776 * a process when running in single process mode.
10777 */
10778 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
10779 boolean restarting, int index) {
10780 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010781 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 }
10783
Dianne Hackborn36124872009-10-08 16:22:03 -070010784 mProcessesToGc.remove(app);
10785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010786 // Dismiss any open dialogs.
10787 if (app.crashDialog != null) {
10788 app.crashDialog.dismiss();
10789 app.crashDialog = null;
10790 }
10791 if (app.anrDialog != null) {
10792 app.anrDialog.dismiss();
10793 app.anrDialog = null;
10794 }
10795 if (app.waitDialog != null) {
10796 app.waitDialog.dismiss();
10797 app.waitDialog = null;
10798 }
10799
10800 app.crashing = false;
10801 app.notResponding = false;
10802
10803 app.resetPackageList();
10804 app.thread = null;
10805 app.forcingToForeground = null;
10806 app.foregroundServices = false;
10807
10808 killServicesLocked(app, true);
10809
10810 boolean restart = false;
10811
10812 int NL = mLaunchingProviders.size();
10813
10814 // Remove published content providers.
10815 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010816 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010818 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010819 cpr.provider = null;
10820 cpr.app = null;
10821
10822 // See if someone is waiting for this provider... in which
10823 // case we don't remove it, but just let it restart.
10824 int i = 0;
10825 if (!app.bad) {
10826 for (; i<NL; i++) {
10827 if (mLaunchingProviders.get(i) == cpr) {
10828 restart = true;
10829 break;
10830 }
10831 }
10832 } else {
10833 i = NL;
10834 }
10835
10836 if (i >= NL) {
10837 removeDyingProviderLocked(app, cpr);
10838 NL = mLaunchingProviders.size();
10839 }
10840 }
10841 app.pubProviders.clear();
10842 }
10843
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010844 // Take care of any launching providers waiting for this process.
10845 if (checkAppInLaunchingProvidersLocked(app, false)) {
10846 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010847 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010849 // Unregister from connected content providers.
10850 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010851 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010852 while (it.hasNext()) {
10853 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10854 cpr.clients.remove(app);
10855 }
10856 app.conProviders.clear();
10857 }
10858
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010859 // At this point there may be remaining entries in mLaunchingProviders
10860 // where we were the only one waiting, so they are no longer of use.
10861 // Look for these and clean up if found.
10862 // XXX Commented out for now. Trying to figure out a way to reproduce
10863 // the actual situation to identify what is actually going on.
10864 if (false) {
10865 for (int i=0; i<NL; i++) {
10866 ContentProviderRecord cpr = (ContentProviderRecord)
10867 mLaunchingProviders.get(i);
10868 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10869 synchronized (cpr) {
10870 cpr.launchingApp = null;
10871 cpr.notifyAll();
10872 }
10873 }
10874 }
10875 }
10876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010877 skipCurrentReceiverLocked(app);
10878
10879 // Unregister any receivers.
10880 if (app.receivers.size() > 0) {
10881 Iterator<ReceiverList> it = app.receivers.iterator();
10882 while (it.hasNext()) {
10883 removeReceiverLocked(it.next());
10884 }
10885 app.receivers.clear();
10886 }
10887
Christopher Tate181fafa2009-05-14 11:12:14 -070010888 // If the app is undergoing backup, tell the backup manager about it
10889 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010890 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010891 try {
10892 IBackupManager bm = IBackupManager.Stub.asInterface(
10893 ServiceManager.getService(Context.BACKUP_SERVICE));
10894 bm.agentDisconnected(app.info.packageName);
10895 } catch (RemoteException e) {
10896 // can't happen; backup manager is local
10897 }
10898 }
10899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010900 // If the caller is restarting this app, then leave it in its
10901 // current lists and let the caller take care of it.
10902 if (restarting) {
10903 return;
10904 }
10905
10906 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010907 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 "Removing non-persistent process during cleanup: " + app);
10909 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010910 if (mHeavyWeightProcess == app) {
10911 mHeavyWeightProcess = null;
10912 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
10913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010914 } else if (!app.removed) {
10915 // This app is persistent, so we need to keep its record around.
10916 // If it is not already on the pending app list, add it there
10917 // and start a new process for it.
10918 app.thread = null;
10919 app.forcingToForeground = null;
10920 app.foregroundServices = false;
10921 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10922 mPersistentStartingProcesses.add(app);
10923 restart = true;
10924 }
10925 }
10926 mProcessesOnHold.remove(app);
10927
The Android Open Source Project4df24232009-03-05 14:34:35 -080010928 if (app == mHomeProcess) {
10929 mHomeProcess = null;
10930 }
10931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010932 if (restart) {
10933 // We have components that still need to be running in the
10934 // process, so re-launch it.
10935 mProcessNames.put(app.processName, app.info.uid, app);
10936 startProcessLocked(app, "restart", app.processName);
10937 } else if (app.pid > 0 && app.pid != MY_PID) {
10938 // Goodbye!
10939 synchronized (mPidsSelfLocked) {
10940 mPidsSelfLocked.remove(app.pid);
10941 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10942 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010943 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010944 }
10945 }
10946
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010947 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10948 // Look through the content providers we are waiting to have launched,
10949 // and if any run in this process then either schedule a restart of
10950 // the process or kill the client waiting for it if this process has
10951 // gone bad.
10952 int NL = mLaunchingProviders.size();
10953 boolean restart = false;
10954 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010955 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010956 if (cpr.launchingApp == app) {
10957 if (!alwaysBad && !app.bad) {
10958 restart = true;
10959 } else {
10960 removeDyingProviderLocked(app, cpr);
10961 NL = mLaunchingProviders.size();
10962 }
10963 }
10964 }
10965 return restart;
10966 }
10967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010968 // =========================================================
10969 // SERVICES
10970 // =========================================================
10971
10972 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10973 ActivityManager.RunningServiceInfo info =
10974 new ActivityManager.RunningServiceInfo();
10975 info.service = r.name;
10976 if (r.app != null) {
10977 info.pid = r.app.pid;
10978 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010979 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 info.process = r.processName;
10981 info.foreground = r.isForeground;
10982 info.activeSince = r.createTime;
10983 info.started = r.startRequested;
10984 info.clientCount = r.connections.size();
10985 info.crashCount = r.crashCount;
10986 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010987 if (r.isForeground) {
10988 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10989 }
10990 if (r.startRequested) {
10991 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10992 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010993 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010994 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10995 }
10996 if (r.app != null && r.app.persistent) {
10997 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10998 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010999 for (ConnectionRecord conn : r.connections.values()) {
11000 if (conn.clientLabel != 0) {
11001 info.clientPackage = conn.binding.client.info.packageName;
11002 info.clientLabel = conn.clientLabel;
11003 break;
11004 }
11005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011006 return info;
11007 }
11008
11009 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
11010 int flags) {
11011 synchronized (this) {
11012 ArrayList<ActivityManager.RunningServiceInfo> res
11013 = new ArrayList<ActivityManager.RunningServiceInfo>();
11014
11015 if (mServices.size() > 0) {
11016 Iterator<ServiceRecord> it = mServices.values().iterator();
11017 while (it.hasNext() && res.size() < maxNum) {
11018 res.add(makeRunningServiceInfoLocked(it.next()));
11019 }
11020 }
11021
11022 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
11023 ServiceRecord r = mRestartingServices.get(i);
11024 ActivityManager.RunningServiceInfo info =
11025 makeRunningServiceInfoLocked(r);
11026 info.restarting = r.nextRestartTime;
11027 res.add(info);
11028 }
11029
11030 return res;
11031 }
11032 }
11033
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011034 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
11035 synchronized (this) {
11036 ServiceRecord r = mServices.get(name);
11037 if (r != null) {
11038 for (ConnectionRecord conn : r.connections.values()) {
11039 if (conn.clientIntent != null) {
11040 return conn.clientIntent;
11041 }
11042 }
11043 }
11044 }
11045 return null;
11046 }
11047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011048 private final ServiceRecord findServiceLocked(ComponentName name,
11049 IBinder token) {
11050 ServiceRecord r = mServices.get(name);
11051 return r == token ? r : null;
11052 }
11053
11054 private final class ServiceLookupResult {
11055 final ServiceRecord record;
11056 final String permission;
11057
11058 ServiceLookupResult(ServiceRecord _record, String _permission) {
11059 record = _record;
11060 permission = _permission;
11061 }
11062 };
11063
11064 private ServiceLookupResult findServiceLocked(Intent service,
11065 String resolvedType) {
11066 ServiceRecord r = null;
11067 if (service.getComponent() != null) {
11068 r = mServices.get(service.getComponent());
11069 }
11070 if (r == null) {
11071 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11072 r = mServicesByIntent.get(filter);
11073 }
11074
11075 if (r == null) {
11076 try {
11077 ResolveInfo rInfo =
11078 ActivityThread.getPackageManager().resolveService(
11079 service, resolvedType, 0);
11080 ServiceInfo sInfo =
11081 rInfo != null ? rInfo.serviceInfo : null;
11082 if (sInfo == null) {
11083 return null;
11084 }
11085
11086 ComponentName name = new ComponentName(
11087 sInfo.applicationInfo.packageName, sInfo.name);
11088 r = mServices.get(name);
11089 } catch (RemoteException ex) {
11090 // pm is in same process, this will never happen.
11091 }
11092 }
11093 if (r != null) {
11094 int callingPid = Binder.getCallingPid();
11095 int callingUid = Binder.getCallingUid();
11096 if (checkComponentPermission(r.permission,
11097 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11098 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011099 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011100 + " from pid=" + callingPid
11101 + ", uid=" + callingUid
11102 + " requires " + r.permission);
11103 return new ServiceLookupResult(null, r.permission);
11104 }
11105 return new ServiceLookupResult(r, null);
11106 }
11107 return null;
11108 }
11109
11110 private class ServiceRestarter implements Runnable {
11111 private ServiceRecord mService;
11112
11113 void setService(ServiceRecord service) {
11114 mService = service;
11115 }
11116
11117 public void run() {
11118 synchronized(ActivityManagerService.this) {
11119 performServiceRestartLocked(mService);
11120 }
11121 }
11122 }
11123
11124 private ServiceLookupResult retrieveServiceLocked(Intent service,
11125 String resolvedType, int callingPid, int callingUid) {
11126 ServiceRecord r = null;
11127 if (service.getComponent() != null) {
11128 r = mServices.get(service.getComponent());
11129 }
11130 Intent.FilterComparison filter = new Intent.FilterComparison(service);
11131 r = mServicesByIntent.get(filter);
11132 if (r == null) {
11133 try {
11134 ResolveInfo rInfo =
11135 ActivityThread.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011136 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011137 ServiceInfo sInfo =
11138 rInfo != null ? rInfo.serviceInfo : null;
11139 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011140 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011141 ": not found");
11142 return null;
11143 }
11144
11145 ComponentName name = new ComponentName(
11146 sInfo.applicationInfo.packageName, sInfo.name);
11147 r = mServices.get(name);
11148 if (r == null) {
11149 filter = new Intent.FilterComparison(service.cloneFilter());
11150 ServiceRestarter res = new ServiceRestarter();
11151 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11152 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11153 synchronized (stats) {
11154 ss = stats.getServiceStatsLocked(
11155 sInfo.applicationInfo.uid, sInfo.packageName,
11156 sInfo.name);
11157 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080011158 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011159 res.setService(r);
11160 mServices.put(name, r);
11161 mServicesByIntent.put(filter, r);
11162
11163 // Make sure this component isn't in the pending list.
11164 int N = mPendingServices.size();
11165 for (int i=0; i<N; i++) {
11166 ServiceRecord pr = mPendingServices.get(i);
11167 if (pr.name.equals(name)) {
11168 mPendingServices.remove(i);
11169 i--;
11170 N--;
11171 }
11172 }
11173 }
11174 } catch (RemoteException ex) {
11175 // pm is in same process, this will never happen.
11176 }
11177 }
11178 if (r != null) {
11179 if (checkComponentPermission(r.permission,
11180 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
11181 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011182 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011183 + " from pid=" + Binder.getCallingPid()
11184 + ", uid=" + Binder.getCallingUid()
11185 + " requires " + r.permission);
11186 return new ServiceLookupResult(null, r.permission);
11187 }
11188 return new ServiceLookupResult(r, null);
11189 }
11190 return null;
11191 }
11192
11193 private final void bumpServiceExecutingLocked(ServiceRecord r) {
11194 long now = SystemClock.uptimeMillis();
11195 if (r.executeNesting == 0 && r.app != null) {
11196 if (r.app.executingServices.size() == 0) {
11197 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11198 msg.obj = r.app;
11199 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
11200 }
11201 r.app.executingServices.add(r);
11202 }
11203 r.executeNesting++;
11204 r.executingStart = now;
11205 }
11206
11207 private final void sendServiceArgsLocked(ServiceRecord r,
11208 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011209 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 if (N == 0) {
11211 return;
11212 }
11213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 int i = 0;
11215 while (i < N) {
11216 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011217 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011218 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011219 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -070011220 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011221 // If somehow we got a dummy start at the front, then
11222 // just drop it here.
11223 i++;
11224 continue;
11225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011226 bumpServiceExecutingLocked(r);
11227 if (!oomAdjusted) {
11228 oomAdjusted = true;
11229 updateOomAdjLocked(r.app);
11230 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011231 int flags = 0;
11232 if (si.deliveryCount > 0) {
11233 flags |= Service.START_FLAG_RETRY;
11234 }
11235 if (si.doneExecutingCount > 0) {
11236 flags |= Service.START_FLAG_REDELIVERY;
11237 }
11238 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
11239 si.deliveredTime = SystemClock.uptimeMillis();
11240 r.deliveredStarts.add(si);
11241 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011242 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011243 } catch (RemoteException e) {
11244 // Remote process gone... we'll let the normal cleanup take
11245 // care of this.
11246 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011247 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011248 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011249 break;
11250 }
11251 }
11252 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011253 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254 } else {
11255 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011256 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011257 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 }
11259 }
11260 }
11261
11262 private final boolean requestServiceBindingLocked(ServiceRecord r,
11263 IntentBindRecord i, boolean rebind) {
11264 if (r.app == null || r.app.thread == null) {
11265 // If service is not currently running, can't yet bind.
11266 return false;
11267 }
11268 if ((!i.requested || rebind) && i.apps.size() > 0) {
11269 try {
11270 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011271 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 + ": shouldUnbind=" + i.hasBound);
11273 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
11274 if (!rebind) {
11275 i.requested = true;
11276 }
11277 i.hasBound = true;
11278 i.doRebind = false;
11279 } catch (RemoteException e) {
11280 return false;
11281 }
11282 }
11283 return true;
11284 }
11285
11286 private final void requestServiceBindingsLocked(ServiceRecord r) {
11287 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
11288 while (bindings.hasNext()) {
11289 IntentBindRecord i = bindings.next();
11290 if (!requestServiceBindingLocked(r, i, false)) {
11291 break;
11292 }
11293 }
11294 }
11295
11296 private final void realStartServiceLocked(ServiceRecord r,
11297 ProcessRecord app) throws RemoteException {
11298 if (app.thread == null) {
11299 throw new RemoteException();
11300 }
11301
11302 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070011303 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011304
11305 app.services.add(r);
11306 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011307 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011308
11309 boolean created = false;
11310 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011311 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011313 mStringBuilder.setLength(0);
11314 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011315 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011316 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070011317 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011318 synchronized (r.stats.getBatteryStats()) {
11319 r.stats.startLaunchedLocked();
11320 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011321 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011322 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011323 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011324 created = true;
11325 } finally {
11326 if (!created) {
11327 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011328 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 }
11330 }
11331
11332 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011333
11334 // If the service is in the started state, and there are no
11335 // pending arguments, then fake up one so its onStartCommand() will
11336 // be called.
11337 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
11338 r.lastStartId++;
11339 if (r.lastStartId < 1) {
11340 r.lastStartId = 1;
11341 }
11342 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
11343 }
11344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011345 sendServiceArgsLocked(r, true);
11346 }
11347
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011348 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
11349 boolean allowCancel) {
11350 boolean canceled = false;
11351
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011352 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011353 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070011354 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011355
11356 // Any delivered but not yet finished starts should be put back
11357 // on the pending list.
11358 final int N = r.deliveredStarts.size();
11359 if (N > 0) {
11360 for (int i=N-1; i>=0; i--) {
11361 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
11362 if (si.intent == null) {
11363 // We'll generate this again if needed.
11364 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
11365 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
11366 r.pendingStarts.add(0, si);
11367 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
11368 dur *= 2;
11369 if (minDuration < dur) minDuration = dur;
11370 if (resetTime < dur) resetTime = dur;
11371 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011372 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011373 + r.name);
11374 canceled = true;
11375 }
11376 }
11377 r.deliveredStarts.clear();
11378 }
11379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011380 r.totalRestartCount++;
11381 if (r.restartDelay == 0) {
11382 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011383 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384 } else {
11385 // If it has been a "reasonably long time" since the service
11386 // was started, then reset our restart duration back to
11387 // the beginning, so we don't infinitely increase the duration
11388 // on a service that just occasionally gets killed (which is
11389 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011390 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011391 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011392 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011393 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011394 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011395 if (r.restartDelay < minDuration) {
11396 r.restartDelay = minDuration;
11397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011398 }
11399 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011400
11401 r.nextRestartTime = now + r.restartDelay;
11402
11403 // Make sure that we don't end up restarting a bunch of services
11404 // all at the same time.
11405 boolean repeat;
11406 do {
11407 repeat = false;
11408 for (int i=mRestartingServices.size()-1; i>=0; i--) {
11409 ServiceRecord r2 = mRestartingServices.get(i);
11410 if (r2 != r && r.nextRestartTime
11411 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
11412 && r.nextRestartTime
11413 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
11414 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
11415 r.restartDelay = r.nextRestartTime - now;
11416 repeat = true;
11417 break;
11418 }
11419 }
11420 } while (repeat);
11421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011422 if (!mRestartingServices.contains(r)) {
11423 mRestartingServices.add(r);
11424 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011425
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011426 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011428 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011429 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011430 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011431 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080011433 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 r.shortName, r.restartDelay);
11435
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011436 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011437 }
11438
11439 final void performServiceRestartLocked(ServiceRecord r) {
11440 if (!mRestartingServices.contains(r)) {
11441 return;
11442 }
11443 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
11444 }
11445
11446 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
11447 if (r.restartDelay == 0) {
11448 return false;
11449 }
11450 r.resetRestartCounter();
11451 mRestartingServices.remove(r);
11452 mHandler.removeCallbacks(r.restarter);
11453 return true;
11454 }
11455
11456 private final boolean bringUpServiceLocked(ServiceRecord r,
11457 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011458 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011459 //r.dump(" ");
11460
Dianne Hackborn36124872009-10-08 16:22:03 -070011461 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011462 sendServiceArgsLocked(r, false);
11463 return true;
11464 }
11465
11466 if (!whileRestarting && r.restartDelay > 0) {
11467 // If waiting for a restart, then do nothing.
11468 return true;
11469 }
11470
Joe Onorato8a9b2202010-02-26 18:56:32 -080011471 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 + " " + r.intent);
11473
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011474 // We are now bringing the service up, so no longer in the
11475 // restarting state.
11476 mRestartingServices.remove(r);
11477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011478 final String appName = r.processName;
11479 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11480 if (app != null && app.thread != null) {
11481 try {
11482 realStartServiceLocked(r, app);
11483 return true;
11484 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011485 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011486 }
11487
11488 // If a dead object exception was thrown -- fall through to
11489 // restart the application.
11490 }
11491
Dianne Hackborn36124872009-10-08 16:22:03 -070011492 // Not running -- get it started, and enqueue this service record
11493 // to be executed when the app comes up.
11494 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11495 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011496 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011497 + r.appInfo.packageName + "/"
11498 + r.appInfo.uid + " for service "
11499 + r.intent.getIntent() + ": process is bad");
11500 bringDownServiceLocked(r, true);
11501 return false;
11502 }
11503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011504 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011505 mPendingServices.add(r);
11506 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011508 return true;
11509 }
11510
11511 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011512 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 //r.dump(" ");
11514
11515 // Does it still need to run?
11516 if (!force && r.startRequested) {
11517 return;
11518 }
11519 if (r.connections.size() > 0) {
11520 if (!force) {
11521 // XXX should probably keep a count of the number of auto-create
11522 // connections directly in the service.
11523 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11524 while (it.hasNext()) {
11525 ConnectionRecord cr = it.next();
11526 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11527 return;
11528 }
11529 }
11530 }
11531
11532 // Report to all of the connections that the service is no longer
11533 // available.
11534 Iterator<ConnectionRecord> it = r.connections.values().iterator();
11535 while (it.hasNext()) {
11536 ConnectionRecord c = it.next();
11537 try {
11538 // todo: shouldn't be a synchronous call!
11539 c.conn.connected(r.name, null);
11540 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011541 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011542 " to connection " + c.conn.asBinder() +
11543 " (in " + c.binding.client.processName + ")", e);
11544 }
11545 }
11546 }
11547
11548 // Tell the service that it has been unbound.
11549 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11550 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11551 while (it.hasNext()) {
11552 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011553 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011554 + ": hasBound=" + ibr.hasBound);
11555 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11556 try {
11557 bumpServiceExecutingLocked(r);
11558 updateOomAdjLocked(r.app);
11559 ibr.hasBound = false;
11560 r.app.thread.scheduleUnbindService(r,
11561 ibr.intent.getIntent());
11562 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011563 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011564 + r.shortName, e);
11565 serviceDoneExecutingLocked(r, true);
11566 }
11567 }
11568 }
11569 }
11570
Joe Onorato8a9b2202010-02-26 18:56:32 -080011571 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011573 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011574 System.identityHashCode(r), r.shortName,
11575 (r.app != null) ? r.app.pid : -1);
11576
11577 mServices.remove(r.name);
11578 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011579 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011580 r.totalRestartCount = 0;
11581 unscheduleServiceRestartLocked(r);
11582
11583 // Also make sure it is not on the pending list.
11584 int N = mPendingServices.size();
11585 for (int i=0; i<N; i++) {
11586 if (mPendingServices.get(i) == r) {
11587 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011588 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011589 TAG, "Removed pending service: " + r.shortName);
11590 i--;
11591 N--;
11592 }
11593 }
11594
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011595 r.cancelNotification();
11596 r.isForeground = false;
11597 r.foregroundId = 0;
11598 r.foregroundNoti = null;
11599
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011600 // Clear start entries.
11601 r.deliveredStarts.clear();
11602 r.pendingStarts.clear();
11603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 if (r.app != null) {
11605 synchronized (r.stats.getBatteryStats()) {
11606 r.stats.stopLaunchedLocked();
11607 }
11608 r.app.services.remove(r);
11609 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011610 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011611 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -070011612 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 bumpServiceExecutingLocked(r);
11614 mStoppingServices.add(r);
11615 updateOomAdjLocked(r.app);
11616 r.app.thread.scheduleStopService(r);
11617 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011618 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011619 + r.shortName, e);
11620 serviceDoneExecutingLocked(r, true);
11621 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011622 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011623 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011624 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011625 TAG, "Removed service that has no process: " + r.shortName);
11626 }
11627 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011628 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011629 TAG, "Removed service that is not running: " + r.shortName);
11630 }
11631 }
11632
11633 ComponentName startServiceLocked(IApplicationThread caller,
11634 Intent service, String resolvedType,
11635 int callingPid, int callingUid) {
11636 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011637 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011638 + " type=" + resolvedType + " args=" + service.getExtras());
11639
11640 if (caller != null) {
11641 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11642 if (callerApp == null) {
11643 throw new SecurityException(
11644 "Unable to find app for caller " + caller
11645 + " (pid=" + Binder.getCallingPid()
11646 + ") when starting service " + service);
11647 }
11648 }
11649
11650 ServiceLookupResult res =
11651 retrieveServiceLocked(service, resolvedType,
11652 callingPid, callingUid);
11653 if (res == null) {
11654 return null;
11655 }
11656 if (res.record == null) {
11657 return new ComponentName("!", res.permission != null
11658 ? res.permission : "private to package");
11659 }
11660 ServiceRecord r = res.record;
11661 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011662 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663 + r.shortName);
11664 }
11665 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011666 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011667 r.lastStartId++;
11668 if (r.lastStartId < 1) {
11669 r.lastStartId = 1;
11670 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011671 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672 r.lastActivity = SystemClock.uptimeMillis();
11673 synchronized (r.stats.getBatteryStats()) {
11674 r.stats.startRunningLocked();
11675 }
11676 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11677 return new ComponentName("!", "Service process is bad");
11678 }
11679 return r.name;
11680 }
11681 }
11682
11683 public ComponentName startService(IApplicationThread caller, Intent service,
11684 String resolvedType) {
11685 // Refuse possible leaked file descriptors
11686 if (service != null && service.hasFileDescriptors() == true) {
11687 throw new IllegalArgumentException("File descriptors passed in Intent");
11688 }
11689
11690 synchronized(this) {
11691 final int callingPid = Binder.getCallingPid();
11692 final int callingUid = Binder.getCallingUid();
11693 final long origId = Binder.clearCallingIdentity();
11694 ComponentName res = startServiceLocked(caller, service,
11695 resolvedType, callingPid, callingUid);
11696 Binder.restoreCallingIdentity(origId);
11697 return res;
11698 }
11699 }
11700
11701 ComponentName startServiceInPackage(int uid,
11702 Intent service, String resolvedType) {
11703 synchronized(this) {
11704 final long origId = Binder.clearCallingIdentity();
11705 ComponentName res = startServiceLocked(null, service,
11706 resolvedType, -1, uid);
11707 Binder.restoreCallingIdentity(origId);
11708 return res;
11709 }
11710 }
11711
11712 public int stopService(IApplicationThread caller, Intent service,
11713 String resolvedType) {
11714 // Refuse possible leaked file descriptors
11715 if (service != null && service.hasFileDescriptors() == true) {
11716 throw new IllegalArgumentException("File descriptors passed in Intent");
11717 }
11718
11719 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011720 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011721 + " type=" + resolvedType);
11722
11723 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11724 if (caller != null && callerApp == null) {
11725 throw new SecurityException(
11726 "Unable to find app for caller " + caller
11727 + " (pid=" + Binder.getCallingPid()
11728 + ") when stopping service " + service);
11729 }
11730
11731 // If this service is active, make sure it is stopped.
11732 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11733 if (r != null) {
11734 if (r.record != null) {
11735 synchronized (r.record.stats.getBatteryStats()) {
11736 r.record.stats.stopRunningLocked();
11737 }
11738 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011739 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011740 final long origId = Binder.clearCallingIdentity();
11741 bringDownServiceLocked(r.record, false);
11742 Binder.restoreCallingIdentity(origId);
11743 return 1;
11744 }
11745 return -1;
11746 }
11747 }
11748
11749 return 0;
11750 }
11751
11752 public IBinder peekService(Intent service, String resolvedType) {
11753 // Refuse possible leaked file descriptors
11754 if (service != null && service.hasFileDescriptors() == true) {
11755 throw new IllegalArgumentException("File descriptors passed in Intent");
11756 }
11757
11758 IBinder ret = null;
11759
11760 synchronized(this) {
11761 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11762
11763 if (r != null) {
11764 // r.record is null if findServiceLocked() failed the caller permission check
11765 if (r.record == null) {
11766 throw new SecurityException(
11767 "Permission Denial: Accessing service " + r.record.name
11768 + " from pid=" + Binder.getCallingPid()
11769 + ", uid=" + Binder.getCallingUid()
11770 + " requires " + r.permission);
11771 }
11772 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11773 if (ib != null) {
11774 ret = ib.binder;
11775 }
11776 }
11777 }
11778
11779 return ret;
11780 }
11781
11782 public boolean stopServiceToken(ComponentName className, IBinder token,
11783 int startId) {
11784 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011785 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011786 + " " + token + " startId=" + startId);
11787 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011788 if (r != null) {
11789 if (startId >= 0) {
11790 // Asked to only stop if done with all work. Note that
11791 // to avoid leaks, we will take this as dropping all
11792 // start items up to and including this one.
11793 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11794 if (si != null) {
11795 while (r.deliveredStarts.size() > 0) {
11796 if (r.deliveredStarts.remove(0) == si) {
11797 break;
11798 }
11799 }
11800 }
11801
11802 if (r.lastStartId != startId) {
11803 return false;
11804 }
11805
11806 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011807 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011808 + " is last, but have " + r.deliveredStarts.size()
11809 + " remaining args");
11810 }
11811 }
11812
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011813 synchronized (r.stats.getBatteryStats()) {
11814 r.stats.stopRunningLocked();
11815 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011816 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011817 }
11818 final long origId = Binder.clearCallingIdentity();
11819 bringDownServiceLocked(r, false);
11820 Binder.restoreCallingIdentity(origId);
11821 return true;
11822 }
11823 }
11824 return false;
11825 }
11826
11827 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011828 int id, Notification notification, boolean removeNotification) {
11829 final long origId = Binder.clearCallingIdentity();
11830 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011831 synchronized(this) {
11832 ServiceRecord r = findServiceLocked(className, token);
11833 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011834 if (id != 0) {
11835 if (notification == null) {
11836 throw new IllegalArgumentException("null notification");
11837 }
11838 if (r.foregroundId != id) {
11839 r.cancelNotification();
11840 r.foregroundId = id;
11841 }
11842 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11843 r.foregroundNoti = notification;
11844 r.isForeground = true;
11845 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 if (r.app != null) {
11847 updateServiceForegroundLocked(r.app, true);
11848 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011849 } else {
11850 if (r.isForeground) {
11851 r.isForeground = false;
11852 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011853 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011854 updateServiceForegroundLocked(r.app, true);
11855 }
11856 }
11857 if (removeNotification) {
11858 r.cancelNotification();
11859 r.foregroundId = 0;
11860 r.foregroundNoti = null;
11861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011862 }
11863 }
11864 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011865 } finally {
11866 Binder.restoreCallingIdentity(origId);
11867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011868 }
11869
11870 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11871 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070011872 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011873 if (sr.isForeground) {
11874 anyForeground = true;
11875 break;
11876 }
11877 }
11878 if (anyForeground != proc.foregroundServices) {
11879 proc.foregroundServices = anyForeground;
11880 if (oomAdj) {
11881 updateOomAdjLocked();
11882 }
11883 }
11884 }
11885
11886 public int bindService(IApplicationThread caller, IBinder token,
11887 Intent service, String resolvedType,
11888 IServiceConnection connection, int flags) {
11889 // Refuse possible leaked file descriptors
11890 if (service != null && service.hasFileDescriptors() == true) {
11891 throw new IllegalArgumentException("File descriptors passed in Intent");
11892 }
11893
11894 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011895 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011896 + " type=" + resolvedType + " conn=" + connection.asBinder()
11897 + " flags=0x" + Integer.toHexString(flags));
11898 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11899 if (callerApp == null) {
11900 throw new SecurityException(
11901 "Unable to find app for caller " + caller
11902 + " (pid=" + Binder.getCallingPid()
11903 + ") when binding service " + service);
11904 }
11905
11906 HistoryRecord activity = null;
11907 if (token != null) {
Dianne Hackborn75b03852009-06-12 15:43:26 -070011908 int aindex = indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011910 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011911 return 0;
11912 }
11913 activity = (HistoryRecord)mHistory.get(aindex);
11914 }
11915
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011916 int clientLabel = 0;
11917 PendingIntent clientIntent = null;
11918
11919 if (callerApp.info.uid == Process.SYSTEM_UID) {
11920 // Hacky kind of thing -- allow system stuff to tell us
11921 // what they are, so we can report this elsewhere for
11922 // others to know why certain services are running.
11923 try {
11924 clientIntent = (PendingIntent)service.getParcelableExtra(
11925 Intent.EXTRA_CLIENT_INTENT);
11926 } catch (RuntimeException e) {
11927 }
11928 if (clientIntent != null) {
11929 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11930 if (clientLabel != 0) {
11931 // There are no useful extras in the intent, trash them.
11932 // System code calling with this stuff just needs to know
11933 // this will happen.
11934 service = service.cloneFilter();
11935 }
11936 }
11937 }
11938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011939 ServiceLookupResult res =
11940 retrieveServiceLocked(service, resolvedType,
11941 Binder.getCallingPid(), Binder.getCallingUid());
11942 if (res == null) {
11943 return 0;
11944 }
11945 if (res.record == null) {
11946 return -1;
11947 }
11948 ServiceRecord s = res.record;
11949
11950 final long origId = Binder.clearCallingIdentity();
11951
11952 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011953 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 + s.shortName);
11955 }
11956
11957 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11958 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011959 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011960
11961 IBinder binder = connection.asBinder();
11962 s.connections.put(binder, c);
11963 b.connections.add(c);
11964 if (activity != null) {
11965 if (activity.connections == null) {
11966 activity.connections = new HashSet<ConnectionRecord>();
11967 }
11968 activity.connections.add(c);
11969 }
11970 b.client.connections.add(c);
11971 mServiceConnections.put(binder, c);
11972
11973 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11974 s.lastActivity = SystemClock.uptimeMillis();
11975 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11976 return 0;
11977 }
11978 }
11979
11980 if (s.app != null) {
11981 // This could have made the service more important.
11982 updateOomAdjLocked(s.app);
11983 }
11984
Joe Onorato8a9b2202010-02-26 18:56:32 -080011985 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011986 + ": received=" + b.intent.received
11987 + " apps=" + b.intent.apps.size()
11988 + " doRebind=" + b.intent.doRebind);
11989
11990 if (s.app != null && b.intent.received) {
11991 // Service is already running, so we can immediately
11992 // publish the connection.
11993 try {
11994 c.conn.connected(s.name, b.intent.binder);
11995 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011996 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011997 + " to connection " + c.conn.asBinder()
11998 + " (in " + c.binding.client.processName + ")", e);
11999 }
12000
12001 // If this is the first app connected back to this binding,
12002 // and the service had previously asked to be told when
12003 // rebound, then do so.
12004 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
12005 requestServiceBindingLocked(s, b.intent, true);
12006 }
12007 } else if (!b.intent.requested) {
12008 requestServiceBindingLocked(s, b.intent, false);
12009 }
12010
12011 Binder.restoreCallingIdentity(origId);
12012 }
12013
12014 return 1;
12015 }
12016
12017 private void removeConnectionLocked(
12018 ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
12019 IBinder binder = c.conn.asBinder();
12020 AppBindRecord b = c.binding;
12021 ServiceRecord s = b.service;
12022 s.connections.remove(binder);
12023 b.connections.remove(c);
12024 if (c.activity != null && c.activity != skipAct) {
12025 if (c.activity.connections != null) {
12026 c.activity.connections.remove(c);
12027 }
12028 }
12029 if (b.client != skipApp) {
12030 b.client.connections.remove(c);
12031 }
12032 mServiceConnections.remove(binder);
12033
12034 if (b.connections.size() == 0) {
12035 b.intent.apps.remove(b.client);
12036 }
12037
Joe Onorato8a9b2202010-02-26 18:56:32 -080012038 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012039 + ": shouldUnbind=" + b.intent.hasBound);
12040 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
12041 && b.intent.hasBound) {
12042 try {
12043 bumpServiceExecutingLocked(s);
12044 updateOomAdjLocked(s.app);
12045 b.intent.hasBound = false;
12046 // Assume the client doesn't want to know about a rebind;
12047 // we will deal with that later if it asks for one.
12048 b.intent.doRebind = false;
12049 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
12050 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012051 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012052 serviceDoneExecutingLocked(s, true);
12053 }
12054 }
12055
12056 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
12057 bringDownServiceLocked(s, false);
12058 }
12059 }
12060
12061 public boolean unbindService(IServiceConnection connection) {
12062 synchronized (this) {
12063 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012064 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012065 ConnectionRecord r = mServiceConnections.get(binder);
12066 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012067 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012068 + connection.asBinder());
12069 return false;
12070 }
12071
12072 final long origId = Binder.clearCallingIdentity();
12073
12074 removeConnectionLocked(r, null, null);
12075
12076 if (r.binding.service.app != null) {
12077 // This could have made the service less important.
12078 updateOomAdjLocked(r.binding.service.app);
12079 }
12080
12081 Binder.restoreCallingIdentity(origId);
12082 }
12083
12084 return true;
12085 }
12086
12087 public void publishService(IBinder token, Intent intent, IBinder service) {
12088 // Refuse possible leaked file descriptors
12089 if (intent != null && intent.hasFileDescriptors() == true) {
12090 throw new IllegalArgumentException("File descriptors passed in Intent");
12091 }
12092
12093 synchronized(this) {
12094 if (!(token instanceof ServiceRecord)) {
12095 throw new IllegalArgumentException("Invalid service token");
12096 }
12097 ServiceRecord r = (ServiceRecord)token;
12098
12099 final long origId = Binder.clearCallingIdentity();
12100
Joe Onorato8a9b2202010-02-26 18:56:32 -080012101 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012102 + " " + intent + ": " + service);
12103 if (r != null) {
12104 Intent.FilterComparison filter
12105 = new Intent.FilterComparison(intent);
12106 IntentBindRecord b = r.bindings.get(filter);
12107 if (b != null && !b.received) {
12108 b.binder = service;
12109 b.requested = true;
12110 b.received = true;
12111 if (r.connections.size() > 0) {
12112 Iterator<ConnectionRecord> it
12113 = r.connections.values().iterator();
12114 while (it.hasNext()) {
12115 ConnectionRecord c = it.next();
12116 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012117 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012118 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012119 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012120 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012121 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012122 TAG, "Published intent: " + intent);
12123 continue;
12124 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012125 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012126 try {
12127 c.conn.connected(r.name, service);
12128 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012129 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012130 " to connection " + c.conn.asBinder() +
12131 " (in " + c.binding.client.processName + ")", e);
12132 }
12133 }
12134 }
12135 }
12136
12137 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12138
12139 Binder.restoreCallingIdentity(origId);
12140 }
12141 }
12142 }
12143
12144 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
12145 // Refuse possible leaked file descriptors
12146 if (intent != null && intent.hasFileDescriptors() == true) {
12147 throw new IllegalArgumentException("File descriptors passed in Intent");
12148 }
12149
12150 synchronized(this) {
12151 if (!(token instanceof ServiceRecord)) {
12152 throw new IllegalArgumentException("Invalid service token");
12153 }
12154 ServiceRecord r = (ServiceRecord)token;
12155
12156 final long origId = Binder.clearCallingIdentity();
12157
12158 if (r != null) {
12159 Intent.FilterComparison filter
12160 = new Intent.FilterComparison(intent);
12161 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012162 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012163 + " at " + b + ": apps="
12164 + (b != null ? b.apps.size() : 0));
12165 if (b != null) {
12166 if (b.apps.size() > 0) {
12167 // Applications have already bound since the last
12168 // unbind, so just rebind right here.
12169 requestServiceBindingLocked(r, b, true);
12170 } else {
12171 // Note to tell the service the next time there is
12172 // a new client.
12173 b.doRebind = true;
12174 }
12175 }
12176
12177 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
12178
12179 Binder.restoreCallingIdentity(origId);
12180 }
12181 }
12182 }
12183
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012184 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012185 synchronized(this) {
12186 if (!(token instanceof ServiceRecord)) {
12187 throw new IllegalArgumentException("Invalid service token");
12188 }
12189 ServiceRecord r = (ServiceRecord)token;
12190 boolean inStopping = mStoppingServices.contains(token);
12191 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012192 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012193 + ": nesting=" + r.executeNesting
12194 + ", inStopping=" + inStopping);
12195 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012196 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012197 + " with incorrect token: given " + token
12198 + ", expected " + r);
12199 return;
12200 }
12201
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070012202 if (type == 1) {
12203 // This is a call from a service start... take care of
12204 // book-keeping.
12205 r.callStart = true;
12206 switch (res) {
12207 case Service.START_STICKY_COMPATIBILITY:
12208 case Service.START_STICKY: {
12209 // We are done with the associated start arguments.
12210 r.findDeliveredStart(startId, true);
12211 // Don't stop if killed.
12212 r.stopIfKilled = false;
12213 break;
12214 }
12215 case Service.START_NOT_STICKY: {
12216 // We are done with the associated start arguments.
12217 r.findDeliveredStart(startId, true);
12218 if (r.lastStartId == startId) {
12219 // There is no more work, and this service
12220 // doesn't want to hang around if killed.
12221 r.stopIfKilled = true;
12222 }
12223 break;
12224 }
12225 case Service.START_REDELIVER_INTENT: {
12226 // We'll keep this item until they explicitly
12227 // call stop for it, but keep track of the fact
12228 // that it was delivered.
12229 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
12230 if (si != null) {
12231 si.deliveryCount = 0;
12232 si.doneExecutingCount++;
12233 // Don't stop if killed.
12234 r.stopIfKilled = true;
12235 }
12236 break;
12237 }
12238 default:
12239 throw new IllegalArgumentException(
12240 "Unknown service start result: " + res);
12241 }
12242 if (res == Service.START_STICKY_COMPATIBILITY) {
12243 r.callStart = false;
12244 }
12245 }
12246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012247 final long origId = Binder.clearCallingIdentity();
12248 serviceDoneExecutingLocked(r, inStopping);
12249 Binder.restoreCallingIdentity(origId);
12250 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012251 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012252 + " with token " + token);
12253 }
12254 }
12255 }
12256
12257 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
12258 r.executeNesting--;
12259 if (r.executeNesting <= 0 && r.app != null) {
12260 r.app.executingServices.remove(r);
12261 if (r.app.executingServices.size() == 0) {
12262 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
12263 }
12264 if (inStopping) {
12265 mStoppingServices.remove(r);
12266 }
12267 updateOomAdjLocked(r.app);
12268 }
12269 }
12270
12271 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012272 String anrMessage = null;
12273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012274 synchronized(this) {
12275 if (proc.executingServices.size() == 0 || proc.thread == null) {
12276 return;
12277 }
12278 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
12279 Iterator<ServiceRecord> it = proc.executingServices.iterator();
12280 ServiceRecord timeout = null;
12281 long nextTime = 0;
12282 while (it.hasNext()) {
12283 ServiceRecord sr = it.next();
12284 if (sr.executingStart < maxTime) {
12285 timeout = sr;
12286 break;
12287 }
12288 if (sr.executingStart > nextTime) {
12289 nextTime = sr.executingStart;
12290 }
12291 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012292 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012293 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012294 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012295 } else {
12296 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
12297 msg.obj = proc;
12298 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
12299 }
12300 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012301
12302 if (anrMessage != null) {
12303 appNotResponding(proc, null, null, anrMessage);
12304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012305 }
12306
12307 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070012308 // BACKUP AND RESTORE
12309 // =========================================================
12310
12311 // Cause the target app to be launched if necessary and its backup agent
12312 // instantiated. The backup agent will invoke backupAgentCreated() on the
12313 // activity manager to announce its creation.
12314 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012315 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070012316 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
12317
12318 synchronized(this) {
12319 // !!! TODO: currently no check here that we're already bound
12320 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
12321 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12322 synchronized (stats) {
12323 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
12324 }
12325
12326 BackupRecord r = new BackupRecord(ss, app, backupMode);
12327 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
12328 // startProcessLocked() returns existing proc's record if it's already running
12329 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012330 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070012331 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012332 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070012333 return false;
12334 }
12335
12336 r.app = proc;
12337 mBackupTarget = r;
12338 mBackupAppName = app.packageName;
12339
Christopher Tate6fa95972009-06-05 18:43:55 -070012340 // Try not to kill the process during backup
12341 updateOomAdjLocked(proc);
12342
Christopher Tate181fafa2009-05-14 11:12:14 -070012343 // If the process is already attached, schedule the creation of the backup agent now.
12344 // If it is not yet live, this will be done when it attaches to the framework.
12345 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012346 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070012347 try {
12348 proc.thread.scheduleCreateBackupAgent(app, backupMode);
12349 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070012350 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070012351 }
12352 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012353 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070012354 }
12355 // Invariants: at this point, the target app process exists and the application
12356 // is either already running or in the process of coming up. mBackupTarget and
12357 // mBackupAppName describe the app, so that when it binds back to the AM we
12358 // know that it's scheduled for a backup-agent operation.
12359 }
12360
12361 return true;
12362 }
12363
12364 // A backup agent has just come up
12365 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012366 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070012367 + " = " + agent);
12368
12369 synchronized(this) {
12370 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012371 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070012372 return;
12373 }
12374
Christopher Tate043dadc2009-06-02 16:11:00 -070012375 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -070012376 try {
12377 IBackupManager bm = IBackupManager.Stub.asInterface(
12378 ServiceManager.getService(Context.BACKUP_SERVICE));
12379 bm.agentConnected(agentPackageName, agent);
12380 } catch (RemoteException e) {
12381 // can't happen; the backup manager service is local
12382 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012383 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -070012384 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -070012385 } finally {
12386 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012387 }
12388 }
12389 }
12390
12391 // done with this agent
12392 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012393 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012394 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012395 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012396 return;
12397 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012398
12399 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012400 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012401 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012402 return;
12403 }
12404
Christopher Tate181fafa2009-05-14 11:12:14 -070012405 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012406 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012407 return;
12408 }
12409
Christopher Tate6fa95972009-06-05 18:43:55 -070012410 ProcessRecord proc = mBackupTarget.app;
12411 mBackupTarget = null;
12412 mBackupAppName = null;
12413
12414 // Not backing this app up any more; reset its OOM adjustment
12415 updateOomAdjLocked(proc);
12416
Christopher Tatec7b31e32009-06-10 15:49:30 -070012417 // If the app crashed during backup, 'thread' will be null here
12418 if (proc.thread != null) {
12419 try {
12420 proc.thread.scheduleDestroyBackupAgent(appInfo);
12421 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012422 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012423 e.printStackTrace();
12424 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012425 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012426 }
12427 }
12428 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012429 // BROADCASTS
12430 // =========================================================
12431
Josh Bartel7f208742010-02-25 11:01:44 -060012432 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012433 List cur) {
12434 final ContentResolver resolver = mContext.getContentResolver();
12435 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12436 if (list == null) {
12437 return cur;
12438 }
12439 int N = list.size();
12440 for (int i=0; i<N; i++) {
12441 Intent intent = list.get(i);
12442 if (filter.match(resolver, intent, true, TAG) >= 0) {
12443 if (cur == null) {
12444 cur = new ArrayList<Intent>();
12445 }
12446 cur.add(intent);
12447 }
12448 }
12449 return cur;
12450 }
12451
12452 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012453 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012454 + mBroadcastsScheduled);
12455
12456 if (mBroadcastsScheduled) {
12457 return;
12458 }
12459 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12460 mBroadcastsScheduled = true;
12461 }
12462
12463 public Intent registerReceiver(IApplicationThread caller,
12464 IIntentReceiver receiver, IntentFilter filter, String permission) {
12465 synchronized(this) {
12466 ProcessRecord callerApp = null;
12467 if (caller != null) {
12468 callerApp = getRecordForAppLocked(caller);
12469 if (callerApp == null) {
12470 throw new SecurityException(
12471 "Unable to find app for caller " + caller
12472 + " (pid=" + Binder.getCallingPid()
12473 + ") when registering receiver " + receiver);
12474 }
12475 }
12476
12477 List allSticky = null;
12478
12479 // Look for any matching sticky broadcasts...
12480 Iterator actions = filter.actionsIterator();
12481 if (actions != null) {
12482 while (actions.hasNext()) {
12483 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012484 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012485 }
12486 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012487 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012488 }
12489
12490 // The first sticky in the list is returned directly back to
12491 // the client.
12492 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12493
Joe Onorato8a9b2202010-02-26 18:56:32 -080012494 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012495 + ": " + sticky);
12496
12497 if (receiver == null) {
12498 return sticky;
12499 }
12500
12501 ReceiverList rl
12502 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12503 if (rl == null) {
12504 rl = new ReceiverList(this, callerApp,
12505 Binder.getCallingPid(),
12506 Binder.getCallingUid(), receiver);
12507 if (rl.app != null) {
12508 rl.app.receivers.add(rl);
12509 } else {
12510 try {
12511 receiver.asBinder().linkToDeath(rl, 0);
12512 } catch (RemoteException e) {
12513 return sticky;
12514 }
12515 rl.linkedToDeath = true;
12516 }
12517 mRegisteredReceivers.put(receiver.asBinder(), rl);
12518 }
12519 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
12520 rl.add(bf);
12521 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012522 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012523 }
12524 mReceiverResolver.addFilter(bf);
12525
12526 // Enqueue broadcasts for all existing stickies that match
12527 // this filter.
12528 if (allSticky != null) {
12529 ArrayList receivers = new ArrayList();
12530 receivers.add(bf);
12531
12532 int N = allSticky.size();
12533 for (int i=0; i<N; i++) {
12534 Intent intent = (Intent)allSticky.get(i);
12535 BroadcastRecord r = new BroadcastRecord(intent, null,
12536 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012537 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012538 if (mParallelBroadcasts.size() == 0) {
12539 scheduleBroadcastsLocked();
12540 }
12541 mParallelBroadcasts.add(r);
12542 }
12543 }
12544
12545 return sticky;
12546 }
12547 }
12548
12549 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012550 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012551
12552 boolean doNext = false;
12553
12554 synchronized(this) {
12555 ReceiverList rl
12556 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12557 if (rl != null) {
12558 if (rl.curBroadcast != null) {
12559 BroadcastRecord r = rl.curBroadcast;
12560 doNext = finishReceiverLocked(
12561 receiver.asBinder(), r.resultCode, r.resultData,
12562 r.resultExtras, r.resultAbort, true);
12563 }
12564
12565 if (rl.app != null) {
12566 rl.app.receivers.remove(rl);
12567 }
12568 removeReceiverLocked(rl);
12569 if (rl.linkedToDeath) {
12570 rl.linkedToDeath = false;
12571 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12572 }
12573 }
12574 }
12575
12576 if (!doNext) {
12577 return;
12578 }
12579
12580 final long origId = Binder.clearCallingIdentity();
12581 processNextBroadcast(false);
12582 trimApplications();
12583 Binder.restoreCallingIdentity(origId);
12584 }
12585
12586 void removeReceiverLocked(ReceiverList rl) {
12587 mRegisteredReceivers.remove(rl.receiver.asBinder());
12588 int N = rl.size();
12589 for (int i=0; i<N; i++) {
12590 mReceiverResolver.removeFilter(rl.get(i));
12591 }
12592 }
12593
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012594 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12595 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12596 ProcessRecord r = mLruProcesses.get(i);
12597 if (r.thread != null) {
12598 try {
12599 r.thread.dispatchPackageBroadcast(cmd, packages);
12600 } catch (RemoteException ex) {
12601 }
12602 }
12603 }
12604 }
12605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012606 private final int broadcastIntentLocked(ProcessRecord callerApp,
12607 String callerPackage, Intent intent, String resolvedType,
12608 IIntentReceiver resultTo, int resultCode, String resultData,
12609 Bundle map, String requiredPermission,
12610 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12611 intent = new Intent(intent);
12612
Joe Onorato8a9b2202010-02-26 18:56:32 -080012613 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012614 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12615 + " ordered=" + ordered);
12616 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012617 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012618 }
12619
12620 // Handle special intents: if this broadcast is from the package
12621 // manager about a package being removed, we need to remove all of
12622 // its activities from the history stack.
12623 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
12624 intent.getAction());
12625 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12626 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012627 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012628 || uidRemoved) {
12629 if (checkComponentPermission(
12630 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
12631 callingPid, callingUid, -1)
12632 == PackageManager.PERMISSION_GRANTED) {
12633 if (uidRemoved) {
12634 final Bundle intentExtras = intent.getExtras();
12635 final int uid = intentExtras != null
12636 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12637 if (uid >= 0) {
12638 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12639 synchronized (bs) {
12640 bs.removeUidStatsLocked(uid);
12641 }
12642 }
12643 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012644 // If resources are unvailble just force stop all
12645 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012646 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012647 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12648 if (list != null && (list.length > 0)) {
12649 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012650 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012651 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012652 sendPackageBroadcastLocked(
12653 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012654 }
12655 } else {
12656 Uri data = intent.getData();
12657 String ssp;
12658 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12659 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12660 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012661 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012662 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012663 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
12664 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12665 new String[] {ssp});
12666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012667 }
12668 }
12669 }
12670 } else {
12671 String msg = "Permission Denial: " + intent.getAction()
12672 + " broadcast from " + callerPackage + " (pid=" + callingPid
12673 + ", uid=" + callingUid + ")"
12674 + " requires "
12675 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012676 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012677 throw new SecurityException(msg);
12678 }
12679 }
12680
12681 /*
12682 * If this is the time zone changed action, queue up a message that will reset the timezone
12683 * of all currently running processes. This message will get queued up before the broadcast
12684 * happens.
12685 */
12686 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12687 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12688 }
12689
Dianne Hackborn854060af2009-07-09 18:14:31 -070012690 /*
12691 * Prevent non-system code (defined here to be non-persistent
12692 * processes) from sending protected broadcasts.
12693 */
12694 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12695 || callingUid == Process.SHELL_UID || callingUid == 0) {
12696 // Always okay.
12697 } else if (callerApp == null || !callerApp.persistent) {
12698 try {
12699 if (ActivityThread.getPackageManager().isProtectedBroadcast(
12700 intent.getAction())) {
12701 String msg = "Permission Denial: not allowed to send broadcast "
12702 + intent.getAction() + " from pid="
12703 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012704 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012705 throw new SecurityException(msg);
12706 }
12707 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012708 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012709 return BROADCAST_SUCCESS;
12710 }
12711 }
12712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012713 // Add to the sticky list if requested.
12714 if (sticky) {
12715 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12716 callingPid, callingUid)
12717 != PackageManager.PERMISSION_GRANTED) {
12718 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12719 + callingPid + ", uid=" + callingUid
12720 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012721 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012722 throw new SecurityException(msg);
12723 }
12724 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012725 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012726 + " and enforce permission " + requiredPermission);
12727 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12728 }
12729 if (intent.getComponent() != null) {
12730 throw new SecurityException(
12731 "Sticky broadcasts can't target a specific component");
12732 }
12733 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12734 if (list == null) {
12735 list = new ArrayList<Intent>();
12736 mStickyBroadcasts.put(intent.getAction(), list);
12737 }
12738 int N = list.size();
12739 int i;
12740 for (i=0; i<N; i++) {
12741 if (intent.filterEquals(list.get(i))) {
12742 // This sticky already exists, replace it.
12743 list.set(i, new Intent(intent));
12744 break;
12745 }
12746 }
12747 if (i >= N) {
12748 list.add(new Intent(intent));
12749 }
12750 }
12751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012752 // Figure out who all will receive this broadcast.
12753 List receivers = null;
12754 List<BroadcastFilter> registeredReceivers = null;
12755 try {
12756 if (intent.getComponent() != null) {
12757 // Broadcast is going to one specific receiver class...
12758 ActivityInfo ai = ActivityThread.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012759 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012760 if (ai != null) {
12761 receivers = new ArrayList();
12762 ResolveInfo ri = new ResolveInfo();
12763 ri.activityInfo = ai;
12764 receivers.add(ri);
12765 }
12766 } else {
12767 // Need to resolve the intent to interested receivers...
12768 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12769 == 0) {
12770 receivers =
12771 ActivityThread.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012772 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012773 }
Mihai Preda074edef2009-05-18 17:13:31 +020012774 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012775 }
12776 } catch (RemoteException ex) {
12777 // pm is in same process, this will never happen.
12778 }
12779
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012780 final boolean replacePending =
12781 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12782
Joe Onorato8a9b2202010-02-26 18:56:32 -080012783 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012784 + " replacePending=" + replacePending);
12785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012786 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12787 if (!ordered && NR > 0) {
12788 // If we are not serializing this broadcast, then send the
12789 // registered receivers separately so they don't wait for the
12790 // components to be launched.
12791 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12792 callerPackage, callingPid, callingUid, requiredPermission,
12793 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012794 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012795 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012796 TAG, "Enqueueing parallel broadcast " + r
12797 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012798 boolean replaced = false;
12799 if (replacePending) {
12800 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12801 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012802 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012803 "***** DROPPING PARALLEL: " + intent);
12804 mParallelBroadcasts.set(i, r);
12805 replaced = true;
12806 break;
12807 }
12808 }
12809 }
12810 if (!replaced) {
12811 mParallelBroadcasts.add(r);
12812 scheduleBroadcastsLocked();
12813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012814 registeredReceivers = null;
12815 NR = 0;
12816 }
12817
12818 // Merge into one list.
12819 int ir = 0;
12820 if (receivers != null) {
12821 // A special case for PACKAGE_ADDED: do not allow the package
12822 // being added to see this broadcast. This prevents them from
12823 // using this as a back door to get run as soon as they are
12824 // installed. Maybe in the future we want to have a special install
12825 // broadcast or such for apps, but we'd like to deliberately make
12826 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012827 String skipPackages[] = null;
12828 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12829 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12830 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
12831 Uri data = intent.getData();
12832 if (data != null) {
12833 String pkgName = data.getSchemeSpecificPart();
12834 if (pkgName != null) {
12835 skipPackages = new String[] { pkgName };
12836 }
12837 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012838 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012839 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012840 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012841 if (skipPackages != null && (skipPackages.length > 0)) {
12842 for (String skipPackage : skipPackages) {
12843 if (skipPackage != null) {
12844 int NT = receivers.size();
12845 for (int it=0; it<NT; it++) {
12846 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12847 if (curt.activityInfo.packageName.equals(skipPackage)) {
12848 receivers.remove(it);
12849 it--;
12850 NT--;
12851 }
12852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012853 }
12854 }
12855 }
12856
12857 int NT = receivers != null ? receivers.size() : 0;
12858 int it = 0;
12859 ResolveInfo curt = null;
12860 BroadcastFilter curr = null;
12861 while (it < NT && ir < NR) {
12862 if (curt == null) {
12863 curt = (ResolveInfo)receivers.get(it);
12864 }
12865 if (curr == null) {
12866 curr = registeredReceivers.get(ir);
12867 }
12868 if (curr.getPriority() >= curt.priority) {
12869 // Insert this broadcast record into the final list.
12870 receivers.add(it, curr);
12871 ir++;
12872 curr = null;
12873 it++;
12874 NT++;
12875 } else {
12876 // Skip to the next ResolveInfo in the final list.
12877 it++;
12878 curt = null;
12879 }
12880 }
12881 }
12882 while (ir < NR) {
12883 if (receivers == null) {
12884 receivers = new ArrayList();
12885 }
12886 receivers.add(registeredReceivers.get(ir));
12887 ir++;
12888 }
12889
12890 if ((receivers != null && receivers.size() > 0)
12891 || resultTo != null) {
12892 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12893 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012894 receivers, resultTo, resultCode, resultData, map, ordered,
12895 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012896 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012897 TAG, "Enqueueing ordered broadcast " + r
12898 + ": prev had " + mOrderedBroadcasts.size());
12899 if (DEBUG_BROADCAST) {
12900 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012901 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012902 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012903 boolean replaced = false;
12904 if (replacePending) {
12905 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
12906 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012907 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012908 "***** DROPPING ORDERED: " + intent);
12909 mOrderedBroadcasts.set(i, r);
12910 replaced = true;
12911 break;
12912 }
12913 }
12914 }
12915 if (!replaced) {
12916 mOrderedBroadcasts.add(r);
12917 scheduleBroadcastsLocked();
12918 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012919 }
12920
12921 return BROADCAST_SUCCESS;
12922 }
12923
12924 public final int broadcastIntent(IApplicationThread caller,
12925 Intent intent, String resolvedType, IIntentReceiver resultTo,
12926 int resultCode, String resultData, Bundle map,
12927 String requiredPermission, boolean serialized, boolean sticky) {
12928 // Refuse possible leaked file descriptors
12929 if (intent != null && intent.hasFileDescriptors() == true) {
12930 throw new IllegalArgumentException("File descriptors passed in Intent");
12931 }
12932
12933 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012934 int flags = intent.getFlags();
12935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012936 if (!mSystemReady) {
12937 // if the caller really truly claims to know what they're doing, go
12938 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012939 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12940 intent = new Intent(intent);
12941 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12942 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080012943 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012944 + " before boot completion");
12945 throw new IllegalStateException("Cannot broadcast before boot completed");
12946 }
12947 }
12948
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012949 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12950 throw new IllegalArgumentException(
12951 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12952 }
12953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012954 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12955 final int callingPid = Binder.getCallingPid();
12956 final int callingUid = Binder.getCallingUid();
12957 final long origId = Binder.clearCallingIdentity();
12958 int res = broadcastIntentLocked(callerApp,
12959 callerApp != null ? callerApp.info.packageName : null,
12960 intent, resolvedType, resultTo,
12961 resultCode, resultData, map, requiredPermission, serialized,
12962 sticky, callingPid, callingUid);
12963 Binder.restoreCallingIdentity(origId);
12964 return res;
12965 }
12966 }
12967
12968 int broadcastIntentInPackage(String packageName, int uid,
12969 Intent intent, String resolvedType, IIntentReceiver resultTo,
12970 int resultCode, String resultData, Bundle map,
12971 String requiredPermission, boolean serialized, boolean sticky) {
12972 synchronized(this) {
12973 final long origId = Binder.clearCallingIdentity();
12974 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12975 resultTo, resultCode, resultData, map, requiredPermission,
12976 serialized, sticky, -1, uid);
12977 Binder.restoreCallingIdentity(origId);
12978 return res;
12979 }
12980 }
12981
12982 public final void unbroadcastIntent(IApplicationThread caller,
12983 Intent intent) {
12984 // Refuse possible leaked file descriptors
12985 if (intent != null && intent.hasFileDescriptors() == true) {
12986 throw new IllegalArgumentException("File descriptors passed in Intent");
12987 }
12988
12989 synchronized(this) {
12990 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12991 != PackageManager.PERMISSION_GRANTED) {
12992 String msg = "Permission Denial: unbroadcastIntent() from pid="
12993 + Binder.getCallingPid()
12994 + ", uid=" + Binder.getCallingUid()
12995 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012996 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012997 throw new SecurityException(msg);
12998 }
12999 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
13000 if (list != null) {
13001 int N = list.size();
13002 int i;
13003 for (i=0; i<N; i++) {
13004 if (intent.filterEquals(list.get(i))) {
13005 list.remove(i);
13006 break;
13007 }
13008 }
13009 }
13010 }
13011 }
13012
13013 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
13014 String resultData, Bundle resultExtras, boolean resultAbort,
13015 boolean explicit) {
13016 if (mOrderedBroadcasts.size() == 0) {
13017 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013018 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013019 }
13020 return false;
13021 }
13022 BroadcastRecord r = mOrderedBroadcasts.get(0);
13023 if (r.receiver == null) {
13024 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013025 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013026 }
13027 return false;
13028 }
13029 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013030 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013031 return false;
13032 }
13033 int state = r.state;
13034 r.state = r.IDLE;
13035 if (state == r.IDLE) {
13036 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013037 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013038 }
13039 }
13040 r.receiver = null;
13041 r.intent.setComponent(null);
13042 if (r.curApp != null) {
13043 r.curApp.curReceiver = null;
13044 }
13045 if (r.curFilter != null) {
13046 r.curFilter.receiverList.curBroadcast = null;
13047 }
13048 r.curFilter = null;
13049 r.curApp = null;
13050 r.curComponent = null;
13051 r.curReceiver = null;
13052 mPendingBroadcast = null;
13053
13054 r.resultCode = resultCode;
13055 r.resultData = resultData;
13056 r.resultExtras = resultExtras;
13057 r.resultAbort = resultAbort;
13058
13059 // We will process the next receiver right now if this is finishing
13060 // an app receiver (which is always asynchronous) or after we have
13061 // come back from calling a receiver.
13062 return state == BroadcastRecord.APP_RECEIVE
13063 || state == BroadcastRecord.CALL_DONE_RECEIVE;
13064 }
13065
13066 public void finishReceiver(IBinder who, int resultCode, String resultData,
13067 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013068 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013069
13070 // Refuse possible leaked file descriptors
13071 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
13072 throw new IllegalArgumentException("File descriptors passed in Bundle");
13073 }
13074
13075 boolean doNext;
13076
13077 final long origId = Binder.clearCallingIdentity();
13078
13079 synchronized(this) {
13080 doNext = finishReceiverLocked(
13081 who, resultCode, resultData, resultExtras, resultAbort, true);
13082 }
13083
13084 if (doNext) {
13085 processNextBroadcast(false);
13086 }
13087 trimApplications();
13088
13089 Binder.restoreCallingIdentity(origId);
13090 }
13091
13092 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
13093 if (r.nextReceiver > 0) {
13094 Object curReceiver = r.receivers.get(r.nextReceiver-1);
13095 if (curReceiver instanceof BroadcastFilter) {
13096 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080013097 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013098 System.identityHashCode(r),
13099 r.intent.getAction(),
13100 r.nextReceiver - 1,
13101 System.identityHashCode(bf));
13102 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080013103 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013104 System.identityHashCode(r),
13105 r.intent.getAction(),
13106 r.nextReceiver - 1,
13107 ((ResolveInfo)curReceiver).toString());
13108 }
13109 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013110 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013111 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013112 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013113 System.identityHashCode(r),
13114 r.intent.getAction(),
13115 r.nextReceiver,
13116 "NONE");
13117 }
13118 }
13119
13120 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013121 ProcessRecord app = null;
13122 String anrMessage = null;
13123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013124 synchronized (this) {
13125 if (mOrderedBroadcasts.size() == 0) {
13126 return;
13127 }
13128 long now = SystemClock.uptimeMillis();
13129 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013130 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013131 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013132 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013133 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013134 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013135 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013136 return;
13137 }
13138
Joe Onorato8a9b2202010-02-26 18:56:32 -080013139 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013140 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013141 r.anrCount++;
13142
13143 // Current receiver has passed its expiration date.
13144 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013145 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013146 return;
13147 }
13148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013149 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013150 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013151 logBroadcastReceiverDiscard(r);
13152 if (curReceiver instanceof BroadcastFilter) {
13153 BroadcastFilter bf = (BroadcastFilter)curReceiver;
13154 if (bf.receiverList.pid != 0
13155 && bf.receiverList.pid != MY_PID) {
13156 synchronized (this.mPidsSelfLocked) {
13157 app = this.mPidsSelfLocked.get(
13158 bf.receiverList.pid);
13159 }
13160 }
13161 } else {
13162 app = r.curApp;
13163 }
13164
13165 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013166 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013167 }
13168
13169 if (mPendingBroadcast == r) {
13170 mPendingBroadcast = null;
13171 }
13172
13173 // Move on to the next receiver.
13174 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13175 r.resultExtras, r.resultAbort, true);
13176 scheduleBroadcastsLocked();
13177 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070013178
13179 if (anrMessage != null) {
13180 appNotResponding(app, null, null, anrMessage);
13181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013182 }
13183
13184 private final void processCurBroadcastLocked(BroadcastRecord r,
13185 ProcessRecord app) throws RemoteException {
13186 if (app.thread == null) {
13187 throw new RemoteException();
13188 }
13189 r.receiver = app.thread.asBinder();
13190 r.curApp = app;
13191 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013192 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013193
13194 // Tell the application to launch this receiver.
13195 r.intent.setComponent(r.curComponent);
13196
13197 boolean started = false;
13198 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013199 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013200 "Delivering to component " + r.curComponent
13201 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070013202 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
13204 r.resultCode, r.resultData, r.resultExtras, r.ordered);
13205 started = true;
13206 } finally {
13207 if (!started) {
13208 r.receiver = null;
13209 r.curApp = null;
13210 app.curReceiver = null;
13211 }
13212 }
13213
13214 }
13215
13216 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013217 Intent intent, int resultCode, String data, Bundle extras,
13218 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013219 if (app != null && app.thread != null) {
13220 // If we have an app thread, do the call through that so it is
13221 // correctly ordered with other one-way calls.
13222 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013223 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013224 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013225 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013226 }
13227 }
13228
13229 private final void deliverToRegisteredReceiver(BroadcastRecord r,
13230 BroadcastFilter filter, boolean ordered) {
13231 boolean skip = false;
13232 if (filter.requiredPermission != null) {
13233 int perm = checkComponentPermission(filter.requiredPermission,
13234 r.callingPid, r.callingUid, -1);
13235 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013236 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013237 + r.intent.toString()
13238 + " from " + r.callerPackage + " (pid="
13239 + r.callingPid + ", uid=" + r.callingUid + ")"
13240 + " requires " + filter.requiredPermission
13241 + " due to registered receiver " + filter);
13242 skip = true;
13243 }
13244 }
13245 if (r.requiredPermission != null) {
13246 int perm = checkComponentPermission(r.requiredPermission,
13247 filter.receiverList.pid, filter.receiverList.uid, -1);
13248 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013249 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013250 + r.intent.toString()
13251 + " to " + filter.receiverList.app
13252 + " (pid=" + filter.receiverList.pid
13253 + ", uid=" + filter.receiverList.uid + ")"
13254 + " requires " + r.requiredPermission
13255 + " due to sender " + r.callerPackage
13256 + " (uid " + r.callingUid + ")");
13257 skip = true;
13258 }
13259 }
13260
13261 if (!skip) {
13262 // If this is not being sent as an ordered broadcast, then we
13263 // don't want to touch the fields that keep track of the current
13264 // state of ordered broadcasts.
13265 if (ordered) {
13266 r.receiver = filter.receiverList.receiver.asBinder();
13267 r.curFilter = filter;
13268 filter.receiverList.curBroadcast = r;
13269 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013270 if (filter.receiverList.app != null) {
13271 // Bump hosting application to no longer be in background
13272 // scheduling class. Note that we can't do that if there
13273 // isn't an app... but we can only be in that case for
13274 // things that directly call the IActivityManager API, which
13275 // are already core system stuff so don't matter for this.
13276 r.curApp = filter.receiverList.app;
13277 filter.receiverList.app.curReceiver = r;
13278 updateOomAdjLocked();
13279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013280 }
13281 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013282 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013283 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013284 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013285 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013286 }
13287 performReceive(filter.receiverList.app, filter.receiverList.receiver,
13288 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080013289 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013290 if (ordered) {
13291 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13292 }
13293 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013294 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013295 if (ordered) {
13296 r.receiver = null;
13297 r.curFilter = null;
13298 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013299 if (filter.receiverList.app != null) {
13300 filter.receiverList.app.curReceiver = null;
13301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013302 }
13303 }
13304 }
13305 }
13306
Dianne Hackborn12527f92009-11-11 17:39:50 -080013307 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13308 if (r.callingUid < 0) {
13309 // This was from a registerReceiver() call; ignore it.
13310 return;
13311 }
13312 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13313 MAX_BROADCAST_HISTORY-1);
13314 r.finishTime = SystemClock.uptimeMillis();
13315 mBroadcastHistory[0] = r;
13316 }
13317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013318 private final void processNextBroadcast(boolean fromMsg) {
13319 synchronized(this) {
13320 BroadcastRecord r;
13321
Joe Onorato8a9b2202010-02-26 18:56:32 -080013322 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013323 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013324 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013325
13326 updateCpuStats();
13327
13328 if (fromMsg) {
13329 mBroadcastsScheduled = false;
13330 }
13331
13332 // First, deliver any non-serialized broadcasts right away.
13333 while (mParallelBroadcasts.size() > 0) {
13334 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013335 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013336 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013337 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013338 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013339 for (int i=0; i<N; i++) {
13340 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013341 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013342 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013343 + target + ": " + r);
13344 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
13345 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013346 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013347 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013348 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013349 }
13350
13351 // Now take care of the next serialized one...
13352
13353 // If we are waiting for a process to come up to handle the next
13354 // broadcast, then do nothing at this point. Just in case, we
13355 // check that the process we're waiting for still exists.
13356 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013357 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013358 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013359 + mPendingBroadcast.curApp);
13360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013361
13362 boolean isDead;
13363 synchronized (mPidsSelfLocked) {
13364 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13365 }
13366 if (!isDead) {
13367 // It's still alive, so keep waiting
13368 return;
13369 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013370 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013371 + " died before responding to broadcast");
13372 mPendingBroadcast = null;
13373 }
13374 }
13375
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013376 boolean looped = false;
13377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013378 do {
13379 if (mOrderedBroadcasts.size() == 0) {
13380 // No more broadcasts pending, so all done!
13381 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013382 if (looped) {
13383 // If we had finished the last ordered broadcast, then
13384 // make sure all processes have correct oom and sched
13385 // adjustments.
13386 updateOomAdjLocked();
13387 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013388 return;
13389 }
13390 r = mOrderedBroadcasts.get(0);
13391 boolean forceReceive = false;
13392
13393 // Ensure that even if something goes awry with the timeout
13394 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013395 // and continue to make progress.
13396 //
13397 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
13398 // receivers don't get executed with with timeouts. They're intended for
13399 // one time heavy lifting after system upgrades and can take
13400 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013401 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013402 if (mSystemReady && r.dispatchTime > 0) {
13403 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013404 if ((numReceivers > 0) &&
13405 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013406 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013407 + " now=" + now
13408 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013409 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013410 + " intent=" + r.intent
13411 + " numReceivers=" + numReceivers
13412 + " nextReceiver=" + r.nextReceiver
13413 + " state=" + r.state);
13414 broadcastTimeout(); // forcibly finish this broadcast
13415 forceReceive = true;
13416 r.state = BroadcastRecord.IDLE;
13417 }
13418 }
13419
13420 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013421 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013422 "processNextBroadcast() called when not idle (state="
13423 + r.state + ")");
13424 return;
13425 }
13426
13427 if (r.receivers == null || r.nextReceiver >= numReceivers
13428 || r.resultAbort || forceReceive) {
13429 // No more receivers for this broadcast! Send the final
13430 // result if requested...
13431 if (r.resultTo != null) {
13432 try {
13433 if (DEBUG_BROADCAST) {
13434 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013435 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013436 + " seq=" + seq + " app=" + r.callerApp);
13437 }
13438 performReceive(r.callerApp, r.resultTo,
13439 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013440 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013441 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013442 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013443 }
13444 }
13445
Joe Onorato8a9b2202010-02-26 18:56:32 -080013446 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013447 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
13448
Joe Onorato8a9b2202010-02-26 18:56:32 -080013449 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013450 + r);
13451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013452 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013453 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013454 mOrderedBroadcasts.remove(0);
13455 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013456 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013457 continue;
13458 }
13459 } while (r == null);
13460
13461 // Get the next receiver...
13462 int recIdx = r.nextReceiver++;
13463
13464 // Keep track of when this receiver started, and make sure there
13465 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013466 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013467 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013468 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013469
Joe Onorato8a9b2202010-02-26 18:56:32 -080013470 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013471 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013472 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013473 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080013474 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013475 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013476 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013477 }
13478
13479 Object nextReceiver = r.receivers.get(recIdx);
13480 if (nextReceiver instanceof BroadcastFilter) {
13481 // Simple case: this is a registered receiver who gets
13482 // a direct call.
13483 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013484 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013485 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013486 + filter + ": " + r);
13487 deliverToRegisteredReceiver(r, filter, r.ordered);
13488 if (r.receiver == null || !r.ordered) {
13489 // The receiver has already finished, so schedule to
13490 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013491 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13492 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013493 r.state = BroadcastRecord.IDLE;
13494 scheduleBroadcastsLocked();
13495 }
13496 return;
13497 }
13498
13499 // Hard case: need to instantiate the receiver, possibly
13500 // starting its application process to host it.
13501
13502 ResolveInfo info =
13503 (ResolveInfo)nextReceiver;
13504
13505 boolean skip = false;
13506 int perm = checkComponentPermission(info.activityInfo.permission,
13507 r.callingPid, r.callingUid,
13508 info.activityInfo.exported
13509 ? -1 : info.activityInfo.applicationInfo.uid);
13510 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013511 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013512 + r.intent.toString()
13513 + " from " + r.callerPackage + " (pid=" + r.callingPid
13514 + ", uid=" + r.callingUid + ")"
13515 + " requires " + info.activityInfo.permission
13516 + " due to receiver " + info.activityInfo.packageName
13517 + "/" + info.activityInfo.name);
13518 skip = true;
13519 }
13520 if (r.callingUid != Process.SYSTEM_UID &&
13521 r.requiredPermission != null) {
13522 try {
13523 perm = ActivityThread.getPackageManager().
13524 checkPermission(r.requiredPermission,
13525 info.activityInfo.applicationInfo.packageName);
13526 } catch (RemoteException e) {
13527 perm = PackageManager.PERMISSION_DENIED;
13528 }
13529 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013530 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013531 + r.intent + " to "
13532 + info.activityInfo.applicationInfo.packageName
13533 + " requires " + r.requiredPermission
13534 + " due to sender " + r.callerPackage
13535 + " (uid " + r.callingUid + ")");
13536 skip = true;
13537 }
13538 }
13539 if (r.curApp != null && r.curApp.crashing) {
13540 // If the target process is crashing, just skip it.
13541 skip = true;
13542 }
13543
13544 if (skip) {
13545 r.receiver = null;
13546 r.curFilter = null;
13547 r.state = BroadcastRecord.IDLE;
13548 scheduleBroadcastsLocked();
13549 return;
13550 }
13551
13552 r.state = BroadcastRecord.APP_RECEIVE;
13553 String targetProcess = info.activityInfo.processName;
13554 r.curComponent = new ComponentName(
13555 info.activityInfo.applicationInfo.packageName,
13556 info.activityInfo.name);
13557 r.curReceiver = info.activityInfo;
13558
13559 // Is this receiver's application already running?
13560 ProcessRecord app = getProcessRecordLocked(targetProcess,
13561 info.activityInfo.applicationInfo.uid);
13562 if (app != null && app.thread != null) {
13563 try {
13564 processCurBroadcastLocked(r, app);
13565 return;
13566 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013567 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013568 + r.curComponent, e);
13569 }
13570
13571 // If a dead object exception was thrown -- fall through to
13572 // restart the application.
13573 }
13574
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013575 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013576 if ((r.curApp=startProcessLocked(targetProcess,
13577 info.activityInfo.applicationInfo, true,
13578 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013579 "broadcast", r.curComponent,
13580 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13581 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013582 // Ah, this recipient is unavailable. Finish it if necessary,
13583 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013584 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013585 + info.activityInfo.applicationInfo.packageName + "/"
13586 + info.activityInfo.applicationInfo.uid + " for broadcast "
13587 + r.intent + ": process is bad");
13588 logBroadcastReceiverDiscard(r);
13589 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13590 r.resultExtras, r.resultAbort, true);
13591 scheduleBroadcastsLocked();
13592 r.state = BroadcastRecord.IDLE;
13593 return;
13594 }
13595
13596 mPendingBroadcast = r;
13597 }
13598 }
13599
13600 // =========================================================
13601 // INSTRUMENTATION
13602 // =========================================================
13603
13604 public boolean startInstrumentation(ComponentName className,
13605 String profileFile, int flags, Bundle arguments,
13606 IInstrumentationWatcher watcher) {
13607 // Refuse possible leaked file descriptors
13608 if (arguments != null && arguments.hasFileDescriptors()) {
13609 throw new IllegalArgumentException("File descriptors passed in Bundle");
13610 }
13611
13612 synchronized(this) {
13613 InstrumentationInfo ii = null;
13614 ApplicationInfo ai = null;
13615 try {
13616 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013617 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013618 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013619 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013620 } catch (PackageManager.NameNotFoundException e) {
13621 }
13622 if (ii == null) {
13623 reportStartInstrumentationFailure(watcher, className,
13624 "Unable to find instrumentation info for: " + className);
13625 return false;
13626 }
13627 if (ai == null) {
13628 reportStartInstrumentationFailure(watcher, className,
13629 "Unable to find instrumentation target package: " + ii.targetPackage);
13630 return false;
13631 }
13632
13633 int match = mContext.getPackageManager().checkSignatures(
13634 ii.targetPackage, ii.packageName);
13635 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13636 String msg = "Permission Denial: starting instrumentation "
13637 + className + " from pid="
13638 + Binder.getCallingPid()
13639 + ", uid=" + Binder.getCallingPid()
13640 + " not allowed because package " + ii.packageName
13641 + " does not have a signature matching the target "
13642 + ii.targetPackage;
13643 reportStartInstrumentationFailure(watcher, className, msg);
13644 throw new SecurityException(msg);
13645 }
13646
13647 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013648 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013649 ProcessRecord app = addAppLocked(ai);
13650 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013651 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013652 app.instrumentationProfileFile = profileFile;
13653 app.instrumentationArguments = arguments;
13654 app.instrumentationWatcher = watcher;
13655 app.instrumentationResultClass = className;
13656 Binder.restoreCallingIdentity(origId);
13657 }
13658
13659 return true;
13660 }
13661
13662 /**
13663 * Report errors that occur while attempting to start Instrumentation. Always writes the
13664 * error to the logs, but if somebody is watching, send the report there too. This enables
13665 * the "am" command to report errors with more information.
13666 *
13667 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13668 * @param cn The component name of the instrumentation.
13669 * @param report The error report.
13670 */
13671 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13672 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013673 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013674 try {
13675 if (watcher != null) {
13676 Bundle results = new Bundle();
13677 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13678 results.putString("Error", report);
13679 watcher.instrumentationStatus(cn, -1, results);
13680 }
13681 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013682 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013683 }
13684 }
13685
13686 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13687 if (app.instrumentationWatcher != null) {
13688 try {
13689 // NOTE: IInstrumentationWatcher *must* be oneway here
13690 app.instrumentationWatcher.instrumentationFinished(
13691 app.instrumentationClass,
13692 resultCode,
13693 results);
13694 } catch (RemoteException e) {
13695 }
13696 }
13697 app.instrumentationWatcher = null;
13698 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013699 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013700 app.instrumentationProfileFile = null;
13701 app.instrumentationArguments = null;
13702
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080013703 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013704 }
13705
13706 public void finishInstrumentation(IApplicationThread target,
13707 int resultCode, Bundle results) {
13708 // Refuse possible leaked file descriptors
13709 if (results != null && results.hasFileDescriptors()) {
13710 throw new IllegalArgumentException("File descriptors passed in Intent");
13711 }
13712
13713 synchronized(this) {
13714 ProcessRecord app = getRecordForAppLocked(target);
13715 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013716 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013717 return;
13718 }
13719 final long origId = Binder.clearCallingIdentity();
13720 finishInstrumentationLocked(app, resultCode, results);
13721 Binder.restoreCallingIdentity(origId);
13722 }
13723 }
13724
13725 // =========================================================
13726 // CONFIGURATION
13727 // =========================================================
13728
13729 public ConfigurationInfo getDeviceConfigurationInfo() {
13730 ConfigurationInfo config = new ConfigurationInfo();
13731 synchronized (this) {
13732 config.reqTouchScreen = mConfiguration.touchscreen;
13733 config.reqKeyboardType = mConfiguration.keyboard;
13734 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013735 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13736 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013737 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13738 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013739 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13740 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013741 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13742 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013743 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013744 }
13745 return config;
13746 }
13747
13748 public Configuration getConfiguration() {
13749 Configuration ci;
13750 synchronized(this) {
13751 ci = new Configuration(mConfiguration);
13752 }
13753 return ci;
13754 }
13755
13756 public void updateConfiguration(Configuration values) {
13757 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13758 "updateConfiguration()");
13759
13760 synchronized(this) {
13761 if (values == null && mWindowManager != null) {
13762 // sentinel: fetch the current configuration from the window manager
13763 values = mWindowManager.computeNewConfiguration();
13764 }
13765
13766 final long origId = Binder.clearCallingIdentity();
13767 updateConfigurationLocked(values, null);
13768 Binder.restoreCallingIdentity(origId);
13769 }
13770 }
13771
13772 /**
13773 * Do either or both things: (1) change the current configuration, and (2)
13774 * make sure the given activity is running with the (now) current
13775 * configuration. Returns true if the activity has been left running, or
13776 * false if <var>starting</var> is being destroyed to match the new
13777 * configuration.
13778 */
13779 public boolean updateConfigurationLocked(Configuration values,
13780 HistoryRecord starting) {
13781 int changes = 0;
13782
13783 boolean kept = true;
13784
13785 if (values != null) {
13786 Configuration newConfig = new Configuration(mConfiguration);
13787 changes = newConfig.updateFrom(values);
13788 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013789 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013790 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013791 }
13792
Doug Zongker2bec3d42009-12-04 12:52:44 -080013793 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013794
13795 if (values.locale != null) {
13796 saveLocaleLocked(values.locale,
13797 !values.locale.equals(mConfiguration.locale),
13798 values.userSetLocale);
13799 }
13800
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013801 mConfigurationSeq++;
13802 if (mConfigurationSeq <= 0) {
13803 mConfigurationSeq = 1;
13804 }
13805 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013806 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013807 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013808
13809 AttributeCache ac = AttributeCache.instance();
13810 if (ac != null) {
13811 ac.updateConfiguration(mConfiguration);
13812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013813
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013814 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
13815 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
13816 msg.obj = new Configuration(mConfiguration);
13817 mHandler.sendMessage(msg);
13818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013819
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013820 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13821 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013822 try {
13823 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013824 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013825 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013826 app.thread.scheduleConfigurationChanged(mConfiguration);
13827 }
13828 } catch (Exception e) {
13829 }
13830 }
13831 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013832 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13833 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013834 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13835 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013836 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13837 broadcastIntentLocked(null, null,
13838 new Intent(Intent.ACTION_LOCALE_CHANGED),
13839 null, null, 0, null, null,
13840 null, false, false, MY_PID, Process.SYSTEM_UID);
13841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013842 }
13843 }
13844
13845 if (changes != 0 && starting == null) {
13846 // If the configuration changed, and the caller is not already
13847 // in the process of starting an activity, then find the top
13848 // activity to check if its configuration needs to change.
13849 starting = topRunningActivityLocked(null);
13850 }
13851
13852 if (starting != null) {
13853 kept = ensureActivityConfigurationLocked(starting, changes);
13854 if (kept) {
13855 // If this didn't result in the starting activity being
13856 // destroyed, then we need to make sure at this point that all
13857 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013858 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013859 + ", ensuring others are correct.");
13860 ensureActivitiesVisibleLocked(starting, changes);
13861 }
13862 }
13863
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013864 if (values != null && mWindowManager != null) {
13865 mWindowManager.setNewConfiguration(mConfiguration);
13866 }
13867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013868 return kept;
13869 }
13870
13871 private final boolean relaunchActivityLocked(HistoryRecord r,
13872 int changes, boolean andResume) {
13873 List<ResultInfo> results = null;
13874 List<Intent> newIntents = null;
13875 if (andResume) {
13876 results = r.results;
13877 newIntents = r.newIntents;
13878 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013879 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013880 + " with results=" + results + " newIntents=" + newIntents
13881 + " andResume=" + andResume);
Doug Zongker2bec3d42009-12-04 12:52:44 -080013882 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
13883 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013884 r.task.taskId, r.shortComponentName);
13885
13886 r.startFreezingScreenLocked(r.app, 0);
13887
13888 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013889 if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013890 r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
Dianne Hackborn871ecdc2009-12-11 15:24:33 -080013891 changes, !andResume, mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013892 // Note: don't need to call pauseIfSleepingLocked() here, because
13893 // the caller will only pass in 'andResume' if this activity is
13894 // currently resumed, which implies we aren't sleeping.
13895 } catch (RemoteException e) {
13896 return false;
13897 }
13898
13899 if (andResume) {
13900 r.results = null;
13901 r.newIntents = null;
Dianne Hackborn1bcf5a82009-09-30 15:22:29 -070013902 reportResumedActivityLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013903 }
13904
13905 return true;
13906 }
13907
13908 /**
13909 * Make sure the given activity matches the current configuration. Returns
13910 * false if the activity had to be destroyed. Returns true if the
13911 * configuration is the same, or the activity will remain running as-is
13912 * for whatever reason. Ensures the HistoryRecord is updated with the
13913 * correct configuration and all other bookkeeping is handled.
13914 */
13915 private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
13916 int globalChanges) {
Dianne Hackborne2522462010-03-29 18:41:30 -070013917 if (mConfigWillChange) {
Dianne Hackbornd49258f2010-03-26 00:44:29 -070013918 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
13919 "Skipping config check (will change): " + r);
13920 return true;
13921 }
13922
Joe Onorato8a9b2202010-02-26 18:56:32 -080013923 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013924 "Ensuring correct configuration: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013925
13926 // Short circuit: if the two configurations are the exact same
13927 // object (the common case), then there is nothing to do.
13928 Configuration newConfig = mConfiguration;
13929 if (r.configuration == newConfig) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013930 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013931 "Configuration unchanged in " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013932 return true;
13933 }
13934
13935 // We don't worry about activities that are finishing.
13936 if (r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013937 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013938 "Configuration doesn't matter in finishing " + r);
13939 r.stopFreezingScreenLocked(false);
13940 return true;
13941 }
13942
13943 // Okay we now are going to make this activity have the new config.
13944 // But then we need to figure out how it needs to deal with that.
13945 Configuration oldConfig = r.configuration;
13946 r.configuration = newConfig;
13947
13948 // If the activity isn't currently running, just leave the new
13949 // configuration and it will pick that up next time it starts.
13950 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013951 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013952 "Configuration doesn't matter not running " + r);
13953 r.stopFreezingScreenLocked(false);
13954 return true;
13955 }
13956
13957 // If the activity isn't persistent, there is a chance we will
13958 // need to restart it.
13959 if (!r.persistent) {
13960
13961 // Figure out what has changed between the two configurations.
13962 int changes = oldConfig.diff(newConfig);
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013963 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013964 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013965 + Integer.toHexString(changes) + ", handles=0x"
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013966 + Integer.toHexString(r.info.configChanges)
13967 + ", newConfig=" + newConfig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013968 }
13969 if ((changes&(~r.info.configChanges)) != 0) {
13970 // Aha, the activity isn't handling the change, so DIE DIE DIE.
13971 r.configChangeFlags |= changes;
13972 r.startFreezingScreenLocked(r.app, globalChanges);
13973 if (r.app == null || r.app.thread == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013974 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013975 "Switch is destroying non-running " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013976 destroyActivityLocked(r, true);
13977 } else if (r.state == ActivityState.PAUSING) {
13978 // A little annoying: we are waiting for this activity to
13979 // finish pausing. Let's not do anything now, but just
13980 // flag that it needs to be restarted when done pausing.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013981 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013982 "Switch is skipping already pausing " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013983 r.configDestroy = true;
13984 return true;
13985 } else if (r.state == ActivityState.RESUMED) {
13986 // Try to optimize this case: the configuration is changing
13987 // and we need to restart the top, resumed activity.
13988 // Instead of doing the normal handshaking, just say
13989 // "restart!".
Joe Onorato8a9b2202010-02-26 18:56:32 -080013990 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013991 "Switch is restarting resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013992 relaunchActivityLocked(r, r.configChangeFlags, true);
13993 r.configChangeFlags = 0;
13994 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013995 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013996 "Switch is restarting non-resumed " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013997 relaunchActivityLocked(r, r.configChangeFlags, false);
13998 r.configChangeFlags = 0;
13999 }
14000
14001 // All done... tell the caller we weren't able to keep this
14002 // activity around.
14003 return false;
14004 }
14005 }
14006
14007 // Default case: the activity can handle this new configuration, so
14008 // hand it over. Note that we don't need to give it the new
14009 // configuration, since we always send configuration changes to all
14010 // process when they happen so it can just use whatever configuration
14011 // it last got.
14012 if (r.app != null && r.app.thread != null) {
14013 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014014 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014015 r.app.thread.scheduleActivityConfigurationChanged(r);
14016 } catch (RemoteException e) {
14017 // If process died, whatever.
14018 }
14019 }
14020 r.stopFreezingScreenLocked(false);
14021
14022 return true;
14023 }
14024
14025 /**
14026 * Save the locale. You must be inside a synchronized (this) block.
14027 */
14028 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
14029 if(isDiff) {
14030 SystemProperties.set("user.language", l.getLanguage());
14031 SystemProperties.set("user.region", l.getCountry());
14032 }
14033
14034 if(isPersist) {
14035 SystemProperties.set("persist.sys.language", l.getLanguage());
14036 SystemProperties.set("persist.sys.country", l.getCountry());
14037 SystemProperties.set("persist.sys.localevar", l.getVariant());
14038 }
14039 }
14040
14041 // =========================================================
14042 // LIFETIME MANAGEMENT
14043 // =========================================================
14044
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014045 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
14046 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014047 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014048 // This adjustment has already been computed. If we are calling
14049 // from the top, we may have already computed our adjustment with
14050 // an earlier hidden adjustment that isn't really for us... if
14051 // so, use the new hidden adjustment.
14052 if (!recursed && app.hidden) {
14053 app.curAdj = hiddenAdj;
14054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014055 return app.curAdj;
14056 }
14057
14058 if (app.thread == null) {
14059 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014060 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014061 return (app.curAdj=EMPTY_APP_ADJ);
14062 }
14063
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014064 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
14065 // The max adjustment doesn't allow this app to be anything
14066 // below foreground, so it is not worth doing work for it.
14067 app.adjType = "fixed";
14068 app.adjSeq = mAdjSeq;
14069 app.curRawAdj = app.maxAdj;
14070 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
14071 return (app.curAdj=app.maxAdj);
14072 }
14073
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014074 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014075 app.adjSource = null;
14076 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014077 app.empty = false;
14078 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014079
The Android Open Source Project4df24232009-03-05 14:34:35 -080014080 // Determine the importance of the process, starting with most
14081 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014082 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014083 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014084 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014085 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014086 // The last app on the list is the foreground app.
14087 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014088 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014089 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014090 } else if (app.instrumentationClass != null) {
14091 // Don't want to kill running instrumentation.
14092 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014093 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014094 app.adjType = "instrumentation";
Dianne Hackborn860755f2010-06-03 18:47:52 -070014095 } else if (app == mHeavyWeightProcess) {
14096 // We don't want to kill the current heavy-weight process.
14097 adj = FOREGROUND_APP_ADJ;
14098 schedGroup = Process.THREAD_GROUP_DEFAULT;
14099 app.adjType = "heavy";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014100 } else if (app.persistentActivities > 0) {
14101 // Special persistent activities... shouldn't be used these days.
14102 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014103 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014104 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014105 } else if (app.curReceiver != null ||
14106 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
14107 // An app that is currently receiving a broadcast also
14108 // counts as being in the foreground.
14109 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014110 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014111 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014112 } else if (app.executingServices.size() > 0) {
14113 // An app that is currently executing a service callback also
14114 // counts as being in the foreground.
14115 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014116 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014117 app.adjType = "exec-service";
14118 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014119 // The user is aware of this app, so make it visible.
14120 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014121 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014122 app.adjType = "foreground-service";
14123 } else if (app.forcingToForeground != null) {
14124 // The user is aware of this app, so make it visible.
14125 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014126 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014127 app.adjType = "force-foreground";
14128 app.adjSource = app.forcingToForeground;
The Android Open Source Project4df24232009-03-05 14:34:35 -080014129 } else if (app == mHomeProcess) {
14130 // This process is hosting what we currently consider to be the
14131 // home app, so we don't want to let it go into the background.
14132 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014133 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014134 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014135 } else if ((N=app.activities.size()) != 0) {
14136 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014137 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014138 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014139 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014140 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014141 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014142 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014143 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014144 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014145 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014146 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014147 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014148 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014149 break;
14150 }
14151 }
14152 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014153 // A very not-needed process. If this is lower in the lru list,
14154 // we will push it in to the empty bucket.
14155 app.hidden = true;
14156 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014157 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014158 adj = hiddenAdj;
14159 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014160 }
14161
Joe Onorato8a9b2202010-02-26 18:56:32 -080014162 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014163
The Android Open Source Project4df24232009-03-05 14:34:35 -080014164 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014165 // there are applications dependent on our services or providers, but
14166 // this gives us a baseline and makes sure we don't get into an
14167 // infinite recursion.
14168 app.adjSeq = mAdjSeq;
14169 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014170
Christopher Tate6fa95972009-06-05 18:43:55 -070014171 if (mBackupTarget != null && app == mBackupTarget.app) {
14172 // If possible we want to avoid killing apps while they're being backed up
14173 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014174 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070014175 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014176 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014177 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070014178 }
14179 }
14180
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014181 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
14182 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014183 final long now = SystemClock.uptimeMillis();
14184 // This process is more important if the top activity is
14185 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070014186 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014187 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014188 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014189 if (s.startRequested) {
14190 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
14191 // This service has seen some activity within
14192 // recent memory, so we will keep its process ahead
14193 // of the background processes.
14194 if (adj > SECONDARY_SERVER_ADJ) {
14195 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014196 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014197 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014198 }
14199 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014200 // If we have let the service slide into the background
14201 // state, still have some text describing what it is doing
14202 // even though the service no longer has an impact.
14203 if (adj > SECONDARY_SERVER_ADJ) {
14204 app.adjType = "started-bg-services";
14205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014206 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014207 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
14208 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014209 Iterator<ConnectionRecord> kt
14210 = s.connections.values().iterator();
14211 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14212 // XXX should compute this based on the max of
14213 // all connected clients.
14214 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014215 if (cr.binding.client == app) {
14216 // Binding to ourself is not interesting.
14217 continue;
14218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014219 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
14220 ProcessRecord client = cr.binding.client;
14221 int myHiddenAdj = hiddenAdj;
14222 if (myHiddenAdj > client.hiddenAdj) {
14223 if (client.hiddenAdj > VISIBLE_APP_ADJ) {
14224 myHiddenAdj = client.hiddenAdj;
14225 } else {
14226 myHiddenAdj = VISIBLE_APP_ADJ;
14227 }
14228 }
14229 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014230 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014231 if (adj > clientAdj) {
14232 adj = clientAdj > VISIBLE_APP_ADJ
14233 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014234 if (!client.hidden) {
14235 app.hidden = false;
14236 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014237 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014238 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14239 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014240 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014241 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014242 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014243 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14244 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14245 schedGroup = Process.THREAD_GROUP_DEFAULT;
14246 }
14247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014248 }
14249 HistoryRecord a = cr.activity;
14250 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014251 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014252 //}
14253 if (a != null && adj > FOREGROUND_APP_ADJ &&
14254 (a.state == ActivityState.RESUMED
14255 || a.state == ActivityState.PAUSING)) {
14256 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014257 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014258 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014259 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014260 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14261 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014262 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014263 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014264 }
14265 }
14266 }
14267 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014268
14269 // Finally, f this process has active services running in it, we
14270 // would like to avoid killing it unless it would prevent the current
14271 // application from running. By default we put the process in
14272 // with the rest of the background processes; as we scan through
14273 // its services we may bump it up from there.
14274 if (adj > hiddenAdj) {
14275 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014276 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014277 app.adjType = "bg-services";
14278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014279 }
14280
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014281 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
14282 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014283 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014284 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
14285 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014286 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014287 if (cpr.clients.size() != 0) {
14288 Iterator<ProcessRecord> kt = cpr.clients.iterator();
14289 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
14290 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014291 if (client == app) {
14292 // Being our own client is not interesting.
14293 continue;
14294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014295 int myHiddenAdj = hiddenAdj;
14296 if (myHiddenAdj > client.hiddenAdj) {
14297 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
14298 myHiddenAdj = client.hiddenAdj;
14299 } else {
14300 myHiddenAdj = FOREGROUND_APP_ADJ;
14301 }
14302 }
14303 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014304 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014305 if (adj > clientAdj) {
14306 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014307 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014308 if (!client.hidden) {
14309 app.hidden = false;
14310 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014311 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014312 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14313 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014314 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014315 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014316 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014317 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14318 schedGroup = Process.THREAD_GROUP_DEFAULT;
14319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014320 }
14321 }
14322 // If the provider has external (non-framework) process
14323 // dependencies, ensure that its adjustment is at least
14324 // FOREGROUND_APP_ADJ.
14325 if (cpr.externals != 0) {
14326 if (adj > FOREGROUND_APP_ADJ) {
14327 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014328 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014329 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014330 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014331 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014332 }
14333 }
14334 }
14335 }
14336
14337 app.curRawAdj = adj;
14338
Joe Onorato8a9b2202010-02-26 18:56:32 -080014339 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014340 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14341 if (adj > app.maxAdj) {
14342 adj = app.maxAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014343 if (app.maxAdj <= VISIBLE_APP_ADJ) {
14344 schedGroup = Process.THREAD_GROUP_DEFAULT;
14345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014346 }
14347
14348 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014349 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014351 return adj;
14352 }
14353
14354 /**
14355 * Ask a given process to GC right now.
14356 */
14357 final void performAppGcLocked(ProcessRecord app) {
14358 try {
14359 app.lastRequestedGc = SystemClock.uptimeMillis();
14360 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014361 if (app.reportLowMemory) {
14362 app.reportLowMemory = false;
14363 app.thread.scheduleLowMemory();
14364 } else {
14365 app.thread.processInBackground();
14366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014367 }
14368 } catch (Exception e) {
14369 // whatever.
14370 }
14371 }
14372
14373 /**
14374 * Returns true if things are idle enough to perform GCs.
14375 */
Josh Bartel7f208742010-02-25 11:01:44 -060014376 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014377 return mParallelBroadcasts.size() == 0
14378 && mOrderedBroadcasts.size() == 0
14379 && (mSleeping || (mResumedActivity != null &&
14380 mResumedActivity.idle));
14381 }
14382
14383 /**
14384 * Perform GCs on all processes that are waiting for it, but only
14385 * if things are idle.
14386 */
14387 final void performAppGcsLocked() {
14388 final int N = mProcessesToGc.size();
14389 if (N <= 0) {
14390 return;
14391 }
Josh Bartel7f208742010-02-25 11:01:44 -060014392 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014393 while (mProcessesToGc.size() > 0) {
14394 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014395 if (proc.curRawAdj > VISIBLE_APP_ADJ || proc.reportLowMemory) {
14396 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14397 <= SystemClock.uptimeMillis()) {
14398 // To avoid spamming the system, we will GC processes one
14399 // at a time, waiting a few seconds between each.
14400 performAppGcLocked(proc);
14401 scheduleAppGcsLocked();
14402 return;
14403 } else {
14404 // It hasn't been long enough since we last GCed this
14405 // process... put it in the list to wait for its time.
14406 addProcessToGcListLocked(proc);
14407 break;
14408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014409 }
14410 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014411
14412 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014413 }
14414 }
14415
14416 /**
14417 * If all looks good, perform GCs on all processes waiting for them.
14418 */
14419 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014420 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014421 performAppGcsLocked();
14422 return;
14423 }
14424 // Still not idle, wait some more.
14425 scheduleAppGcsLocked();
14426 }
14427
14428 /**
14429 * Schedule the execution of all pending app GCs.
14430 */
14431 final void scheduleAppGcsLocked() {
14432 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014433
14434 if (mProcessesToGc.size() > 0) {
14435 // Schedule a GC for the time to the next process.
14436 ProcessRecord proc = mProcessesToGc.get(0);
14437 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14438
14439 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
14440 long now = SystemClock.uptimeMillis();
14441 if (when < (now+GC_TIMEOUT)) {
14442 when = now + GC_TIMEOUT;
14443 }
14444 mHandler.sendMessageAtTime(msg, when);
14445 }
14446 }
14447
14448 /**
14449 * Add a process to the array of processes waiting to be GCed. Keeps the
14450 * list in sorted order by the last GC time. The process can't already be
14451 * on the list.
14452 */
14453 final void addProcessToGcListLocked(ProcessRecord proc) {
14454 boolean added = false;
14455 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14456 if (mProcessesToGc.get(i).lastRequestedGc <
14457 proc.lastRequestedGc) {
14458 added = true;
14459 mProcessesToGc.add(i+1, proc);
14460 break;
14461 }
14462 }
14463 if (!added) {
14464 mProcessesToGc.add(0, proc);
14465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014466 }
14467
14468 /**
14469 * Set up to ask a process to GC itself. This will either do it
14470 * immediately, or put it on the list of processes to gc the next
14471 * time things are idle.
14472 */
14473 final void scheduleAppGcLocked(ProcessRecord app) {
14474 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014475 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014476 return;
14477 }
14478 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014479 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014480 scheduleAppGcsLocked();
14481 }
14482 }
14483
14484 private final boolean updateOomAdjLocked(
14485 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
14486 app.hiddenAdj = hiddenAdj;
14487
14488 if (app.thread == null) {
14489 return true;
14490 }
14491
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014492 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014493
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014494 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014495 if (app.curRawAdj != app.setRawAdj) {
14496 if (app.curRawAdj > FOREGROUND_APP_ADJ
14497 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
14498 // If this app is transitioning from foreground to
14499 // non-foreground, have it do a gc.
14500 scheduleAppGcLocked(app);
14501 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
14502 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
14503 // Likewise do a gc when an app is moving in to the
14504 // background (such as a service stopping).
14505 scheduleAppGcLocked(app);
14506 }
14507 app.setRawAdj = app.curRawAdj;
14508 }
14509 if (adj != app.setAdj) {
14510 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014511 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014512 TAG, "Set app " + app.processName +
14513 " oom adj to " + adj);
14514 app.setAdj = adj;
14515 } else {
14516 return false;
14517 }
14518 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014519 if (app.setSchedGroup != app.curSchedGroup) {
14520 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014521 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014522 "Setting process group of " + app.processName
14523 + " to " + app.curSchedGroup);
14524 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070014525 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014526 try {
14527 Process.setProcessGroup(app.pid, app.curSchedGroup);
14528 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014529 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014530 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070014531 e.printStackTrace();
14532 } finally {
14533 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014534 }
14535 }
14536 if (false) {
14537 if (app.thread != null) {
14538 try {
14539 app.thread.setSchedulingGroup(app.curSchedGroup);
14540 } catch (RemoteException e) {
14541 }
14542 }
14543 }
14544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014545 }
14546
14547 return true;
14548 }
14549
14550 private final HistoryRecord resumedAppLocked() {
14551 HistoryRecord resumedActivity = mResumedActivity;
14552 if (resumedActivity == null || resumedActivity.app == null) {
14553 resumedActivity = mPausingActivity;
14554 if (resumedActivity == null || resumedActivity.app == null) {
14555 resumedActivity = topRunningActivityLocked(null);
14556 }
14557 }
14558 return resumedActivity;
14559 }
14560
14561 private final boolean updateOomAdjLocked(ProcessRecord app) {
14562 final HistoryRecord TOP_ACT = resumedAppLocked();
14563 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14564 int curAdj = app.curAdj;
14565 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14566 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14567
14568 mAdjSeq++;
14569
14570 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
14571 if (res) {
14572 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
14573 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
14574 if (nowHidden != wasHidden) {
14575 // Changed to/from hidden state, so apps after it in the LRU
14576 // list may also be changed.
14577 updateOomAdjLocked();
14578 }
14579 }
14580 return res;
14581 }
14582
14583 private final boolean updateOomAdjLocked() {
14584 boolean didOomAdj = true;
14585 final HistoryRecord TOP_ACT = resumedAppLocked();
14586 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14587
14588 if (false) {
14589 RuntimeException e = new RuntimeException();
14590 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014591 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014592 }
14593
14594 mAdjSeq++;
14595
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014596 // Let's determine how many processes we have running vs.
14597 // how many slots we have for background processes; we may want
14598 // to put multiple processes in a slot of there are enough of
14599 // them.
14600 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
14601 int factor = (mLruProcesses.size()-4)/numSlots;
14602 if (factor < 1) factor = 1;
14603 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014604 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014606 // First try updating the OOM adjustment for each of the
14607 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014608 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014609 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
14610 while (i > 0) {
14611 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014612 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014613 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014614 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014615 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014616 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014617 step++;
14618 if (step >= factor) {
14619 step = 0;
14620 curHiddenAdj++;
14621 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014622 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014623 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070014624 if (!app.killedBackground) {
14625 numHidden++;
14626 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070014627 Slog.i(TAG, "No longer want " + app.processName
14628 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014629 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14630 app.processName, app.setAdj, "too many background");
14631 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070014632 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070014633 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070014634 }
14635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014636 } else {
14637 didOomAdj = false;
14638 }
14639 }
14640
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014641 // If we return false, we will fall back on killing processes to
14642 // have a fixed limit. Do this if a limit has been requested; else
14643 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014644 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
14645 }
14646
14647 private final void trimApplications() {
14648 synchronized (this) {
14649 int i;
14650
14651 // First remove any unused application processes whose package
14652 // has been removed.
14653 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14654 final ProcessRecord app = mRemovedProcesses.get(i);
14655 if (app.activities.size() == 0
14656 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014657 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014658 TAG, "Exiting empty application process "
14659 + app.processName + " ("
14660 + (app.thread != null ? app.thread.asBinder() : null)
14661 + ")\n");
14662 if (app.pid > 0 && app.pid != MY_PID) {
14663 Process.killProcess(app.pid);
14664 } else {
14665 try {
14666 app.thread.scheduleExit();
14667 } catch (Exception e) {
14668 // Ignore exceptions.
14669 }
14670 }
14671 cleanUpApplicationRecordLocked(app, false, -1);
14672 mRemovedProcesses.remove(i);
14673
14674 if (app.persistent) {
14675 if (app.persistent) {
14676 addAppLocked(app.info);
14677 }
14678 }
14679 }
14680 }
14681
14682 // Now try updating the OOM adjustment for each of the
14683 // application processes based on their current state.
14684 // If the setOomAdj() API is not supported, then go with our
14685 // back-up plan...
14686 if (!updateOomAdjLocked()) {
14687
14688 // Count how many processes are running services.
14689 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014690 for (i=mLruProcesses.size()-1; i>=0; i--) {
14691 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014692
14693 if (app.persistent || app.services.size() != 0
14694 || app.curReceiver != null
14695 || app.persistentActivities > 0) {
14696 // Don't count processes holding services against our
14697 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014698 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014699 TAG, "Not trimming app " + app + " with services: "
14700 + app.services);
14701 numServiceProcs++;
14702 }
14703 }
14704
14705 int curMaxProcs = mProcessLimit;
14706 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
14707 if (mAlwaysFinishActivities) {
14708 curMaxProcs = 1;
14709 }
14710 curMaxProcs += numServiceProcs;
14711
14712 // Quit as many processes as we can to get down to the desired
14713 // process count. First remove any processes that no longer
14714 // have activites running in them.
14715 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014716 i<mLruProcesses.size()
14717 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014718 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014719 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014720 // Quit an application only if it is not currently
14721 // running any activities.
14722 if (!app.persistent && app.activities.size() == 0
14723 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014724 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014725 TAG, "Exiting empty application process "
14726 + app.processName + " ("
14727 + (app.thread != null ? app.thread.asBinder() : null)
14728 + ")\n");
14729 if (app.pid > 0 && app.pid != MY_PID) {
14730 Process.killProcess(app.pid);
14731 } else {
14732 try {
14733 app.thread.scheduleExit();
14734 } catch (Exception e) {
14735 // Ignore exceptions.
14736 }
14737 }
14738 // todo: For now we assume the application is not buggy
14739 // or evil, and will quit as a result of our request.
14740 // Eventually we need to drive this off of the death
14741 // notification, and kill the process if it takes too long.
14742 cleanUpApplicationRecordLocked(app, false, i);
14743 i--;
14744 }
14745 }
14746
14747 // If we still have too many processes, now from the least
14748 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080014749 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014750 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014751 " of " + curMaxProcs + " processes");
14752 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014753 i<mLruProcesses.size()
14754 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014755 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014756 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014757 // Quit the application only if we have a state saved for
14758 // all of its activities.
14759 boolean canQuit = !app.persistent && app.curReceiver == null
14760 && app.services.size() == 0
14761 && app.persistentActivities == 0;
14762 int NUMA = app.activities.size();
14763 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080014764 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014765 TAG, "Looking to quit " + app.processName);
14766 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014767 HistoryRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014768 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014769 TAG, " " + r.intent.getComponent().flattenToShortString()
14770 + ": frozen=" + r.haveState + ", visible=" + r.visible);
14771 canQuit = (r.haveState || !r.stateNotNeeded)
14772 && !r.visible && r.stopped;
14773 }
14774 if (canQuit) {
14775 // Finish all of the activities, and then the app itself.
14776 for (j=0; j<NUMA; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014777 HistoryRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014778 if (!r.finishing) {
14779 destroyActivityLocked(r, false);
14780 }
14781 r.resultTo = null;
14782 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080014783 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014784 + app.processName + " ("
14785 + (app.thread != null ? app.thread.asBinder() : null)
14786 + ")\n");
14787 if (app.pid > 0 && app.pid != MY_PID) {
14788 Process.killProcess(app.pid);
14789 } else {
14790 try {
14791 app.thread.scheduleExit();
14792 } catch (Exception e) {
14793 // Ignore exceptions.
14794 }
14795 }
14796 // todo: For now we assume the application is not buggy
14797 // or evil, and will quit as a result of our request.
14798 // Eventually we need to drive this off of the death
14799 // notification, and kill the process if it takes too long.
14800 cleanUpApplicationRecordLocked(app, false, i);
14801 i--;
14802 //dump();
14803 }
14804 }
14805
14806 }
14807
14808 int curMaxActivities = MAX_ACTIVITIES;
14809 if (mAlwaysFinishActivities) {
14810 curMaxActivities = 1;
14811 }
14812
14813 // Finally, if there are too many activities now running, try to
14814 // finish as many as we can to get back down to the limit.
14815 for ( i=0;
14816 i<mLRUActivities.size()
14817 && mLRUActivities.size() > curMaxActivities;
14818 i++) {
14819 final HistoryRecord r
14820 = (HistoryRecord)mLRUActivities.get(i);
14821
14822 // We can finish this one if we have its icicle saved and
14823 // it is not persistent.
14824 if ((r.haveState || !r.stateNotNeeded) && !r.visible
14825 && r.stopped && !r.persistent && !r.finishing) {
14826 final int origSize = mLRUActivities.size();
14827 destroyActivityLocked(r, true);
14828
14829 // This will remove it from the LRU list, so keep
14830 // our index at the same value. Note that this check to
14831 // see if the size changes is just paranoia -- if
14832 // something unexpected happens, we don't want to end up
14833 // in an infinite loop.
14834 if (origSize > mLRUActivities.size()) {
14835 i--;
14836 }
14837 }
14838 }
14839 }
14840 }
14841
14842 /** This method sends the specified signal to each of the persistent apps */
14843 public void signalPersistentProcesses(int sig) throws RemoteException {
14844 if (sig != Process.SIGNAL_USR1) {
14845 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14846 }
14847
14848 synchronized (this) {
14849 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14850 != PackageManager.PERMISSION_GRANTED) {
14851 throw new SecurityException("Requires permission "
14852 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14853 }
14854
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014855 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14856 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014857 if (r.thread != null && r.persistent) {
14858 Process.sendSignal(r.pid, sig);
14859 }
14860 }
14861 }
14862 }
14863
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014864 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014865 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014866
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014867 try {
14868 synchronized (this) {
14869 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14870 // its own permission.
14871 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14872 != PackageManager.PERMISSION_GRANTED) {
14873 throw new SecurityException("Requires permission "
14874 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014875 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014876
14877 if (start && fd == null) {
14878 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014879 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014880
14881 ProcessRecord proc = null;
14882 try {
14883 int pid = Integer.parseInt(process);
14884 synchronized (mPidsSelfLocked) {
14885 proc = mPidsSelfLocked.get(pid);
14886 }
14887 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014888 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014889
14890 if (proc == null) {
14891 HashMap<String, SparseArray<ProcessRecord>> all
14892 = mProcessNames.getMap();
14893 SparseArray<ProcessRecord> procs = all.get(process);
14894 if (procs != null && procs.size() > 0) {
14895 proc = procs.valueAt(0);
14896 }
14897 }
14898
14899 if (proc == null || proc.thread == null) {
14900 throw new IllegalArgumentException("Unknown process: " + process);
14901 }
14902
14903 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
14904 if (isSecure) {
14905 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14906 throw new SecurityException("Process not debuggable: " + proc);
14907 }
14908 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014909
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014910 proc.thread.profilerControl(start, path, fd);
14911 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014912 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014913 }
14914 } catch (RemoteException e) {
14915 throw new IllegalStateException("Process disappeared");
14916 } finally {
14917 if (fd != null) {
14918 try {
14919 fd.close();
14920 } catch (IOException e) {
14921 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014922 }
14923 }
14924 }
14925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014926 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14927 public void monitor() {
14928 synchronized (this) { }
14929 }
14930}